## 任务占用与边界 - 任务名称:财务分析开票费用与业绩明细违约赔付预览 - 实际开发者:yueyang - 任务来源/团队分工:负责人直接指定 - 目标结果:财务经营分析表按科目映射表拆分开票费用/不开票费用;业绩明细增加违约赔付(冲减收入)列并按指定顺序展示。 - 预计修改路径:业务 Pages Controller、财务分析视图、账单明细数据服务、业绩明细配置与相关测试。 - 将写入的公共契约:财务分析费用聚合、默认补偿预览命令、业绩明细列配置。 - 仅复用、明确不修改的公共契约:store_receipt_order_match_rows、ec_account_mapping_rules。 - 数据源、表/视图和字段:店铺收款账单镜像、store_receipt_order_match_rows、store_receipt_product_cost_rows、ec_account_mapping_rules。 - 明确不修改的范围:账单抓取与上游同步链路。 ## 开工碰撞检查 - [x] Codex 已执行 scripts/codex-task-preflight.ps1 - [x] 已检查最新 main 和远程任务分支 - [x] 已搜索主线既有页面、接口和数据服务 - [x] 已将写入和复用契约分开 - [x] 预检列出的残留分支均无开放 PR;当前 2 个开放 PR 与本任务无关,确认无活跃写入冲突 ## 实际改动 - 财务经营分析表增加“开票费用”“不开票费用”及合计;财务类型=费用,票据口径 0.06/0.09 归入开票,不开票归入不开票,金额按支出减收入净额。 - 费用聚合并入现有月度缓存,缓存键包含科目映射哈希,映射变化后自动失效。 - 业绩明细增加违约赔付(冲减收入)列,放在冲减金额后。 - CSV 导出列同步更新。 ## 验证证据 - 正常流程:2026-07/08/09 实库数据计算成功;2026-09 开票费用 3,896,538.65,不开票费用 81,377.62。 - 实际页面:2026-09 财务经营分析表 438 行,两列与合计正常展示。 - 性能:单月费用聚合 7.0–13.6 秒,PHP 峰值约 65.5 MB;页面结果缓存 5 分钟。 - 自动测试:NavigationTest 目标 2 条通过(35 assertions),StoreReceiptMappingPreviewOverrideTest 2 条通过(5 assertions)。 ## 风险检查 - [x] 不涉及数据库迁移或生产数据写入 - [x] 涉及金额口径,已用实库页面和固定总额核对 - [x] 未提交 .env、密码、Token、真实数据或构建产物 - [x] 前端符合 DESIGN.md 黑金表格样式 ## 合并前复查 - [x] 已基于最新 main 53bd1dc4 变基 - [x] 完整 diff 自审,无冲突标记 - [x] 目标测试通过 - [x] 负责人已授权 Squash merge 和发布 Reviewed-on: #480
48 lines
1.8 KiB
PHP
48 lines
1.8 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\EcommerceFinance;
|
|
|
|
use App\Console\Commands\SyncStoreReceiptOrderMatches;
|
|
use Modules\EcommerceFinance\Services\AccountLedgerRemarkMap;
|
|
use ReflectionClass;
|
|
use ReflectionMethod;
|
|
use Tests\TestCase;
|
|
|
|
class StoreReceiptMappingPreviewOverrideTest extends TestCase
|
|
{
|
|
public function test_default_compensation_is_included_in_offset_remarks(): void
|
|
{
|
|
$reflection = new ReflectionClass(SyncStoreReceiptOrderMatches::class);
|
|
$remarks = $reflection->getConstant('OFFSET_REMARKS');
|
|
|
|
$this->assertContains('冲减收入', $remarks);
|
|
$this->assertContains('违约赔付(冲减收入)', $remarks);
|
|
}
|
|
|
|
public function test_local_mapping_override_file_is_used_when_configured(): void
|
|
{
|
|
$path = tempnam(sys_get_temp_dir(), 'caiwu-mapping-override-');
|
|
$this->assertNotFalse($path);
|
|
file_put_contents($path, json_encode([
|
|
['platform' => '京东', 'item' => '结算单', 'memo' => '订单收入'],
|
|
['platform' => '京东', 'item' => '售后卖家赔付费', 'memo' => '违约赔付(冲减收入)'],
|
|
], JSON_UNESCAPED_UNICODE));
|
|
|
|
$previous = getenv('ACCOUNT_MAPPING_OVERRIDE_FILE');
|
|
putenv('ACCOUNT_MAPPING_OVERRIDE_FILE=' . $path);
|
|
|
|
try {
|
|
$method = new ReflectionMethod(AccountLedgerRemarkMap::class, 'accountMappingOverrideRules');
|
|
$rules = $method->invoke(new AccountLedgerRemarkMap());
|
|
|
|
$this->assertCount(2, $rules);
|
|
$this->assertSame('违约赔付(冲减收入)', $rules[1]['memo']);
|
|
} finally {
|
|
putenv($previous === false
|
|
? 'ACCOUNT_MAPPING_OVERRIDE_FILE'
|
|
: 'ACCOUNT_MAPPING_OVERRIDE_FILE=' . $previous);
|
|
@unlink($path);
|
|
}
|
|
}
|
|
}
|