支持进销存报表七月数据 #248

Merged
chenxi merged 1 commits from fix/chenxi-inventory-report-july into main 2026-09-23 11:18:19 +08:00
3 changed files with 43 additions and 10 deletions

View File

@ -60,6 +60,9 @@ class ThirdPartyWarehouseStorageMirrorRepository
public const START_DATE = '2026-08-01';
/** Historical monthly report range can start one month before the flow page. */
private const INVENTORY_REPORT_START_DATE = '2026-07-01';
/** @var array<string,string> */
private const MOVEMENT_COLUMNS = [
'processing_in' => '加工进仓',
@ -299,10 +302,7 @@ class ThirdPartyWarehouseStorageMirrorRepository
}
$page = max($page, 1);
$perPage = min(max($perPage, 1), 5000);
$period = $this->period([
'dimension' => 'month',
'period' => $filters['month'] ?? '',
]);
$period = $this->inventoryReportPeriod((string) ($filters['month'] ?? ''));
$authoritative = $this->monthlyInventoryAuthoritativeQuery($period, $filters);
if ($authoritative !== null) {
$total = $includeTotal ? (clone $authoritative)->count() : 0;
@ -1316,6 +1316,31 @@ class ThirdPartyWarehouseStorageMirrorRepository
];
}
/** @return array{dimension:string,value:string,start:string,end:string,days:int} */
private function inventoryReportPeriod(string $month): array
{
try {
$start = preg_match('/^\d{4}-\d{2}$/', trim($month)) === 1
? Carbon::createFromFormat('!Y-m', trim($month))->startOfMonth()
: now()->startOfMonth();
} catch (Throwable) {
$start = now()->startOfMonth();
}
$minimum = Carbon::parse(self::INVENTORY_REPORT_START_DATE)->startOfMonth();
if ($start->lt($minimum)) {
$start = $minimum;
}
return [
'dimension' => 'month',
'value' => $start->format('Y-m'),
'start' => $start->format('Y-m-d 00:00:00'),
'end' => $start->copy()->addMonth()->format('Y-m-d 00:00:00'),
'days' => $start->daysInMonth,
];
}
/** @param array<string,mixed> $state */
private function stateAnchor(array $state): string
{

View File

@ -12,7 +12,7 @@ class ThirdPartyWarehouseStorageUpstreamRepository
/** 三方仓页面仍固定读取该仓;共享流水镜像覆盖全部仓库。 */
public const WAREHOUSE_ID = 15045364;
public const START_DATE = '2026-08-01';
public const START_DATE = '2026-07-01';
private ?UpstreamReadOnlyQuery $query = null;

View File

@ -400,22 +400,30 @@ class ThirdPartyWarehouseStorageMirrorRepositoryTest extends TestCase
$this->assertFalse($this->repository->allWarehousesReady());
}
public function test_periods_before_the_supported_start_date_are_clamped(): void
public function test_monthly_inventory_report_supports_july_without_changing_flow_page_cutoff(): void
{
$this->markReady();
$this->insertProduct('SKU-CUTOFF');
$this->insertInventory('SKU-CUTOFF', 2, '2026-08-02 00:00:00');
$this->insertInventory('SKU-CUTOFF', 10, '2026-08-01 00:00:00');
$this->insertMovement('SKU-CUTOFF', '采购进仓', 2, 1, '2026-07-15 12:00:00');
$this->insertMovement('SKU-CUTOFF', '采购进仓', 2, 1, '2026-08-01 12:00:00');
$day = $this->repository->paginate($this->filters([
'dimension' => 'day',
'period' => '2026-07-01',
]), 1, 25)['data'][0];
$month = $this->repository->paginate($this->filters(['period' => '2026-07']), 1, 100)['data'];
$inventoryReport = $this->repository->paginateMonthlyInventoryReport([
'month' => '2026-07',
'product_code' => 'SKU-CUTOFF',
'warehouse_provider' => '',
'category' => '',
], 1, 25);
$this->assertSame('2026-08-01', $day['date']);
$this->assertSame('2026-08-01', $month[0]['date']);
$this->assertSame('2026-08-31', $month[30]['date']);
$this->assertSame(1, $inventoryReport['total']);
$this->assertSame('2026-07-01', $inventoryReport['data'][0]->month);
$this->assertSame(8.0, (float) $inventoryReport['data'][0]->opening_quantity);
$this->assertSame(10.0, (float) $inventoryReport['data'][0]->closing_quantity);
}
public function test_product_catalog_must_finish_initial_sync_before_product_fields_are_exposed(): void