135 lines
4.3 KiB
PHP
135 lines
4.3 KiB
PHP
<?php
|
||
|
||
namespace Modules\EcommerceFinance\Repositories;
|
||
|
||
use Illuminate\Database\ConnectionInterface;
|
||
use Illuminate\Database\Query\Builder;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
/**
|
||
* 发货明细只读仓库。读取扁平表 jst_oms_shipping(对齐工作平台发货数据 47 列),
|
||
* 供“发货数据”页面展示与后续快递运费核算使用。
|
||
*/
|
||
class ShippingOrderRepository
|
||
{
|
||
private readonly ConnectionInterface $db;
|
||
|
||
public function __construct()
|
||
{
|
||
$this->db = DB::connection((string) config('jushuitan.connection', 'jushuitan_local'));
|
||
}
|
||
|
||
/**
|
||
* @param array<string,string> $filters
|
||
* @return array{data:array,total:int}
|
||
*/
|
||
public function paginate(array $filters, int $page, int $perPage): array
|
||
{
|
||
$page = max($page, 1);
|
||
$perPage = min(max($perPage, 1), 100);
|
||
|
||
$q = $this->filteredQuery($filters);
|
||
|
||
$total = (clone $q)->count();
|
||
$rows = (clone $q)
|
||
->orderByDesc('ship_time')
|
||
->orderByDesc('id')
|
||
->forPage($page, $perPage)
|
||
->get()
|
||
->map(fn ($r) => (array) $r)
|
||
->all();
|
||
|
||
return ['data' => $rows, 'total' => $total];
|
||
}
|
||
|
||
/**
|
||
* @param array<string,string> $filters
|
||
* @return \Generator<int,array<string,mixed>>
|
||
*/
|
||
public function exportRows(array $filters, int $batchSize = 1000): \Generator
|
||
{
|
||
$batchSize = min(max($batchSize, 1), 5000);
|
||
$lastId = null;
|
||
|
||
while (true) {
|
||
$query = $this->filteredQuery($filters);
|
||
if ($lastId !== null) {
|
||
$query->where('id', '>', $lastId);
|
||
}
|
||
|
||
$rows = $query->orderBy('id')->limit($batchSize)->get()->all();
|
||
if ($rows === []) {
|
||
return;
|
||
}
|
||
|
||
foreach ($rows as $row) {
|
||
yield (array) $row;
|
||
}
|
||
|
||
$lastId = (int) $rows[array_key_last($rows)]->id;
|
||
if (count($rows) < $batchSize) {
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
/** @param array<string,string> $filters */
|
||
private function filteredQuery(array $filters): Builder
|
||
{
|
||
$query = $this->db->table('jst_oms_shipping');
|
||
|
||
if (($filters['express_no'] ?? '') !== '') {
|
||
$query->where('express_no', '=', trim((string) $filters['express_no']));
|
||
}
|
||
if (($filters['sourceno'] ?? '') !== '') {
|
||
$query->where('trade_no', '=', trim((string) $filters['sourceno']));
|
||
}
|
||
|
||
foreach (['barcode', 'supplier_name', 'shop_name', 'warehouse_name'] as $column) {
|
||
if (($filters[$column] ?? '') !== '') {
|
||
$query->whereRaw($column . " LIKE ? ESCAPE '!'", [$this->contains((string) $filters[$column])]);
|
||
}
|
||
}
|
||
|
||
if (($filters['express_company'] ?? '') !== '') {
|
||
$value = $this->contains((string) $filters['express_company']);
|
||
$query->where(static function (Builder $courier) use ($value): void {
|
||
$courier->whereRaw("express_name1 LIKE ? ESCAPE '!'", [$value])
|
||
->orWhereRaw("express_name2 LIKE ? ESCAPE '!'", [$value]);
|
||
});
|
||
}
|
||
|
||
if (($filters['ship_from'] ?? '') !== '') {
|
||
$query->where('ship_time', '>=', $filters['ship_from'] . ' 00:00:00');
|
||
}
|
||
if (($filters['ship_to'] ?? '') !== '') {
|
||
$query->where('ship_time', '<', date('Y-m-d 00:00:00', strtotime($filters['ship_to'] . ' +1 day')));
|
||
}
|
||
|
||
return $query;
|
||
}
|
||
|
||
private function contains(string $value): string
|
||
{
|
||
return '%' . str_replace(['!', '%', '_'], ['!!', '!%', '!_'], trim($value)) . '%';
|
||
}
|
||
|
||
/** 同步状态(供页面显示同步中/最近完成)。 */
|
||
public function syncStatus(): array
|
||
{
|
||
try {
|
||
$row = $this->db->table('jst_sync_state')->where('dataset_key', 'jst.sctrade')->first();
|
||
if (! $row) {
|
||
return ['code' => 'unavailable', 'last_succeeded_at' => null];
|
||
}
|
||
|
||
return [
|
||
'code' => (string) ($row->status ?? 'unavailable'),
|
||
'last_succeeded_at' => $row->last_succeeded_at ?? null,
|
||
];
|
||
} catch (\Throwable) {
|
||
return ['code' => 'unavailable', 'last_succeeded_at' => null];
|
||
}
|
||
}
|
||
}
|