业绩明细账单名称汇总增加平台列 #516
@ -1553,6 +1553,7 @@
|
||||
<table class="receipt-metric-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">平台</th>
|
||||
<th scope="col">账单名称</th>
|
||||
<th scope="col" class="is-number">总金额</th>
|
||||
</tr>
|
||||
@ -1584,7 +1585,7 @@
|
||||
</section>
|
||||
</div>
|
||||
<div class="receipt-metric-dialog__foot">
|
||||
<span data-receipt-metric-count>共 0 个账单名称</span>
|
||||
<span data-receipt-metric-count>共 0 条平台账单汇总</span>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
@ -2347,7 +2348,7 @@
|
||||
title.textContent = label + ' · 明细汇总';
|
||||
subtitle.textContent = '按平台、店铺和账单名称汇总';
|
||||
currentTotalEl.textContent = '…';
|
||||
countEl.textContent = '正在读取账单名称';
|
||||
countEl.textContent = '正在读取平台账单汇总';
|
||||
dialog.setAttribute('aria-busy', 'true');
|
||||
}
|
||||
|
||||
@ -2384,6 +2385,9 @@
|
||||
summaryRowsEl.replaceChildren();
|
||||
rows.forEach(function (row) {
|
||||
var tr = document.createElement('tr');
|
||||
var platform = document.createElement('td');
|
||||
platform.textContent = row.platform || '—';
|
||||
tr.appendChild(platform);
|
||||
var billItem = document.createElement('td');
|
||||
billItem.textContent = row.bill_item || '未命名账单项目';
|
||||
tr.appendChild(billItem);
|
||||
@ -2414,7 +2418,7 @@
|
||||
|
||||
function updateFooterCount() {
|
||||
countEl.textContent = activeTab === 'summary'
|
||||
? '共 ' + summaryCount.toLocaleString('zh-CN') + ' 个账单名称'
|
||||
? '共 ' + summaryCount.toLocaleString('zh-CN') + ' 条平台账单汇总'
|
||||
: '共 ' + detailCount.toLocaleString('zh-CN') + ' 条平台店铺明细';
|
||||
}
|
||||
|
||||
@ -2438,15 +2442,25 @@
|
||||
&& (!store || row.store_name === store)
|
||||
&& (!billItem || row.bill_item === billItem);
|
||||
});
|
||||
var totalsByBillItem = {};
|
||||
var totalsByPlatformBillItem = {};
|
||||
rows.forEach(function (row) {
|
||||
var platform = row.platform || '—';
|
||||
var name = row.bill_item || '未命名账单项目';
|
||||
totalsByBillItem[name] = (totalsByBillItem[name] || 0) + Number(row.amount || 0);
|
||||
var key = JSON.stringify([platform, name]);
|
||||
if (!totalsByPlatformBillItem[key]) {
|
||||
totalsByPlatformBillItem[key] = {
|
||||
platform: platform,
|
||||
bill_item: name,
|
||||
amount: 0
|
||||
};
|
||||
}
|
||||
totalsByPlatformBillItem[key].amount += Number(row.amount || 0);
|
||||
});
|
||||
var summaryRows = Object.keys(totalsByBillItem).map(function (name) {
|
||||
return { bill_item: name, amount: totalsByBillItem[name] };
|
||||
var summaryRows = Object.keys(totalsByPlatformBillItem).map(function (key) {
|
||||
return totalsByPlatformBillItem[key];
|
||||
}).sort(function (left, right) {
|
||||
return Math.abs(right.amount) - Math.abs(left.amount)
|
||||
|| left.platform.localeCompare(right.platform, 'zh-CN')
|
||||
|| left.bill_item.localeCompare(right.bill_item, 'zh-CN');
|
||||
});
|
||||
var filteredTotal = summaryRows.reduce(function (sum, row) {
|
||||
|
||||
@ -75,11 +75,53 @@ class PerformanceDetailsMetricDetailsTest extends FeatureTestCase
|
||||
], $rows);
|
||||
}
|
||||
|
||||
private function row(string $rowKey, string $storeName, float $offset): array
|
||||
public function test_same_bill_item_is_split_by_platform_for_summary(): void
|
||||
{
|
||||
$mirror = DB::connection('business_mirror');
|
||||
$mirror->table('store_receipt_order_match_rows')->insert([
|
||||
$this->row('row-jd', '京东店铺', -100, '京东账单'),
|
||||
$this->row('row-pdd', '拼多多店铺', -50, '拼多多'),
|
||||
]);
|
||||
$mirror->table('store_receipt_order_match_metric_details')->insert([
|
||||
$this->detail('detail-jd', 'row-jd', '账单扣款', -100, '京东账单'),
|
||||
$this->detail('detail-pdd', 'row-pdd', '账单扣款', -50, '拼多多'),
|
||||
]);
|
||||
|
||||
$response = $this->loginAs()->getJson(route(
|
||||
'business.financial-operations.performance-details.metric-details',
|
||||
[
|
||||
'metric' => 'offset_amount',
|
||||
'month' => '2026-09',
|
||||
],
|
||||
));
|
||||
|
||||
$response
|
||||
->assertOk()
|
||||
->assertJsonPath('total', -150)
|
||||
->assertJsonPath('detail_total', -150)
|
||||
->assertJsonPath('balanced', true);
|
||||
|
||||
$this->assertContains([
|
||||
'platform' => '京东账单',
|
||||
'store_name' => '京东店铺',
|
||||
'bill_item' => '账单扣款',
|
||||
'amount' => -100,
|
||||
'line_count' => 1,
|
||||
], $response->json('rows'));
|
||||
$this->assertContains([
|
||||
'platform' => '拼多多',
|
||||
'store_name' => '拼多多店铺',
|
||||
'bill_item' => '账单扣款',
|
||||
'amount' => -50,
|
||||
'line_count' => 1,
|
||||
], $response->json('rows'));
|
||||
}
|
||||
|
||||
private function row(string $rowKey, string $storeName, float $offset, string $platform = '京东账单'): array
|
||||
{
|
||||
return [
|
||||
'report_month' => '2026-09-01',
|
||||
'platform' => '京东账单',
|
||||
'platform' => $platform,
|
||||
'row_key' => $rowKey,
|
||||
'occurred_date' => '2026-09-01',
|
||||
'store_name' => $storeName,
|
||||
@ -100,13 +142,19 @@ class PerformanceDetailsMetricDetailsTest extends FeatureTestCase
|
||||
];
|
||||
}
|
||||
|
||||
private function detail(string $detailKey, string $rowKey, string $billItem, float $amount): array
|
||||
private function detail(
|
||||
string $detailKey,
|
||||
string $rowKey,
|
||||
string $billItem,
|
||||
float $amount,
|
||||
string $platform = '京东账单'
|
||||
): array
|
||||
{
|
||||
return [
|
||||
'report_month' => '2026-09-01',
|
||||
'detail_key' => $detailKey,
|
||||
'row_key' => $rowKey,
|
||||
'platform' => '京东账单',
|
||||
'platform' => $platform,
|
||||
'metric' => 'offset',
|
||||
'bill_item' => $billItem,
|
||||
'amount' => $amount,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user