CaiWuXiTong/app/Business/KukaPostingBase/KukaPostingBaseRepository.php
chenxi 27021ce55a feat: 顾家发货明细补齐物料与成本 (#1117)
按货号同步唯一物料编号,并从顾家报价单带出物料描述和含税成本,按实发数量计算发货金额。
2026-11-11 20:08:21 +08:00

189 lines
5.8 KiB
PHP

<?php
namespace App\Business\KukaPostingBase;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Facades\Schema;
class KukaPostingBaseRepository
{
public function __construct(private readonly DatabaseManager $databases)
{
}
public function available(): bool
{
$schema = Schema::connection($this->connectionName());
return $schema->hasTable('kuka_posting_base_imports')
&& $schema->hasTable('kuka_posting_base_rows');
}
public function latestImport(int $companyId): ?object
{
if (! $this->available()) {
return null;
}
return $this->connection()
->table('kuka_posting_base_imports')
->where('company_id', $companyId)
->orderByDesc('period')
->first();
}
public function importFor(int $companyId, string $period): ?object
{
if (! $this->available()) {
return null;
}
return $this->connection()
->table('kuka_posting_base_imports')
->where('company_id', $companyId)
->where('period', $period)
->first();
}
/**
* @return list<string>
*/
public function periods(int $companyId): array
{
if (! $this->available()) {
return [];
}
return $this->connection()
->table('kuka_posting_base_imports')
->where('company_id', $companyId)
->orderByDesc('period')
->pluck('period')
->map(static fn (mixed $period): string => (string) $period)
->all();
}
/**
* @return list<string>
*/
public function statuses(int $companyId, string $period): array
{
if (! $this->available()) {
return [];
}
return $this->connection()
->table('kuka_posting_base_rows')
->where('company_id', $companyId)
->where('period', $period)
->whereNotNull('order_status')
->where('order_status', '!=', '')
->distinct()
->orderBy('order_status')
->pluck('order_status')
->map(static fn (mixed $status): string => (string) $status)
->all();
}
/**
* @param list<string> $itemNumbers
* @return array<string,object>
*/
public function materialMaps(int $companyId, array $itemNumbers): array
{
$itemNumbers = array_values(array_unique(array_filter(array_map(
static fn (mixed $value): string => trim((string) $value),
$itemNumbers,
))));
if ($itemNumbers === []
|| ! Schema::connection($this->connectionName())->hasTable('kuka_posting_material_map_rows')) {
return [];
}
return $this->connection()
->table('kuka_posting_material_map_rows')
->where('company_id', $companyId)
->where('match_status', 'matched')
->whereIn('item_number', $itemNumbers)
->get(['item_number', 'material_number'])
->filter(static fn (object $row): bool => trim((string) $row->material_number) !== '')
->keyBy(static fn (object $row): string => (string) $row->item_number)
->all();
}
/**
* @param list<string> $materialNumbers
* @return array<string,object>
*/
public function effectiveQuotations(int $companyId, array $materialNumbers): array
{
$materialNumbers = array_values(array_unique(array_filter(array_map(
static fn (mixed $value): string => trim((string) $value),
$materialNumbers,
))));
if ($materialNumbers === []
|| ! Schema::connection($this->connectionName())->hasTable('kuka_posting_quotation_rows')) {
return [];
}
return $this->connection()
->table('kuka_posting_quotation_rows')
->where('company_id', $companyId)
->where('record_status', '生效')
->whereIn('material_number', $materialNumbers)
->get(['material_number', 'material_desc', 'price_including_tax'])
->keyBy(static fn (object $row): string => (string) $row->material_number)
->all();
}
public function paginate(
int $companyId,
string $period,
array $filters,
int $page,
int $perPage,
): LengthAwarePaginator {
$query = $this->connection()
->table('kuka_posting_base_rows')
->where('company_id', $companyId)
->where('period', $period);
$storeName = trim((string) ($filters['store_name'] ?? ''));
if ($storeName !== '') {
$query->where('store_name', $storeName);
}
$status = trim((string) ($filters['status'] ?? ''));
if ($status !== '') {
$query->where('order_status', $status);
}
$keyword = trim((string) ($filters['keyword'] ?? ''));
if ($keyword !== '') {
$like = '%' . addcslashes($keyword, '\\%_') . '%';
$query->where(static function ($nested) use ($like): void {
$nested->where('internal_order_no', 'like', $like)
->orWhere('online_order_no', 'like', $like)
->orWhere('product_code', 'like', $like);
});
}
return $query
->orderBy('source_row_number')
->paginate($perPage, ['*'], 'page', $page)
->withQueryString();
}
private function connection(): ConnectionInterface
{
return $this->databases->connection($this->connectionName());
}
private function connectionName(): string
{
return (string) config('upstream_mirrors.connection', 'business_mirror');
}
}