189 lines
6.3 KiB
PHP
189 lines
6.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Exports;
|
|
|
|
use Carbon\Carbon;
|
|
use Maatwebsite\Excel\Concerns\FromArray;
|
|
use Maatwebsite\Excel\Concerns\WithHeadings;
|
|
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
|
|
use Maatwebsite\Excel\Concerns\WithTitle;
|
|
|
|
/**
|
|
* 三方仓仓储费核算明细导出:汇总 / 进销存数据汇总(每日) / 进销存(逐商品) /
|
|
* 每日商品仓储费四张表。
|
|
* 数据来自 ThirdPartyWarehouseStorageFeeCalculator 的核算结果(或存档快照)。
|
|
*/
|
|
class ThirdPartyWarehouseStorageSettlementExport implements WithMultipleSheets
|
|
{
|
|
/**
|
|
* @param array{summary:array<string,mixed>,daily:list<array<string,mixed>>,per_sku:list<array<string,mixed>>,daily_sku?:list<array<string,mixed>>} $result
|
|
*/
|
|
public function __construct(private readonly array $result)
|
|
{
|
|
}
|
|
|
|
/** @return array<int,object> */
|
|
public function sheets(): array
|
|
{
|
|
return [
|
|
new StorageSettlementSummarySheet($this->result['summary']),
|
|
new StorageSettlementDailySheet($this->result['summary'], $this->result['daily']),
|
|
new StorageSettlementSkuSheet($this->result['per_sku']),
|
|
new ThirdPartyWarehouseStorageDetailExport($this->result['daily_sku'] ?? []),
|
|
];
|
|
}
|
|
}
|
|
|
|
class StorageSettlementSummarySheet implements FromArray, WithHeadings, WithTitle
|
|
{
|
|
/** @param array<string,mixed> $summary */
|
|
public function __construct(private readonly array $summary)
|
|
{
|
|
}
|
|
|
|
public function title(): string
|
|
{
|
|
return '汇总';
|
|
}
|
|
|
|
/** @return array<int,string> */
|
|
public function headings(): array
|
|
{
|
|
$period = (string) ($this->summary['period'] ?? '');
|
|
$label = $period !== '' ? Carbon::createFromFormat('Y-m-d', $period . '-01')->format('Y年n月') : '汇总';
|
|
|
|
return [$label, '仓库提供', '简尚核算', '差异'];
|
|
}
|
|
|
|
/** @return array<int,array<int,mixed>> */
|
|
public function array(): array
|
|
{
|
|
$s = $this->summary;
|
|
$rate = static fn (string $key): string => rtrim(rtrim(number_format((float) ($s[$key] ?? 0), 4, '.', ''), '0'), '.');
|
|
$rows = [
|
|
['入库管理费(' . $rate('inbound_rate_per_ton') . '元/吨)', null, (float) $s['inbound_fee']],
|
|
['出库费用(' . $rate('outbound_rate_per_order') . '元/单)', null, (float) $s['outbound_fee']],
|
|
['当天仓储费用(每日库存结余÷' . $rate('pieces_per_pallet') . '件×托盘' . $rate('pallet_area_sqm') . '㎡×' . $rate('storage_rate_per_sqm_month') . '÷当月天数,逐日累加)', null, (float) $s['storage_fee']],
|
|
['记账', null, (float) $s['memo_fee']],
|
|
['盘亏扣款', null, (float) $s['loss_fee']],
|
|
['赔偿', null, (float) $s['compensation_fee']],
|
|
['合计', 0, (float) $s['total_fee']],
|
|
];
|
|
|
|
return array_map(static function (array $row): array {
|
|
$provided = $row[1];
|
|
$checked = $row[2];
|
|
$diff = $checked === null ? null : round((float) ($provided ?? 0) - (float) $checked, 2);
|
|
|
|
return [$row[0], $provided, $checked, $diff];
|
|
}, $rows);
|
|
}
|
|
}
|
|
|
|
class StorageSettlementDailySheet implements FromArray, WithHeadings, WithTitle
|
|
{
|
|
/**
|
|
* @param array<string,mixed> $summary
|
|
* @param list<array<string,mixed>> $daily
|
|
*/
|
|
public function __construct(private readonly array $summary, private readonly array $daily)
|
|
{
|
|
}
|
|
|
|
public function title(): string
|
|
{
|
|
return '进销存数据汇总';
|
|
}
|
|
|
|
/** @return array<int,string> */
|
|
public function headings(): array
|
|
{
|
|
return ['日期', '当日入库计费件数', '入库管理(吨重)', '当日出库计费件数', '当日库存结余', '坪效仓储费', '入库管理费', '出库费用', '增值服务(元/件)', '合计'];
|
|
}
|
|
|
|
/** @return array<int,array<int,mixed>> */
|
|
public function array(): array
|
|
{
|
|
$rows = [];
|
|
$sumInbound = 0.0;
|
|
$sumOut = 0.0;
|
|
$sumStorage = 0.0;
|
|
$sumOutFee = 0.0;
|
|
foreach ($this->daily as $d) {
|
|
$rows[] = [
|
|
$d['date'],
|
|
(float) $d['inbound_qty'],
|
|
null,
|
|
(float) $d['outbound_qty'],
|
|
(float) $d['closing'],
|
|
(float) $d['storage_fee'],
|
|
null,
|
|
(float) $d['outbound_fee'],
|
|
null,
|
|
(float) $d['total'],
|
|
];
|
|
$sumInbound += (float) $d['inbound_qty'];
|
|
$sumOut += (float) $d['outbound_qty'];
|
|
$sumStorage += (float) $d['storage_fee'];
|
|
$sumOutFee += (float) $d['outbound_fee'];
|
|
}
|
|
|
|
$s = $this->summary;
|
|
$rows[] = [
|
|
'合计',
|
|
round($sumInbound, 2),
|
|
(float) $s['inbound_tons'],
|
|
round($sumOut, 2),
|
|
null,
|
|
round($sumStorage, 2),
|
|
(float) $s['inbound_fee'],
|
|
round($sumOutFee, 2),
|
|
null,
|
|
round($sumStorage + (float) $s['inbound_fee'] + round($sumOutFee, 2), 2),
|
|
];
|
|
|
|
return $rows;
|
|
}
|
|
}
|
|
|
|
class StorageSettlementSkuSheet implements FromArray, WithHeadings, WithTitle
|
|
{
|
|
/** @param list<array<string,mixed>> $perSku */
|
|
public function __construct(private readonly array $perSku)
|
|
{
|
|
}
|
|
|
|
public function title(): string
|
|
{
|
|
return '进销存';
|
|
}
|
|
|
|
/** @return array<int,string> */
|
|
public function headings(): array
|
|
{
|
|
return ['货主', '商品编码', '商品名称', '供应商', '分类', '单位', '重量(kg)', '单件吨', '入库计费件数', '总吨(单件吨×入库计费件数)', '出库计费件数', '期初数量', '期末数量'];
|
|
}
|
|
|
|
/** @return array<int,array<int,mixed>> */
|
|
public function array(): array
|
|
{
|
|
return array_map(static fn (array $r): array => [
|
|
$r['owner'],
|
|
$r['sku_code'],
|
|
$r['product_name'],
|
|
$r['supplier'],
|
|
$r['category'],
|
|
$r['unit'],
|
|
(float) $r['weight'],
|
|
(float) $r['per_ton'],
|
|
(float) $r['inbound_qty'],
|
|
(float) $r['total_ton'],
|
|
(float) $r['outbound_qty'],
|
|
(float) $r['opening'],
|
|
(float) $r['closing'],
|
|
], $this->perSku);
|
|
}
|
|
}
|