CaiWuXiTong/modules/EcommerceFinance/View/SupplierAccessoryFreightPageData.php

82 lines
4.3 KiB
PHP

<?php
namespace Modules\EcommerceFinance\View;
use Illuminate\Pagination\LengthAwarePaginator;
use Modules\EcommerceFinance\Repositories\SupplierAccessoryFreightRepository;
use Modules\EcommerceFinance\Services\SupplierAccessoryFreightMatcher;
class SupplierAccessoryFreightPageData
{
public const TITLE = '新河北仓、曹县仓配件运费扣除明细';
public const TEXT_FILTERS = ['trade_no' => '交易单号', 'express_no' => '快递单号', 'supplier_name' => '供应商', 'normalized_barcode' => '处理后条形码', 'province' => '联系人省'];
public const COLUMNS = ['state' => '扣款状态', 'trade_no' => '交易单号', 'express_no' => '快递单号', 'courier' => '快递名称', 'ship_time' => '发货时间', 'barcode' => '原始条形码', 'normalized_barcode' => '处理后条形码', 'product_name' => '商品名称', 'supplier_name' => '供应商', 'province' => '联系人省', 'freight' => '配件运费(元)', 'deduction' => '扣款金额(元)', 'reason' => '说明'];
public function exportColumns(): array
{
$requested = request()->query('columns');
if ($requested === null) return self::COLUMNS;
abort_unless(is_string($requested) && strlen($requested) <= 500, 422, '导出列无效。');
$keys = explode(',', $requested);
abort_unless($keys !== [] && count($keys) === count(array_unique($keys)) && array_diff($keys, array_keys(self::COLUMNS)) === [], 422, '导出列无效。');
return array_replace(array_flip($keys), array_intersect_key(self::COLUMNS, array_flip($keys)));
}
public function __construct(private readonly SupplierAccessoryFreightRepository $repository) {}
public function filters(): array
{
$month = request()->query('month', now()->format('Y-m'));
abort_unless(is_string($month) && preg_match('/^\d{4}-(0[1-9]|1[0-2])$/', $month) && (int) substr($month, 0, 4) >= 2000, 422, '请选择有效业务月份。');
$state = request()->query('state', 'ready');
abort_unless(is_string($state) && in_array($state, ['all', ...array_keys(SupplierAccessoryFreightMatcher::STATES)], true), 422, '扣款状态无效。');
$filters = compact('month', 'state');
foreach (self::TEXT_FILTERS as $key => $label) {
$value = request()->query($key, '');
abort_unless(is_string($value) && mb_strlen($value) <= 200, 422, '筛选条件格式无效。');
$filters[$key] = trim($value);
}
$filters['province'] = match ($filters['province']) { '山东省' => '山东', '河北省' => '河北', default => $filters['province'] };
return $filters;
}
public function rows(array $filters): \Generator
{
foreach ($this->repository->rows($filters['month']) as $row) {
foreach (self::TEXT_FILTERS as $key => $label) {
if (($filters[$key] ?? '') !== '' && mb_stripos((string) ($row[$key] ?? ''), $filters[$key]) === false) continue 2;
}
yield $row;
}
}
public function page(): array
{
$filters = $this->filters();
$page = max(1, (int) request('page', 1));
$summary = ['all' => 0, 'ready' => 0, 'excluded' => 0, 'pending' => 0, 'amount' => 0];
$items = [];
$total = 0;
$error = null;
try {
foreach ($this->rows($filters) as $row) {
$summary['all']++;
$summary[$row['state']]++;
$summary['amount'] += $row['deduction_cents'];
if ($filters['state'] !== 'all' && $filters['state'] !== $row['state']) continue;
if ($total >= ($page - 1) * 50 && count($items) < 50) $items[] = $row;
$total++;
}
} catch (\Throwable $exception) {
report($exception);
$error = '发货、商品或供应商资料暂时无法读取,或尚未完成同步,请稍后重试。';
$summary = array_fill_keys(array_keys($summary), 0);
$items = [];
$total = 0;
}
return ['view' => 'business.pages.supplier-payables.accessory-freight-deductions',
'freightFilters' => $filters, 'freightSummary' => $summary, 'freightError' => $error,
'freightRows' => new LengthAwarePaginator($items, $total, 50, $page, ['path' => request()->url(), 'query' => request()->except('page')])];
}
}