导入进销存报表表头及演示数据 #213

Merged
chenxi merged 1 commits from feature/chenxi-inventory-report-import into main 2026-09-20 12:58:14 +08:00
5 changed files with 103 additions and 7 deletions

View File

@ -381,6 +381,10 @@ class Pages extends Controller
$tabColumn = null;
$upstreamError = null;
if (($section['slug'] ?? null) === 'product-inventory' && ($page['slug'] ?? null) === 'inventory-report') {
$rows = $this->inventoryReportDemoRows();
}
if ($page && $content === null) {
$descriptor = TableRegistry::describe(
$section['slug'],
@ -481,6 +485,26 @@ class Pages extends Controller
];
}
private function inventoryReportDemoRows(): LengthAwarePaginator
{
$columns = config('inventory_report_demo.columns', []);
$rows = collect(config('inventory_report_demo.rows', []))
->map(fn (array $row): array => array_combine($columns, $row));
$perPage = 50;
$currentPage = max(1, request()->integer('page', 1));
return new LengthAwarePaginator(
$rows->forPage($currentPage, $perPage)->values(),
$rows->count(),
$perPage,
$currentPage,
[
'path' => request()->url(),
'query' => request()->query(),
],
);
}
private function isStoreReceivingAccountPage(string $section, string $page): bool
{
return $section === 'fund-management' && $page === 'store-receiving-accounts';

View File

@ -307,10 +307,32 @@ $navigation = [
'title' => '进销存报表',
'directory' => [
'icon' => 'inventory',
'status' => '字段待定义',
'description' => '进销存报表页面入口已建立,待确认报表字段和数据来源后接入正式数据。',
'empty' => '进销存报表字段和数据来源尚未定义。',
'fields' => [],
'status' => '演示数据',
'description' => '按进销存报表模板展示货主、仓库、商品及库存变动数据。',
'empty' => '暂无进销存演示数据。',
'fields' => [
['name' => 'owner', 'label' => '货主'],
['name' => 'month', 'label' => '月份', 'kind' => 'date'],
['name' => 'warehouse_provider', 'label' => '仓储方'],
['name' => 'warehouse', 'label' => '仓库'],
['name' => 'product_code', 'label' => '商品编码'],
['name' => 'category', 'label' => '分类'],
['name' => 'opening_quantity', 'label' => '期初数量', 'kind' => 'integer'],
['name' => 'closing_quantity', 'label' => '期末数量', 'kind' => 'integer'],
['name' => 'processing_in', 'label' => '加工进仓', 'kind' => 'integer'],
['name' => 'processing_out', 'label' => '加工出仓', 'kind' => 'integer'],
['name' => 'purchase_in', 'label' => '采购进仓', 'kind' => 'integer'],
['name' => 'purchase_return', 'label' => '采购退货', 'kind' => 'integer'],
['name' => 'other_in', 'label' => '其它进仓', 'kind' => 'integer'],
['name' => 'other_return', 'label' => '其它退货', 'kind' => 'integer'],
['name' => 'sales_out', 'label' => '销售出仓', 'kind' => 'integer'],
['name' => 'sales_return', 'label' => '销售退货', 'kind' => 'integer'],
['name' => 'stocktake', 'label' => '盘点', 'kind' => 'integer'],
['name' => 'transfer_out', 'label' => '调拨出', 'kind' => 'integer'],
['name' => 'transfer_in', 'label' => '调拨入', 'kind' => 'integer'],
['name' => 'opening', 'label' => '期初', 'kind' => 'integer'],
['name' => 'other_out', 'label' => '其它出库', 'kind' => 'integer'],
],
],
],
],

View File

@ -0,0 +1,32 @@
<?php
return [
'columns' => [
'owner', 'month', 'warehouse_provider', 'warehouse', 'product_code', 'category',
'opening_quantity', 'closing_quantity', 'processing_in', 'processing_out',
'purchase_in', 'purchase_return', 'other_in', 'other_return', 'sales_out',
'sales_return', 'stocktake', 'transfer_out', 'transfer_in', 'opening', 'other_out',
],
'rows' => [
['常州简尚家居有限公司', '2026-09-01', '简尚-崔桥工厂仓', '简尚-崔桥工厂仓主仓', '100006981661', '住宅家具 - 书桌', 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '简尚-横林二仓', '客退临时上架仓', '110886Z15', null, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '121630-49', '其他 - 配件', -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '简尚-崔桥工厂仓', '简尚-崔桥工厂仓主仓', '121640', '住宅家具 - 门厅/玄关柜/玄关架', 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135150-13', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '简尚-分销部专用仓', '简尚-分销部专用仓主仓', '135580', '住宅家具 - 餐边柜', 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-1', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-12', '其他 - 配件', -3, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-13', '其他 - 配件', -3, -4, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-14', '其他 - 配件', -4, -5, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-15', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-16', '其他 - 配件', -1, -3, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-17', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-18', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-19', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-21', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-26', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-28', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '常州简尚家居有限公司', '配件单仓', '135590-33', '其他 - 配件', -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
['常州简尚家居有限公司', '2026-09-01', '简尚-分销部崔桥专用仓', '简尚-分销部崔桥专用仓主仓', '135600', '住宅家具 - 餐边柜', 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
],
];

View File

@ -369,6 +369,11 @@
<span class="material-icons-outlined" aria-hidden="true">error_outline</span>
<span>{{ $upstreamError }}</span>
</div>
@elseif (($directory['status'] ?? null) === '演示数据' && $directoryTotal > 0)
<div class="directory-table-notice" role="status">
<span class="material-icons-outlined" aria-hidden="true">preview</span>
<span>已按附件模板导入 {{ $directoryTotal }} 条演示数据,当前页面为只读展示。</span>
</div>
@elseif ($directoryTotal > 0)
<div class="directory-table-notice" role="status">
<span class="material-icons-outlined" aria-hidden="true">cloud_done</span>
@ -472,7 +477,7 @@
<tr>
<th scope="col">#</th>
@foreach ($directoryFields as $field)
<th scope="col" data-column-key="{{ $field['name'] }}" class="{{ ($field['kind'] ?? null) === 'number' ? 'is-number' : '' }}">{{ $field['label'] }}</th>
<th scope="col" data-column-key="{{ $field['name'] }}" class="{{ in_array($field['kind'] ?? null, ['number', 'integer'], true) ? 'is-number' : '' }}">{{ $field['label'] }}</th>
@endforeach
</tr>
</thead>
@ -496,11 +501,13 @@
$display = substr((string) $value, 0, 10);
} elseif ($kind === 'number' && is_numeric($value)) {
$display = number_format((float) $value, 2);
} elseif ($kind === 'integer' && is_numeric($value)) {
$display = number_format((int) $value);
} elseif ($kind === 'boolean' && $value !== null && $value !== '') {
$display = in_array($value, [true, 1, '1', '是', '✔'], true) ? '是' : '否';
}
@endphp
<td data-column-key="{{ $field['name'] }}" class="{{ $kind === 'number' ? 'is-number' : '' }}">
<td data-column-key="{{ $field['name'] }}" class="{{ in_array($kind, ['number', 'integer'], true) ? 'is-number' : '' }}">
@if (($page['slug'] ?? '') === 'store-accounts' && $field['name'] === 'password_configured')
<span class="sr-only" data-password-status>{{ filled($display) ? $display : '—' }}</span>
@if ($value === false)

View File

@ -31,7 +31,18 @@ class NavigationTest extends FeatureTestCase
]))
->assertOk()
->assertSeeText('进销存报表')
->assertSeeText('进销存报表字段和数据来源尚未定义。');
->assertSeeTextInOrder([
'货主', '月份', '仓储方', '仓库', '商品编码', '分类',
'期初数量', '期末数量', '加工进仓', '加工出仓', '采购进仓',
'采购退货', '其它进仓', '其它退货', '销售出仓', '销售退货',
'盘点', '调拨出', '调拨入', '期初', '其它出库',
])
->assertSeeText('已按附件模板导入 20 条演示数据')
->assertSeeText('常州简尚家居有限公司')
->assertSeeText('100006981661')
->assertSeeText('2026-09-01')
->assertSeeText('住宅家具 - 门厅/玄关柜/玄关架')
->assertDontSeeText('进销存报表字段和数据来源尚未定义。');
}
public function testGroupedNavigationKeepsRestrictedPagePermissions(): void