CaiWuXiTong/tests/Unit/EcommerceFinance/DewuSettlementAccountBillsRepositoryTest.php
yueyang af10f3c972 接入聚胜算得物完整账单 (#245)
保留得物、退货退款订单和扣减其他费用明细三类渠道;增加受控幂等导入、原子替换与页面权威表查询。
2026-09-22 19:07:11 +08:00

172 lines
7.2 KiB
PHP

<?php
namespace Tests\Unit\EcommerceFinance;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\EcommerceFinance\Repositories\DewuSettlementBillRepository;
use RuntimeException;
use Tests\TestCase;
class DewuSettlementAccountBillsRepositoryTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
config([
'database.connections.business_mirror' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
],
'upstream_mirrors.connection' => 'business_mirror',
]);
DB::purge('business_mirror');
$this->createTables();
}
public function test_account_bill_page_reads_authoritative_rows_with_filters_and_totals(): void
{
$this->insertSucceededImport();
$this->insertRow('REC-INCOME', '得物一店', '交易收款', '2026-08-01 00:00:00', '100.00', '0.00', '100.00', 'M-100', 'O-100');
$this->insertRow('REC-EXPENSE', '得物一店', '退款', '2026-08-31 23:59:59', '0.00', '20.00', '-20.00', 'M-200', 'O-200');
$this->insertRow('REC-OTHER', '得物二店', '交易收款', '2026-08-15 12:00:00', '50.00', '0.00', '50.00', 'M-300', 'O-300');
$result = app(DewuSettlementBillRepository::class)->paginateAccountBills([
'store_name' => '得物一店',
'start' => '2026-08-01',
'end' => '2026-08-31',
], 'occurred_at', 'desc', 1, 10);
$this->assertSame(2, $result['total']);
$this->assertSame(100.0, $result['summary']['income']);
$this->assertSame(20.0, $result['summary']['expense']);
$this->assertSame(80.0, $result['summary']['balance']);
$this->assertSame('REC-EXPENSE', $result['data'][0]['record_code']);
$this->assertSame('M-200', $result['data'][0]['order_no']);
$this->assertSame('O-200', $result['data'][0]['payload']['online_order_no']);
$this->assertSame('退货退款订单', $result['data'][0]['payload']['channel']);
$this->assertSame('DewuTK', $result['data'][0]['payload']['source_channel']);
$this->assertSame('2026-08-31 23:59:59', $result['data'][0]['payload']['ship_return_at']);
$this->assertNull($result['data'][0]['occurred_at']);
$this->assertSame(20.0, $result['data'][0]['amount']);
$this->assertSame(-20.0, $result['data'][0]['balance']);
$filtered = app(DewuSettlementBillRepository::class)->paginateAccountBills([
'bill_item' => '退款',
'keyword' => 'O-200',
], 'record_code', 'asc', 1, 10);
$this->assertSame(1, $filtered['total']);
$this->assertSame('REC-EXPENSE', $filtered['data'][0]['record_code']);
$options = app(DewuSettlementBillRepository::class)->accountBillFilterOptions();
$this->assertSame(['得物一店', '得物二店'], $options['shops']);
$this->assertSame(['交易收款', '退款'], $options['bill_items']);
$export = iterator_to_array(app(DewuSettlementBillRepository::class)->exportAccountBills([
'bill_item' => '退款',
], 'record_code', 'asc'));
$this->assertCount(1, $export);
$this->assertSame('REC-EXPENSE', $export[0]['record_code']);
}
public function test_account_bill_page_fails_closed_until_a_successful_import_exists(): void
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('dewu_authoritative_bills_not_ready');
app(DewuSettlementBillRepository::class)->paginateAccountBills(
[],
'occurred_at',
'desc',
1,
10,
);
}
private function createTables(): void
{
$schema = Schema::connection('business_mirror');
$schema->create('dewu_settlement_bill_imports', function (Blueprint $table): void {
$table->uuid('generation')->primary();
$table->string('status', 32);
});
$schema->create('dewu_settlement_bill_rows', function (Blueprint $table): void {
$table->string('record_code', 191)->primary();
$table->string('order_no', 191)->nullable();
$table->string('online_order_no', 191)->nullable();
$table->string('custom_remark')->nullable();
$table->string('bill_item')->nullable();
$table->string('store_name')->nullable();
$table->string('order_type')->nullable();
$table->string('goods_name', 1000)->nullable();
$table->string('goods_no', 191)->nullable();
$table->string('quantity', 64)->nullable();
$table->string('channel')->nullable();
$table->string('business_type')->nullable();
$table->decimal('income_amount', 20, 2);
$table->decimal('expense_amount', 20, 2);
$table->decimal('signed_amount', 20, 2);
$table->string('online_real_store')->nullable();
$table->dateTime('order_created_at')->nullable();
$table->dateTime('paid_refunded_at')->nullable();
$table->dateTime('ship_return_at')->nullable();
$table->dateTime('bill_date');
$table->string('settle_status')->nullable();
$table->string('pay_period')->nullable();
$table->dateTime('pulled_at')->nullable();
$table->dateTime('source_updated_at')->nullable();
$table->string('source_modified_by')->nullable();
});
}
private function insertSucceededImport(): void
{
DB::connection('business_mirror')->table('dewu_settlement_bill_imports')->insert([
'generation' => '11111111-1111-1111-1111-111111111111',
'status' => 'succeeded',
]);
}
private function insertRow(
string $recordCode,
string $storeName,
string $billItem,
string $occurredAt,
string $income,
string $expense,
string $signed,
string $orderNo,
string $onlineOrderNo,
): void {
DB::connection('business_mirror')->table('dewu_settlement_bill_rows')->insert([
'record_code' => $recordCode,
'order_no' => $orderNo,
'online_order_no' => $onlineOrderNo,
'store_name' => $storeName,
'custom_remark' => '自定义备注',
'bill_item' => $billItem,
'order_type' => '普通订单',
'goods_name' => '测试商品',
'goods_no' => 'SKU-1',
'quantity' => '1',
'channel' => $expense === '0.00' ? '得物' : '退货退款订单',
'business_type' => $expense === '0.00' ? '收入' : '支出',
'income_amount' => $income,
'expense_amount' => $expense,
'signed_amount' => $signed,
'online_real_store' => $storeName,
'ship_return_at' => $occurredAt,
'bill_date' => $occurredAt,
'settle_status' => '已结算',
'pay_period' => '2026-08',
'pulled_at' => '2026-09-01 07:30:00',
'source_updated_at' => '2026-09-01 08:00:00',
'source_modified_by' => '聚胜算',
]);
}
}