更新
This commit is contained in:
@@ -5827,7 +5827,20 @@ class YejiStatsLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
$payMap = self::commissionSettlementBatchPayTsMap($orderIds);
|
$payMap = self::commissionSettlementBatchPayTsMap($orderIds);
|
||||||
$signMap = self::commissionSettlementBatchSignTsMapForOrderIds($orderIds);
|
|
||||||
|
$signItems = [];
|
||||||
|
foreach ($rows as $r) {
|
||||||
|
$oid = (int) ($r['id'] ?? 0);
|
||||||
|
if ($oid <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$signItems[] = [
|
||||||
|
'order_id' => $oid,
|
||||||
|
'tracking_number' => trim((string) ($r['tracking_number'] ?? '')),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// 与快递单详情 / logisticsTrace 同源:PHP 推导含 trace_time 字符串回填,避免 SQL 仅认 trace_time_stamp 导致误为空
|
||||||
|
$signMap = ExpressTrackingService::batchResolveSignUnixFromDbForOrders($signItems);
|
||||||
|
|
||||||
foreach ($rows as &$r) {
|
foreach ($rows as &$r) {
|
||||||
$oid = (int) ($r['id'] ?? 0);
|
$oid = (int) ($r['id'] ?? 0);
|
||||||
@@ -5836,14 +5849,19 @@ class YejiStatsLogic
|
|||||||
}
|
}
|
||||||
$signTs = (int) ($signMap[$oid] ?? 0);
|
$signTs = (int) ($signMap[$oid] ?? 0);
|
||||||
if ($signTs <= 0) {
|
if ($signTs <= 0) {
|
||||||
$tn = trim((string) ($r['tracking_number'] ?? ''));
|
if ($allowKuaidiFallback && $oid > 0) {
|
||||||
if ($tn !== '') {
|
// 与 logisticsTrace 一致:库内无轨迹时 queryAndUpdate 落库后再解析
|
||||||
$signTs = ExpressTrackingService::resolveSignUnixTimeForCommission(
|
$signTs = ExpressTrackingService::syncSignUnixFromLogisticsForPrescriptionOrder($oid, true);
|
||||||
$tn,
|
} else {
|
||||||
(string) ($r['express_company'] ?? 'auto'),
|
$tn = trim((string) ($r['tracking_number'] ?? ''));
|
||||||
(string) ($r['recipient_phone'] ?? ''),
|
if ($tn !== '') {
|
||||||
$allowKuaidiFallback
|
$signTs = ExpressTrackingService::resolveSignUnixTimeForCommission(
|
||||||
);
|
$tn,
|
||||||
|
(string) ($r['express_company'] ?? 'auto'),
|
||||||
|
(string) ($r['recipient_phone'] ?? ''),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$r['sign_ts'] = $signTs;
|
$r['sign_ts'] = $signTs;
|
||||||
@@ -6798,7 +6816,7 @@ class YejiStatsLogic
|
|||||||
->page($page, $pageSize)
|
->page($page, $pageSize)
|
||||||
->select()
|
->select()
|
||||||
->toArray();
|
->toArray();
|
||||||
$pageRows = self::commissionSettlementHydrateSignPay($pageRows, false);
|
$pageRows = self::commissionSettlementHydrateSignPay($pageRows, true);
|
||||||
|
|
||||||
[$linkedApptByOrderId, $apptChannelsDictMap] =
|
[$linkedApptByOrderId, $apptChannelsDictMap] =
|
||||||
self::commissionSettlementLoadApptContextForOrders($pageRows);
|
self::commissionSettlementLoadApptContextForOrders($pageRows);
|
||||||
@@ -6835,7 +6853,7 @@ class YejiStatsLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bucket=current|deferred:分块判定签收/尾款后再 PHP 分页
|
// bucket=current|deferred:分块判定签收/尾款后再 PHP 分页
|
||||||
[$matchingIds, $signPayById] = self::commissionSettlementCollectBucketMatchingOrders(
|
[$matchingIds] = self::commissionSettlementCollectBucketMatchingOrders(
|
||||||
$pack,
|
$pack,
|
||||||
$params,
|
$params,
|
||||||
$linesAssistScopeFlip,
|
$linesAssistScopeFlip,
|
||||||
@@ -6865,14 +6883,8 @@ class YejiStatsLogic
|
|||||||
->order('o.id', 'desc')
|
->order('o.id', 'desc')
|
||||||
->select()
|
->select()
|
||||||
->toArray();
|
->toArray();
|
||||||
foreach ($pageRows as &$r) {
|
// 明细展示:库内解析后仍缺签收时,与 logisticsTrace 一致补查快递100(仅当前页)
|
||||||
$oid = (int) ($r['id'] ?? 0);
|
$pageRows = self::commissionSettlementHydrateSignPay($pageRows, true);
|
||||||
if ($oid > 0 && isset($signPayById[$oid])) {
|
|
||||||
$r['sign_ts'] = $signPayById[$oid]['sign_ts'];
|
|
||||||
$r['pay_ts'] = $signPayById[$oid]['pay_ts'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($r);
|
|
||||||
|
|
||||||
[$linkedApptByOrderId, $apptChannelsDictMap] =
|
[$linkedApptByOrderId, $apptChannelsDictMap] =
|
||||||
self::commissionSettlementLoadApptContextForOrders($pageRows);
|
self::commissionSettlementLoadApptContextForOrders($pageRows);
|
||||||
|
|||||||
@@ -1086,11 +1086,21 @@ class ExpressTrackingService
|
|||||||
|
|
||||||
$detail = self::loadTrackingDetailNormalized($num);
|
$detail = self::loadTrackingDetailNormalized($num);
|
||||||
if (is_array($detail)) {
|
if (is_array($detail)) {
|
||||||
$fromDb = self::effectiveSignUnixFromTrackingDetail($detail);
|
// 与 logisticsTrace:库内有轨迹明细时才视为「库内可查」
|
||||||
if ($fromDb > 0) {
|
if (!empty($detail['traces'])) {
|
||||||
$memo[$cacheKey] = $fromDb;
|
$fromDb = self::effectiveSignUnixFromTrackingDetail($detail);
|
||||||
|
if ($fromDb > 0) {
|
||||||
|
$memo[$cacheKey] = $fromDb;
|
||||||
|
|
||||||
return $fromDb;
|
return $fromDb;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$fromHead = self::effectiveSignUnixFromTrackingDetail($detail);
|
||||||
|
if ($fromHead > 0) {
|
||||||
|
$memo[$cacheKey] = $fromHead;
|
||||||
|
|
||||||
|
return $fromHead;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1100,10 +1110,7 @@ class ExpressTrackingService
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ec = strtolower(trim($expressCompany));
|
$ec = ExpressTrackService::normalizeExpressCompanyCode($num, (string) $expressCompany);
|
||||||
if ($ec === '') {
|
|
||||||
$ec = 'auto';
|
|
||||||
}
|
|
||||||
$api = ExpressTrackService::query($ec, $num, $recipientPhone, '');
|
$api = ExpressTrackService::query($ec, $num, $recipientPhone, '');
|
||||||
$fromApi = self::effectiveSignUnixFromKuaidiPayload($api);
|
$fromApi = self::effectiveSignUnixFromKuaidiPayload($api);
|
||||||
$memo[$cacheKey] = $fromApi;
|
$memo[$cacheKey] = $fromApi;
|
||||||
@@ -1111,6 +1118,94 @@ class ExpressTrackingService
|
|||||||
return $fromApi;
|
return $fromApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按业务订单 id 解析签收时间,与 PrescriptionOrderLogic::logisticsTrace 同口径。
|
||||||
|
* allowHttp 为 true 时:库内无轨迹则 queryAndUpdate 落库后再读,避免「快递单 API 已签收、提成结算库内为空」。
|
||||||
|
*/
|
||||||
|
public static function syncSignUnixFromLogisticsForPrescriptionOrder(int $orderId, bool $allowHttp = true): int
|
||||||
|
{
|
||||||
|
static $memo = [];
|
||||||
|
$cacheKey = $orderId . '|' . ($allowHttp ? '1' : '0');
|
||||||
|
if (isset($memo[$cacheKey])) {
|
||||||
|
return $memo[$cacheKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
$order = PrescriptionOrder::where('id', $orderId)->whereNull('delete_time')->find();
|
||||||
|
if (!$order) {
|
||||||
|
$memo[$cacheKey] = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$num = trim((string) ($order->tracking_number ?? ''));
|
||||||
|
if ($num === '') {
|
||||||
|
$memo[$cacheKey] = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$detail = self::loadTrackingDetailNormalized($num);
|
||||||
|
if (is_array($detail)) {
|
||||||
|
if (!empty($detail['traces'])) {
|
||||||
|
$fromDb = self::effectiveSignUnixFromTrackingDetail($detail);
|
||||||
|
if ($fromDb > 0) {
|
||||||
|
$memo[$cacheKey] = $fromDb;
|
||||||
|
|
||||||
|
return $fromDb;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$fromHead = self::effectiveSignUnixFromTrackingDetail($detail);
|
||||||
|
if ($fromHead > 0) {
|
||||||
|
$memo[$cacheKey] = $fromHead;
|
||||||
|
|
||||||
|
return $fromHead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$allowHttp) {
|
||||||
|
$memo[$cacheKey] = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tracking = self::resolveTrackingByNumber($num);
|
||||||
|
if ($tracking) {
|
||||||
|
try {
|
||||||
|
self::queryAndUpdate((int) $tracking->id, false);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::warning('syncSignUnixFromLogisticsForPrescriptionOrder queryAndUpdate failed: ' . $e->getMessage(), [
|
||||||
|
'order_id' => $orderId,
|
||||||
|
'tracking_number' => $num,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$detailAfter = self::loadTrackingDetailNormalized($num);
|
||||||
|
if (is_array($detailAfter)) {
|
||||||
|
$fromDb = self::effectiveSignUnixFromTrackingDetail($detailAfter);
|
||||||
|
if ($fromDb > 0) {
|
||||||
|
$memo[$cacheKey] = $fromDb;
|
||||||
|
|
||||||
|
return $fromDb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ec = ExpressTrackService::normalizeExpressCompanyCode(
|
||||||
|
$num,
|
||||||
|
(string) ($order->express_company ?? 'auto')
|
||||||
|
);
|
||||||
|
$api = ExpressTrackService::query(
|
||||||
|
$ec,
|
||||||
|
$num,
|
||||||
|
(string) ($order->recipient_phone ?? ''),
|
||||||
|
''
|
||||||
|
);
|
||||||
|
$fromApi = self::effectiveSignUnixFromKuaidiPayload($api);
|
||||||
|
$memo[$cacheKey] = $fromApi;
|
||||||
|
|
||||||
|
return $fromApi;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单号精确匹配失败时尝试 TRIM(TrackingNumber)(历史数据首尾空格)。
|
* 单号精确匹配失败时尝试 TRIM(TrackingNumber)(历史数据首尾空格)。
|
||||||
*
|
*
|
||||||
@@ -1188,7 +1283,26 @@ class ExpressTrackingService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return max($a, $b, $c);
|
return max($a, $b, $c, self::signedTrackingHeadFallbackUnix($detail, $stateOk));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已签收但 sign_time / 轨迹时间戳均未写入时,用主表 latest_trace_time 回填(甘草等同步路径常见)。
|
||||||
|
*
|
||||||
|
* @param array<string, mixed> $detail
|
||||||
|
*/
|
||||||
|
private static function signedTrackingHeadFallbackUnix(array $detail, bool $stateOk): int
|
||||||
|
{
|
||||||
|
if (!$stateOk) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$ltRaw = trim((string) ($detail['latest_trace_time'] ?? ''));
|
||||||
|
if ($ltRaw === '') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$parsed = strtotime($ltRaw);
|
||||||
|
|
||||||
|
return ($parsed !== false && $parsed > 0) ? (int) $parsed : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user