129 lines
4.8 KiB
PHP
129 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Console;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
|
use Tests\Feature\FeatureTestCase;
|
|
|
|
class ImportWechatStatementTest extends FeatureTestCase
|
|
{
|
|
public function test_imports_monthly_wechat_statement_and_replaces_the_same_month(): void
|
|
{
|
|
$connection = DB::connection('business_mirror');
|
|
$connection->table('fin_accounts')->insert([
|
|
'company_name' => '朱俊祥',
|
|
'account_short' => '朱俊祥微信',
|
|
'account_type' => '个人微信',
|
|
'current_balance' => 0,
|
|
]);
|
|
$connection->table('fin_transactions')->insert([
|
|
'txn_date' => '2026-10-03',
|
|
'account_short' => '朱俊祥微信',
|
|
'detail' => '旧月份记录',
|
|
'income' => 1,
|
|
'expense' => 0,
|
|
'balance' => 101,
|
|
'source' => 'wechat-statement',
|
|
'source_value' => '朱俊祥微信',
|
|
'process_type' => '公司微信收支流水',
|
|
'row_key' => 'old-wechat-statement',
|
|
]);
|
|
$file = $this->workbook([
|
|
['日期', '简称', '收入', '支出', '余额'],
|
|
[null, '朱俊祥微信', null, null, 100],
|
|
['10/4/2026', '朱俊祥微信', 20, null, 120],
|
|
['10/5/2026', '朱俊祥微信', null, 5, 115],
|
|
]);
|
|
|
|
$this->artisan('finance-ledger:import-wechat-statement', [
|
|
'path' => $file,
|
|
'--dry-run' => true,
|
|
])->assertExitCode(0);
|
|
$this->assertDatabaseHas('fin_transactions', [
|
|
'row_key' => 'old-wechat-statement',
|
|
], 'business_mirror');
|
|
|
|
$this->artisan('finance-ledger:import-wechat-statement', [
|
|
'path' => $file,
|
|
])->assertExitCode(0);
|
|
|
|
$this->assertDatabaseMissing('fin_transactions', [
|
|
'row_key' => 'old-wechat-statement',
|
|
], 'business_mirror');
|
|
$this->assertSame(2, $connection->table('fin_transactions')
|
|
->where('source', 'wechat-statement')
|
|
->where('account_short', '朱俊祥微信')
|
|
->count());
|
|
$this->assertDatabaseHas('fin_transactions', [
|
|
'txn_date' => '2026-10-04',
|
|
'account_short' => '朱俊祥微信',
|
|
'income' => 20,
|
|
'balance' => 120,
|
|
'source' => 'wechat-statement',
|
|
], 'business_mirror');
|
|
$this->assertDatabaseHas('fin_transactions', [
|
|
'txn_date' => '2026-10-05',
|
|
'account_short' => '朱俊祥微信',
|
|
'expense' => 5,
|
|
'balance' => 115,
|
|
], 'business_mirror');
|
|
$this->assertDatabaseHas('fin_account_opening', [
|
|
'account_short' => '朱俊祥微信',
|
|
'opening_date' => '2026-10-01',
|
|
'opening_balance' => 100,
|
|
], 'business_mirror');
|
|
$this->assertDatabaseMissing('fin_daily_flows', [
|
|
'account_short' => '朱俊祥微信',
|
|
], 'business_mirror');
|
|
$this->assertSame(0.0, (float) $connection->table('fin_accounts')
|
|
->where('account_short', '朱俊祥微信')
|
|
->value('current_balance'));
|
|
}
|
|
|
|
public function test_unbalanced_wechat_statement_keeps_existing_rows(): void
|
|
{
|
|
DB::connection('business_mirror')->table('fin_accounts')->insert([
|
|
'company_name' => '朱俊祥',
|
|
'account_short' => '朱俊祥微信',
|
|
]);
|
|
DB::connection('business_mirror')->table('fin_transactions')->insert([
|
|
'txn_date' => '2026-10-03',
|
|
'account_short' => '朱俊祥微信',
|
|
'detail' => '应保留记录',
|
|
'income' => 1,
|
|
'expense' => 0,
|
|
'balance' => 101,
|
|
'source' => 'wechat-statement',
|
|
'source_value' => '朱俊祥微信',
|
|
'row_key' => 'wechat-unbalanced-existing',
|
|
]);
|
|
$file = $this->workbook([
|
|
['日期', '简称', '收入', '支出', '余额'],
|
|
[null, '朱俊祥微信', null, null, 100],
|
|
['10/4/2026', '朱俊祥微信', 20, null, 125],
|
|
]);
|
|
|
|
$this->withExceptionHandling()->artisan('finance-ledger:import-wechat-statement', [
|
|
'path' => $file,
|
|
])->assertExitCode(1);
|
|
|
|
$this->assertDatabaseHas('fin_transactions', [
|
|
'row_key' => 'wechat-unbalanced-existing',
|
|
], 'business_mirror');
|
|
}
|
|
|
|
/** @param list<list<mixed>> $rows */
|
|
private function workbook(array $rows): string
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$spreadsheet->getActiveSheet()->fromArray($rows, null, 'A1');
|
|
$path = tempnam(sys_get_temp_dir(), 'wechat-statement-') . '.xlsx';
|
|
(new Xlsx($spreadsheet))->save($path);
|
|
$spreadsheet->disconnectWorksheets();
|
|
|
|
return $path;
|
|
}
|
|
}
|