积分与余额账务系统硬切重构
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
use AKSRT\Ledger\AssetType;
|
||||
use AKSRT\Ledger\LedgerCommand;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class LedgerCommandTest extends TestCase {
|
||||
public function test_transfer_splits_principal_fee_and_net_receipt(): void {
|
||||
$command = LedgerCommand::transfer(
|
||||
'client-transfer:1:550e8400-e29b-41d4-a716-446655440000',
|
||||
'transfer',
|
||||
10,
|
||||
20,
|
||||
AssetType::BALANCE,
|
||||
1000,
|
||||
125
|
||||
);
|
||||
|
||||
self::assertSame([-875, -125, 875], array_column($command->entries, 'delta_minor'));
|
||||
self::assertSame(['transfer_out', 'fee', 'transfer_in'], array_column($command->entries, 'entry_type'));
|
||||
self::assertSame(1000, $command->metadata['gross_minor']);
|
||||
self::assertSame(125, $command->metadata['fee_minor']);
|
||||
self::assertSame(875, $command->metadata['net_minor']);
|
||||
self::assertSame(-125, array_sum(array_column($command->entries, 'delta_minor')));
|
||||
}
|
||||
|
||||
public function test_transfer_rejects_net_below_one_minor_unit(): void {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
LedgerCommand::transfer('transfer:key', 'transfer', 1, 2, AssetType::POINTS, 10, 10);
|
||||
}
|
||||
|
||||
public function test_transfer_rejects_negative_fee_before_arithmetic(): void {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
LedgerCommand::transfer('transfer:key', 'transfer', 1, 2, AssetType::POINTS, PHP_INT_MAX, -1);
|
||||
}
|
||||
|
||||
public function test_validation_returns_400_for_bad_operation_key(): void {
|
||||
$command = new LedgerCommand('bad key', 'credit', [[
|
||||
'user_id' => 1,
|
||||
'asset' => 'points',
|
||||
'delta_minor' => 1,
|
||||
'entry_type' => 'credit',
|
||||
]]);
|
||||
$error = $command->validate();
|
||||
self::assertInstanceOf(WP_Error::class, $error);
|
||||
self::assertSame('aksrt_ledger_operation_key', $error->get_error_code());
|
||||
self::assertSame(400, $error->get_error_data()['status']);
|
||||
}
|
||||
|
||||
public function test_payload_hash_is_stable_for_metadata_key_order(): void {
|
||||
$entries = [['user_id' => 1, 'asset' => 'points', 'delta_minor' => 2, 'entry_type' => 'credit']];
|
||||
$first = new LedgerCommand('stable:key', 'credit', $entries, '', '', 0, ['b' => 2, 'a' => 1]);
|
||||
$second = new LedgerCommand('stable:key', 'credit', $entries, '', '', 0, ['a' => 1, 'b' => 2]);
|
||||
self::assertSame($first->payload_hash(), $second->payload_hash());
|
||||
}
|
||||
|
||||
public function test_payload_hash_changes_with_business_payload(): void {
|
||||
$first = new LedgerCommand('stable:key', 'credit', [[
|
||||
'user_id' => 1,
|
||||
'asset' => 'points',
|
||||
'delta_minor' => 2,
|
||||
'entry_type' => 'credit',
|
||||
]]);
|
||||
$second = new LedgerCommand('stable:key', 'credit', [[
|
||||
'user_id' => 1,
|
||||
'asset' => 'points',
|
||||
'delta_minor' => 3,
|
||||
'entry_type' => 'credit',
|
||||
]]);
|
||||
self::assertNotSame($first->payload_hash(), $second->payload_hash());
|
||||
}
|
||||
|
||||
public function test_validation_rejects_empty_entries_and_invalid_asset(): void {
|
||||
$empty = new LedgerCommand('empty:key', 'credit', []);
|
||||
self::assertSame('aksrt_ledger_entries', $empty->validate()->get_error_code());
|
||||
|
||||
$invalid = new LedgerCommand('asset:key', 'credit', [[
|
||||
'user_id' => 1,
|
||||
'asset' => 'cash',
|
||||
'delta_minor' => 1,
|
||||
'entry_type' => 'credit',
|
||||
]]);
|
||||
self::assertSame('aksrt_ledger_asset', $invalid->validate()->get_error_code());
|
||||
}
|
||||
|
||||
public function test_validation_requires_integer_non_zero_entry_values(): void {
|
||||
foreach (['1', 0, PHP_INT_MIN] as $delta) {
|
||||
$command = new LedgerCommand('entry:key', 'credit', [[
|
||||
'user_id' => 1,
|
||||
'asset' => 'points',
|
||||
'delta_minor' => $delta,
|
||||
'entry_type' => 'credit',
|
||||
]]);
|
||||
self::assertSame('aksrt_ledger_entry', $command->validate()->get_error_code());
|
||||
}
|
||||
}
|
||||
|
||||
public function test_validation_rejects_negative_actor_and_invalid_entry_type(): void {
|
||||
$actor = new LedgerCommand('actor:key', 'credit', [[
|
||||
'user_id' => 1,
|
||||
'asset' => 'points',
|
||||
'delta_minor' => 1,
|
||||
'entry_type' => 'credit',
|
||||
]], '', '', -1);
|
||||
self::assertSame('aksrt_ledger_actor', $actor->validate()->get_error_code());
|
||||
|
||||
$type = new LedgerCommand('type:key', 'credit', [[
|
||||
'user_id' => 1,
|
||||
'asset' => 'points',
|
||||
'delta_minor' => 1,
|
||||
'entry_type' => 'Bad Type',
|
||||
]]);
|
||||
self::assertSame('aksrt_ledger_entry', $type->validate()->get_error_code());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user