first
This commit is contained in:
574
server-api/app/support/WarehouseService.php
Normal file
574
server-api/app/support/WarehouseService.php
Normal file
@@ -0,0 +1,574 @@
|
||||
<?php
|
||||
|
||||
namespace app\support;
|
||||
|
||||
use support\think\Db;
|
||||
|
||||
class WarehouseService
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->ensureWarehouseTable();
|
||||
$this->ensureWarehouseRuleColumns();
|
||||
$this->ensureOrderTargetTable();
|
||||
$this->bootstrapDefaults();
|
||||
}
|
||||
|
||||
public function overviewCards(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'title' => '仓库总数',
|
||||
'value' => (int)Db::name('shipping_warehouses')->count(),
|
||||
'desc' => '当前已维护的检测中心 / 收货仓库数量',
|
||||
],
|
||||
[
|
||||
'title' => '启用仓库',
|
||||
'value' => (int)Db::name('shipping_warehouses')->where('status', 'enabled')->count(),
|
||||
'desc' => '当前对前台寄送页可见的仓库数量',
|
||||
],
|
||||
[
|
||||
'title' => '安心验仓库',
|
||||
'value' => (int)Db::name('shipping_warehouses')->where('service_provider', 'anxinyan')->count(),
|
||||
'desc' => '归属安心验服务的默认收货中心数量',
|
||||
],
|
||||
[
|
||||
'title' => '中检仓库',
|
||||
'value' => (int)Db::name('shipping_warehouses')->where('service_provider', 'zhongjian')->count(),
|
||||
'desc' => '归属中检服务的默认收货中心数量',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function list(): array
|
||||
{
|
||||
$rows = Db::name('shipping_warehouses')
|
||||
->order('service_provider', 'asc')
|
||||
->order('is_default', 'desc')
|
||||
->order('sort_order', 'asc')
|
||||
->order('id', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
return array_map(fn(array $item) => $this->formatWarehouse($item), $rows);
|
||||
}
|
||||
|
||||
public function save(array $payload, int $id = 0): int
|
||||
{
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$serviceProvider = trim((string)($payload['service_provider'] ?? 'anxinyan'));
|
||||
$status = trim((string)($payload['status'] ?? 'enabled'));
|
||||
$supportedCategoryIds = $this->normalizeIntArray($payload['supported_category_ids'] ?? []);
|
||||
$serviceAreaProvinces = $this->normalizeStringArray($payload['service_area_provinces'] ?? []);
|
||||
$serviceAreaCities = $this->normalizeStringArray($payload['service_area_cities'] ?? []);
|
||||
$warehouseCode = trim((string)($payload['warehouse_code'] ?? ''));
|
||||
|
||||
if ($warehouseCode === '') {
|
||||
$warehouseCode = $this->generateWarehouseCode($serviceProvider);
|
||||
}
|
||||
|
||||
$existsByCode = Db::name('shipping_warehouses')
|
||||
->where('warehouse_code', $warehouseCode)
|
||||
->when($id > 0, fn($query) => $query->where('id', '<>', $id))
|
||||
->find();
|
||||
if ($existsByCode) {
|
||||
throw new \RuntimeException('仓库编码已存在,请更换后重试');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'warehouse_name' => trim((string)($payload['warehouse_name'] ?? '')),
|
||||
'warehouse_code' => $warehouseCode,
|
||||
'warehouse_type' => 'detection_center',
|
||||
'service_provider' => $serviceProvider,
|
||||
'receiver_name' => trim((string)($payload['receiver_name'] ?? '')),
|
||||
'receiver_mobile' => trim((string)($payload['receiver_mobile'] ?? '')),
|
||||
'province' => trim((string)($payload['province'] ?? '')),
|
||||
'city' => trim((string)($payload['city'] ?? '')),
|
||||
'district' => trim((string)($payload['district'] ?? '')),
|
||||
'detail_address' => trim((string)($payload['detail_address'] ?? '')),
|
||||
'service_time' => trim((string)($payload['service_time'] ?? '')),
|
||||
'notice' => trim((string)($payload['notice'] ?? '')),
|
||||
'supported_category_ids_json' => $supportedCategoryIds ? json_encode($supportedCategoryIds, JSON_UNESCAPED_UNICODE) : null,
|
||||
'service_area_provinces_json' => $serviceAreaProvinces ? json_encode($serviceAreaProvinces, JSON_UNESCAPED_UNICODE) : null,
|
||||
'service_area_cities_json' => $serviceAreaCities ? json_encode($serviceAreaCities, JSON_UNESCAPED_UNICODE) : null,
|
||||
'status' => $status !== '' ? $status : 'enabled',
|
||||
'is_default' => !empty($payload['is_default']) ? 1 : 0,
|
||||
'sort_order' => (int)($payload['sort_order'] ?? 0),
|
||||
'remark' => trim((string)($payload['remark'] ?? '')),
|
||||
'updated_at' => $now,
|
||||
];
|
||||
|
||||
$this->validatePayload($data);
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
if ((int)$data['is_default'] === 1) {
|
||||
Db::name('shipping_warehouses')
|
||||
->where('service_provider', $serviceProvider)
|
||||
->update([
|
||||
'is_default' => 0,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($id > 0) {
|
||||
Db::name('shipping_warehouses')->where('id', $id)->update($data);
|
||||
$warehouseId = $id;
|
||||
} else {
|
||||
$data['created_at'] = $now;
|
||||
$warehouseId = (int)Db::name('shipping_warehouses')->insertGetId($data);
|
||||
}
|
||||
|
||||
if ((int)$data['is_default'] !== 1) {
|
||||
$currentDefault = Db::name('shipping_warehouses')
|
||||
->where('service_provider', $serviceProvider)
|
||||
->where('status', 'enabled')
|
||||
->where('is_default', 1)
|
||||
->find();
|
||||
if (!$currentDefault) {
|
||||
Db::name('shipping_warehouses')->where('id', $warehouseId)->update([
|
||||
'is_default' => 1,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
} catch (\Throwable $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $warehouseId;
|
||||
}
|
||||
|
||||
public function resolveForShipping(string $serviceProvider, ?int $categoryId = null, ?array $userAddress = null): array
|
||||
{
|
||||
$options = $this->optionsForOrder($serviceProvider, $categoryId, $userAddress);
|
||||
if (!$options) {
|
||||
return [
|
||||
'warehouse_id' => 0,
|
||||
'warehouse_name' => '',
|
||||
'warehouse_code' => '',
|
||||
'receiver_name' => '',
|
||||
'receiver_mobile' => '',
|
||||
'province' => '',
|
||||
'city' => '',
|
||||
'district' => '',
|
||||
'detail_address' => '',
|
||||
'service_time' => '',
|
||||
'notice' => '',
|
||||
];
|
||||
}
|
||||
|
||||
$matched = $options[0];
|
||||
return [
|
||||
'warehouse_id' => (int)$matched['id'],
|
||||
'warehouse_name' => $matched['warehouse_name'],
|
||||
'warehouse_code' => $matched['warehouse_code'],
|
||||
'receiver_name' => $matched['receiver_name'],
|
||||
'receiver_mobile' => $matched['receiver_mobile'],
|
||||
'province' => $matched['province'],
|
||||
'city' => $matched['city'],
|
||||
'district' => $matched['district'],
|
||||
'detail_address' => $matched['detail_address'],
|
||||
'service_time' => $matched['service_time'],
|
||||
'notice' => $matched['notice'],
|
||||
];
|
||||
}
|
||||
|
||||
public function bindOrderTarget(int $orderId, string $serviceProvider, ?int $categoryId = null, ?array $userAddress = null): array
|
||||
{
|
||||
$snapshot = $this->resolveForShipping($serviceProvider, $categoryId, $userAddress);
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
$payload = [
|
||||
'order_id' => $orderId,
|
||||
'warehouse_id' => (int)($snapshot['warehouse_id'] ?? 0) ?: null,
|
||||
'warehouse_name' => $snapshot['warehouse_name'] ?? '',
|
||||
'warehouse_code' => $snapshot['warehouse_code'] ?? '',
|
||||
'service_provider' => $serviceProvider,
|
||||
'receiver_name' => $snapshot['receiver_name'] ?? '',
|
||||
'receiver_mobile' => $snapshot['receiver_mobile'] ?? '',
|
||||
'province' => $snapshot['province'] ?? '',
|
||||
'city' => $snapshot['city'] ?? '',
|
||||
'district' => $snapshot['district'] ?? '',
|
||||
'detail_address' => $snapshot['detail_address'] ?? '',
|
||||
'service_time' => $snapshot['service_time'] ?? '',
|
||||
'notice' => $snapshot['notice'] ?? '',
|
||||
'updated_at' => $now,
|
||||
];
|
||||
|
||||
$exists = Db::name('order_shipping_targets')->where('order_id', $orderId)->find();
|
||||
if ($exists) {
|
||||
Db::name('order_shipping_targets')->where('order_id', $orderId)->update($payload);
|
||||
} else {
|
||||
$payload['created_at'] = $now;
|
||||
Db::name('order_shipping_targets')->insert($payload);
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
public function getOrderTarget(int $orderId): ?array
|
||||
{
|
||||
$row = Db::name('order_shipping_targets')->where('order_id', $orderId)->find();
|
||||
if (!$row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'warehouse_id' => (int)($row['warehouse_id'] ?? 0),
|
||||
'warehouse_name' => $row['warehouse_name'] ?? '',
|
||||
'warehouse_code' => $row['warehouse_code'] ?? '',
|
||||
'receiver_name' => $row['receiver_name'] ?? '',
|
||||
'receiver_mobile' => $row['receiver_mobile'] ?? '',
|
||||
'province' => $row['province'] ?? '',
|
||||
'city' => $row['city'] ?? '',
|
||||
'district' => $row['district'] ?? '',
|
||||
'detail_address' => $row['detail_address'] ?? '',
|
||||
'service_time' => $row['service_time'] ?? '',
|
||||
'notice' => $row['notice'] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
public function optionsForOrder(string $serviceProvider, ?int $categoryId = null, ?array $userAddress = null): array
|
||||
{
|
||||
$rows = Db::name('shipping_warehouses')
|
||||
->where('status', 'enabled')
|
||||
->where('service_provider', $serviceProvider)
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
if (!$rows) {
|
||||
$rows = Db::name('shipping_warehouses')
|
||||
->where('status', 'enabled')
|
||||
->select()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
$list = array_map(fn(array $item) => $this->formatWarehouse($item), $rows);
|
||||
|
||||
foreach ($list as &$item) {
|
||||
$item['match_score'] = $this->matchScore($item, $categoryId, $userAddress);
|
||||
$item['is_recommended'] = $item['match_score'] >= 300;
|
||||
$item['recommended_reason'] = $this->recommendedReason($item, $categoryId, $userAddress);
|
||||
}
|
||||
unset($item);
|
||||
|
||||
usort($list, static function (array $left, array $right) {
|
||||
if ($left['match_score'] === $right['match_score']) {
|
||||
if ((int)$left['is_default'] === (int)$right['is_default']) {
|
||||
if ((int)$left['sort_order'] === (int)$right['sort_order']) {
|
||||
return (int)$left['id'] <=> (int)$right['id'];
|
||||
}
|
||||
return (int)$left['sort_order'] <=> (int)$right['sort_order'];
|
||||
}
|
||||
return (int)$right['is_default'] <=> (int)$left['is_default'];
|
||||
}
|
||||
|
||||
return (int)$right['match_score'] <=> (int)$left['match_score'];
|
||||
});
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
private function formatWarehouse(array $item): array
|
||||
{
|
||||
$supportedCategoryIds = $this->decodeIntArray($item['supported_category_ids_json'] ?? null);
|
||||
$serviceAreaProvinces = $this->decodeStringArray($item['service_area_provinces_json'] ?? null);
|
||||
$serviceAreaCities = $this->decodeStringArray($item['service_area_cities_json'] ?? null);
|
||||
|
||||
$categoryNames = [];
|
||||
if ($supportedCategoryIds) {
|
||||
$categoryNames = Db::name('catalog_categories')
|
||||
->whereIn('id', $supportedCategoryIds)
|
||||
->column('name');
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => (int)$item['id'],
|
||||
'warehouse_name' => $item['warehouse_name'],
|
||||
'warehouse_code' => $item['warehouse_code'],
|
||||
'warehouse_type' => $item['warehouse_type'],
|
||||
'warehouse_type_text' => '检测中心 / 收货仓库',
|
||||
'service_provider' => $item['service_provider'],
|
||||
'service_provider_text' => $item['service_provider'] === 'zhongjian' ? '中检鉴定' : '实物鉴定',
|
||||
'receiver_name' => $item['receiver_name'],
|
||||
'receiver_mobile' => $item['receiver_mobile'],
|
||||
'province' => $item['province'],
|
||||
'city' => $item['city'],
|
||||
'district' => $item['district'],
|
||||
'detail_address' => $item['detail_address'],
|
||||
'full_address' => trim(sprintf('%s%s%s%s', $item['province'], $item['city'], $item['district'], $item['detail_address'])),
|
||||
'service_time' => $item['service_time'],
|
||||
'notice' => $item['notice'],
|
||||
'supported_category_ids' => $supportedCategoryIds,
|
||||
'supported_category_names' => array_values($categoryNames),
|
||||
'service_area_provinces' => $serviceAreaProvinces,
|
||||
'service_area_cities' => $serviceAreaCities,
|
||||
'status' => $item['status'],
|
||||
'status_text' => $item['status'] === 'enabled' ? '启用中' : '已停用',
|
||||
'is_default' => (bool)$item['is_default'],
|
||||
'sort_order' => (int)$item['sort_order'],
|
||||
'remark' => $item['remark'] ?? '',
|
||||
'created_at' => $item['created_at'] ?? '',
|
||||
'updated_at' => $item['updated_at'] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
private function validatePayload(array $data): void
|
||||
{
|
||||
foreach (['warehouse_name', 'receiver_name', 'receiver_mobile', 'province', 'city', 'district', 'detail_address', 'service_time'] as $field) {
|
||||
if (trim((string)($data[$field] ?? '')) === '') {
|
||||
throw new \RuntimeException('请完整填写仓库名称、收件信息与地址');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function normalizeIntArray(mixed $value): array
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_values(array_unique(array_filter(array_map(static function ($item) {
|
||||
$int = (int)$item;
|
||||
return $int > 0 ? $int : null;
|
||||
}, $value))));
|
||||
}
|
||||
|
||||
private function normalizeStringArray(mixed $value): array
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$items = [];
|
||||
foreach ($value as $item) {
|
||||
$text = trim((string)$item);
|
||||
if ($text === '') {
|
||||
continue;
|
||||
}
|
||||
$items[] = $text;
|
||||
}
|
||||
|
||||
return array_values(array_unique($items));
|
||||
}
|
||||
|
||||
private function decodeIntArray(mixed $value): array
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return $this->normalizeIntArray($value);
|
||||
}
|
||||
if (is_string($value) && $value !== '') {
|
||||
$decoded = json_decode($value, true);
|
||||
return is_array($decoded) ? $this->normalizeIntArray($decoded) : [];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
private function decodeStringArray(mixed $value): array
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return $this->normalizeStringArray($value);
|
||||
}
|
||||
if (is_string($value) && $value !== '') {
|
||||
$decoded = json_decode($value, true);
|
||||
return is_array($decoded) ? $this->normalizeStringArray($decoded) : [];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
private function generateWarehouseCode(string $serviceProvider): string
|
||||
{
|
||||
$prefix = $serviceProvider === 'zhongjian' ? 'ZJ' : 'AXY';
|
||||
return sprintf('%s-WH-%s', $prefix, date('YmdHis'));
|
||||
}
|
||||
|
||||
private function ensureWarehouseTable(): void
|
||||
{
|
||||
Db::execute(<<<'SQL'
|
||||
CREATE TABLE IF NOT EXISTS shipping_warehouses (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
warehouse_name VARCHAR(128) NOT NULL DEFAULT '',
|
||||
warehouse_code VARCHAR(64) NOT NULL DEFAULT '',
|
||||
warehouse_type VARCHAR(32) NOT NULL DEFAULT 'detection_center',
|
||||
service_provider VARCHAR(32) NOT NULL DEFAULT 'anxinyan',
|
||||
receiver_name VARCHAR(64) NOT NULL DEFAULT '',
|
||||
receiver_mobile VARCHAR(32) NOT NULL DEFAULT '',
|
||||
province VARCHAR(64) NOT NULL DEFAULT '',
|
||||
city VARCHAR(64) NOT NULL DEFAULT '',
|
||||
district VARCHAR(64) NOT NULL DEFAULT '',
|
||||
detail_address VARCHAR(255) NOT NULL DEFAULT '',
|
||||
service_time VARCHAR(128) NOT NULL DEFAULT '',
|
||||
notice VARCHAR(500) NOT NULL DEFAULT '',
|
||||
supported_category_ids_json JSON NULL,
|
||||
service_area_provinces_json JSON NULL,
|
||||
service_area_cities_json JSON NULL,
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'enabled',
|
||||
is_default TINYINT(1) NOT NULL DEFAULT 0,
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
remark VARCHAR(255) NOT NULL DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_shipping_warehouses_code (warehouse_code),
|
||||
KEY idx_shipping_warehouses_service_provider (service_provider),
|
||||
KEY idx_shipping_warehouses_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='收货仓库 / 检测中心';
|
||||
SQL);
|
||||
}
|
||||
|
||||
private function ensureWarehouseRuleColumns(): void
|
||||
{
|
||||
$columns = Db::query("SHOW COLUMNS FROM shipping_warehouses LIKE 'service_area_provinces_json'");
|
||||
if (!$columns) {
|
||||
Db::execute("ALTER TABLE shipping_warehouses ADD COLUMN service_area_provinces_json JSON NULL AFTER supported_category_ids_json");
|
||||
}
|
||||
|
||||
$columns = Db::query("SHOW COLUMNS FROM shipping_warehouses LIKE 'service_area_cities_json'");
|
||||
if (!$columns) {
|
||||
Db::execute("ALTER TABLE shipping_warehouses ADD COLUMN service_area_cities_json JSON NULL AFTER service_area_provinces_json");
|
||||
}
|
||||
}
|
||||
|
||||
private function ensureOrderTargetTable(): void
|
||||
{
|
||||
Db::execute(<<<'SQL'
|
||||
CREATE TABLE IF NOT EXISTS order_shipping_targets (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
order_id BIGINT UNSIGNED NOT NULL,
|
||||
warehouse_id BIGINT UNSIGNED NULL DEFAULT NULL,
|
||||
warehouse_name VARCHAR(128) NOT NULL DEFAULT '',
|
||||
warehouse_code VARCHAR(64) NOT NULL DEFAULT '',
|
||||
service_provider VARCHAR(32) NOT NULL DEFAULT 'anxinyan',
|
||||
receiver_name VARCHAR(64) NOT NULL DEFAULT '',
|
||||
receiver_mobile VARCHAR(32) NOT NULL DEFAULT '',
|
||||
province VARCHAR(64) NOT NULL DEFAULT '',
|
||||
city VARCHAR(64) NOT NULL DEFAULT '',
|
||||
district VARCHAR(64) NOT NULL DEFAULT '',
|
||||
detail_address VARCHAR(255) NOT NULL DEFAULT '',
|
||||
service_time VARCHAR(128) NOT NULL DEFAULT '',
|
||||
notice VARCHAR(500) NOT NULL DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_order_shipping_targets_order_id (order_id),
|
||||
KEY idx_order_shipping_targets_warehouse_id (warehouse_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单锁定仓库快照'
|
||||
SQL);
|
||||
}
|
||||
|
||||
private function bootstrapDefaults(): void
|
||||
{
|
||||
$count = (int)Db::name('shipping_warehouses')->count();
|
||||
if ($count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
Db::name('shipping_warehouses')->insertAll([
|
||||
[
|
||||
'warehouse_name' => '安心验鉴定中心',
|
||||
'warehouse_code' => 'AXY-WH-DEFAULT',
|
||||
'warehouse_type' => 'detection_center',
|
||||
'service_provider' => 'anxinyan',
|
||||
'receiver_name' => '安心验鉴定中心',
|
||||
'receiver_mobile' => '400-800-1314',
|
||||
'province' => '广东省',
|
||||
'city' => '深圳市',
|
||||
'district' => '南山区',
|
||||
'detail_address' => '科技园鉴定路 88 号 安心验收件中心',
|
||||
'service_time' => '周一至周日 09:30-18:30',
|
||||
'notice' => '寄送前请确认订单信息完整,包裹内附上订单号可提升签收后的处理效率。',
|
||||
'supported_category_ids_json' => null,
|
||||
'service_area_provinces_json' => null,
|
||||
'service_area_cities_json' => null,
|
||||
'status' => 'enabled',
|
||||
'is_default' => 1,
|
||||
'sort_order' => 1,
|
||||
'remark' => '默认仓库',
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'warehouse_name' => '中检合作鉴定中心',
|
||||
'warehouse_code' => 'ZJ-WH-DEFAULT',
|
||||
'warehouse_type' => 'detection_center',
|
||||
'service_provider' => 'zhongjian',
|
||||
'receiver_name' => '中检合作鉴定中心',
|
||||
'receiver_mobile' => '400-800-1314',
|
||||
'province' => '广东省',
|
||||
'city' => '深圳市',
|
||||
'district' => '南山区',
|
||||
'detail_address' => '科技园鉴定路 88 号 安心验中检收件中心',
|
||||
'service_time' => '周一至周日 09:30-18:30',
|
||||
'notice' => '中检鉴定订单请优先附上鉴定单号,寄出后尽快填写运单号。',
|
||||
'supported_category_ids_json' => null,
|
||||
'service_area_provinces_json' => null,
|
||||
'service_area_cities_json' => null,
|
||||
'status' => 'enabled',
|
||||
'is_default' => 1,
|
||||
'sort_order' => 1,
|
||||
'remark' => '默认仓库',
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
private function matchScore(array $warehouse, ?int $categoryId, ?array $userAddress): int
|
||||
{
|
||||
$score = 0;
|
||||
|
||||
if ($categoryId && (!$warehouse['supported_category_ids'] || in_array($categoryId, $warehouse['supported_category_ids'], true))) {
|
||||
$score += 200;
|
||||
}
|
||||
|
||||
if ($userAddress) {
|
||||
$province = trim((string)($userAddress['province'] ?? ''));
|
||||
$city = trim((string)($userAddress['city'] ?? ''));
|
||||
|
||||
if ($province !== '' && (!$warehouse['service_area_provinces'] || in_array($province, $warehouse['service_area_provinces'], true))) {
|
||||
$score += 120;
|
||||
}
|
||||
|
||||
if ($city !== '' && (!$warehouse['service_area_cities'] || in_array($city, $warehouse['service_area_cities'], true))) {
|
||||
$score += 180;
|
||||
}
|
||||
}
|
||||
|
||||
if ($warehouse['is_default']) {
|
||||
$score += 40;
|
||||
}
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
private function recommendedReason(array $warehouse, ?int $categoryId, ?array $userAddress): string
|
||||
{
|
||||
$reasons = [];
|
||||
|
||||
if ($categoryId && (!$warehouse['supported_category_ids'] || in_array($categoryId, $warehouse['supported_category_ids'], true))) {
|
||||
$reasons[] = '匹配当前品类';
|
||||
}
|
||||
|
||||
if ($userAddress) {
|
||||
$province = trim((string)($userAddress['province'] ?? ''));
|
||||
$city = trim((string)($userAddress['city'] ?? ''));
|
||||
|
||||
if ($city !== '' && (!$warehouse['service_area_cities'] || in_array($city, $warehouse['service_area_cities'], true))) {
|
||||
$reasons[] = '匹配当前城市';
|
||||
} elseif ($province !== '' && (!$warehouse['service_area_provinces'] || in_array($province, $warehouse['service_area_provinces'], true))) {
|
||||
$reasons[] = '匹配当前省份';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$reasons && $warehouse['is_default']) {
|
||||
$reasons[] = '默认仓库';
|
||||
}
|
||||
|
||||
return implode(' / ', $reasons);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user