CaiWuXiTong/modules/EcommerceFinance/Repositories/ProductPriceRepository.php

111 lines
3.9 KiB
PHP

<?php
namespace Modules\EcommerceFinance\Repositories;
use Modules\EcommerceFinance\Services\UpstreamReadOnlyQuery;
use Modules\EcommerceFinance\Services\UpstreamReadOnlyQueryFactory;
/**
* Supplier product pricing and repricing records from JianSun.
*/
class ProductPriceRepository
{
private const SOURCE = 'jiansun';
private const TABLE = '[dbo].[aaronprice]';
private const PRICE_TYPES = [
'pricing' => '定价',
'repricing' => '变价',
];
private const COST_REDUCTION = [
'yes' => '是',
'no' => '否',
];
private readonly UpstreamReadOnlyQuery $query;
public function __construct(UpstreamReadOnlyQueryFactory $queries)
{
$this->query = $queries->forSource(self::SOURCE);
}
/** @return array{rows:array<int,array<string,mixed>>} */
public function paginate(array $filters, int $page, int $limit): array
{
$page = max($page, 1);
$limit = min(max($limit, 1), 100);
$where = [];
$bindings = [];
if (($filters['barcode'] ?? '') !== '') {
$where[] = "[条形码] LIKE ? ESCAPE '\\'";
$bindings[] = $this->contains((string) $filters['barcode']);
}
$priceType = self::PRICE_TYPES[(string) ($filters['price_type'] ?? '')] ?? null;
if ($priceType !== null) {
$where[] = '[价格类型] = ?';
$bindings[] = $priceType;
}
$costReduction = self::COST_REDUCTION[(string) ($filters['cost_reduction'] ?? '')] ?? null;
if ($costReduction !== null) {
$where[] = '[是否采购降本] = ?';
$bindings[] = $costReduction;
}
if (($filters['effective_from'] ?? '') !== '') {
$where[] = 'TRY_CONVERT(date, [生效开始时间]) >= ?';
$bindings[] = (string) $filters['effective_from'];
}
if (($filters['effective_to'] ?? '') !== '') {
$where[] = 'TRY_CONVERT(date, [生效开始时间]) <= ?';
$bindings[] = (string) $filters['effective_to'];
}
$whereSql = $where === [] ? '' : ' WHERE ' . implode(' AND ', $where);
$offset = ($page - 1) * $limit;
$fetch = $limit + 1;
$sql = 'SELECT '
. '[条形码] AS barcode, '
. '[价格类型] AS price_type, '
. '[变价类型] AS change_type, '
. '[是否采购降本] AS cost_reduction, '
. 'TRY_CONVERT(decimal(18,2), NULLIF([变价前价格], \'\')) AS price_before, '
. 'TRY_CONVERT(decimal(18,2), NULLIF([变价后价格], \'\')) AS price_after, '
. 'TRY_CONVERT(decimal(18,2), NULLIF([差价], \'\')) AS price_diff, '
. '[申请人] AS applicant, '
. '[备注] AS remark, '
. 'CONVERT(varchar(19), TRY_CONVERT(datetime2, [生效开始时间]), 120) AS effective_start, '
. 'CONVERT(varchar(19), TRY_CONVERT(datetime2, [生效结束时间]), 120) AS effective_end, '
. 'CONVERT(varchar(19), TRY_CONVERT(datetime2, [流程完成时间]), 120) AS completed_at '
. 'FROM ' . self::TABLE
. $whereSql
. ' ORDER BY TRY_CONVERT(datetime2, [流程完成时间]) DESC, [条形码] ASC'
. " OFFSET {$offset} ROWS FETCH NEXT {$fetch} ROWS ONLY";
return ['rows' => array_map([$this, 'normalize'], $this->query->select($sql, $bindings))];
}
private function contains(string $value): string
{
return '%' . str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], trim($value)) . '%';
}
/** @param array<string,mixed> $row */
private function normalize(array $row): array
{
foreach (['price_before', 'price_after', 'price_diff'] as $field) {
$row[$field] = $row[$field] === null || $row[$field] === ''
? null
: (float) $row[$field];
}
return $row;
}
}