id(); $table->string('platform', 32); $table->string('bill_item', 191); $table->string('ledger_remark', 191); $table->timestamps(); }); } protected function tearDown(): void { Cache::flush(); Schema::dropIfExists('ec_account_ledger_remarks'); parent::tearDown(); } public function test_every_account_tab_places_ledger_remark_right_after_the_store_column(): void { foreach (AccountBillColumns::map() as $tab => $definition) { $columns = $definition['columns'] ?? []; $labels = array_map(static fn (array $column): string => (string) $column[0], $columns); $storeIndex = null; foreach ($labels as $index => $label) { if (in_array($label, ['店铺', '店铺名称'], true)) { $storeIndex = $index; break; } } $this->assertNotNull($storeIndex, $tab . ' 缺少店铺列'); $this->assertSame('总账备注', $labels[$storeIndex + 1] ?? null, $tab . ' 的总账备注没有紧跟店铺列'); $this->assertSame('payload.ledger_remark', $columns[$storeIndex + 1][1] ?? null, $tab . ' 的总账备注字段不正确'); } } public function test_ledger_remark_filter_options_and_bill_items_are_scoped_per_tab(): void { $now = now(); DB::table('ec_account_ledger_remarks')->insert([ ['platform' => '京东', 'bill_item' => '货款(收)', 'ledger_remark' => '订单收入', 'created_at' => $now, 'updated_at' => $now], ['platform' => '京东', 'bill_item' => '佣金', 'ledger_remark' => '佣金', 'created_at' => $now, 'updated_at' => $now], ['platform' => '京喜', 'bill_item' => '货款(收)', 'ledger_remark' => '订单收入', 'created_at' => $now, 'updated_at' => $now], ['platform' => '淘宝', 'bill_item' => '服务费', 'ledger_remark' => '违约赔付', 'created_at' => $now, 'updated_at' => $now], ['platform' => '天猫', 'bill_item' => '服务费', 'ledger_remark' => '服务费', 'created_at' => $now, 'updated_at' => $now], ]); $map = new AccountLedgerRemarkMap(); $this->assertSame(['佣金', '订单收入'], $map->remarksForTab('jd-transactions')); $this->assertSame(['订单收入'], $map->remarksForTab('jingxi')); $this->assertSame(['货款(收)'], $map->billItemsForTab('jd-transactions', '订单收入')); $this->assertSame([], $map->billItemsForTab('jd-transactions', '不存在的备注')); // 单平台页签不做店铺名前缀限制,直接按账单项目集合过滤。 $single = $map->billItemGroupsForTab('jd-transactions', '订单收入'); $this->assertCount(1, $single); $this->assertFalse($single[0]['isDefault']); $this->assertSame([], $single[0]['prefixes']); $this->assertSame([], $single[0]['excludePrefixes']); $this->assertSame(['货款(收)'], $single[0]['items']); // 淘系支付宝同一页签混有淘宝/天猫店铺:同名账单项目在两边对应不同总账备注。 $taobao = $map->billItemGroupsForTab('taobao-alipay', '违约赔付'); $this->assertCount(1, $taobao); $this->assertSame('淘宝', $taobao[0]['platform']); $this->assertTrue($taobao[0]['isDefault']); $this->assertSame(['淘宝'], $taobao[0]['prefixes']); $this->assertContains('天猫', $taobao[0]['excludePrefixes']); $this->assertSame(['服务费'], $taobao[0]['items']); $tmall = $map->billItemGroupsForTab('taobao-alipay', '服务费'); $this->assertCount(1, $tmall); $this->assertSame('天猫', $tmall[0]['platform']); $this->assertFalse($tmall[0]['isDefault']); $this->assertSame(['天猫'], $tmall[0]['prefixes']); $this->assertSame([], $tmall[0]['excludePrefixes']); $this->assertSame(['服务费'], $tmall[0]['items']); } public function test_it_matches_platform_and_bill_item_then_decorates_rows(): void { $now = now(); DB::table('ec_account_ledger_remarks')->insert([ ['platform' => '抖音', 'bill_item' => '保费扣除', 'ledger_remark' => '运费险', 'created_at' => $now, 'updated_at' => $now], ['platform' => '天猫', 'bill_item' => '天猫佣金', 'ledger_remark' => '平台佣金', 'created_at' => $now, 'updated_at' => $now], ['platform' => '阿里巴巴', 'bill_item' => '1688大分销业务平台抽佣', 'ledger_remark' => '1688佣金', 'created_at' => $now, 'updated_at' => $now], ]); $map = new AccountLedgerRemarkMap(); $this->assertSame('运费险', $map->remark('抖音-乾廷润凯家具专卖店', '抖音', '保费扣除')); $this->assertSame('平台佣金', $map->remark('天猫-卓尔家具旗舰店', '淘宝', '天猫佣金')); $this->assertSame('平台佣金', $map->remark('没有平台前缀的店铺', '天猫', '天猫佣金')); // 1688 / 新佰广 前缀按阿里巴巴口径匹配(店铺名不带「阿里巴巴」前缀) $this->assertSame('阿里巴巴', $map->platform('新佰广1688', '淘宝')); $this->assertSame('阿里巴巴', $map->platform('1688某某旗舰店', '淘宝')); $this->assertSame('1688佣金', $map->remark('新佰广1688', '淘宝', '1688大分销业务平台抽佣')); $this->assertNull($map->remark('抖音-乾廷润凯家具专卖店', '抖音', '不存在的账单项目')); $row = $map->decorate([ 'store_name' => '抖音-乾廷润凯家具专卖店', 'bill_item' => '保费扣除', 'payload' => ['settle_account' => 'TouTiaoFXGZJ'], ], 'douyin'); $this->assertSame('运费险', $row['payload']['ledger_remark']); $this->assertSame('运费险', $row['ledger_remark']); $this->assertSame('TouTiaoFXGZJ', $row['payload']['settle_account']); $untouched = $map->decorate(['store_name' => '抖音-xx', 'bill_item' => '未知项目', 'payload' => []], 'douyin'); $this->assertSame([], $untouched['payload']); } }