getStore()->getTimezoneString(); $refund_fee = (float) ($record['refund_fee'] ?? 0); yield [ 'company_id' => $this->getCompany()->id, 'platform_id' => $this->getPlatform()->id, 'store_id' => $this->getStore()->id, 'order_id' => null, 'platform_order_id' => strval($record['tid']), 'platform_refund_id' => strval($record['refund_id']), 'refund_status_id' => $this->getRefundStatusId($record['status']), 'refund_type_id' => $this->getRefundTypeId($record), 'reason' => $record['reason'] ?? null, 'refund_amount' => $refund_fee, 'freight_refund' => 0, 'refund_total' => $refund_fee, 'currency' => 'CNY', 'buyer_user_id' => $record['buyer_open_uid'] ?? null, 'order_created_date' => Carbon::parse($record['created'], $tz)->format('Y-m-d H:i:sP'), 'order_paid_date' => Carbon::parse($record['created'], $tz)->format('Y-m-d H:i:sP'), 'created_date' => Carbon::parse($record['created'], $tz)->format('Y-m-d H:i:sP'), 'updated_date' => isset($record['modified']) ? Carbon::parse($record['modified'], $tz)->format('Y-m-d H:i:sP') : null, 'completed_date' => isset($record['end_time']) ? Carbon::parse($record['end_time'], $tz)->format('Y-m-d H:i:sP') : null, 'raw' => $raw, 'ext' => null, 'hash' => \md5($raw), 'created_at' => Carbon::now()->format('Y-m-d H:i:sP'), 'updated_at' => Carbon::now()->format('Y-m-d H:i:sP'), ]; } }); } /** * 获取实体的唯一键字段(用于 upsert 的 uniqueBy 参数) * * @return array */ public function getUniqueBy(): array { return ['store_id', 'platform_refund_id']; } /** * 获取可更新的字段列表(用于 upsert 的 update 参数) * * @return array */ public function getUpdateFields(): array { return [ 'order_id', 'refund_status_id', 'refund_type_id', 'reason', 'refund_amount', 'freight_refund', 'refund_total', 'buyer_user_id', 'updated_date', 'completed_date', 'raw', 'ext', 'hash', 'updated_at', ]; } /** * 格式化退款子项数据 - 映射到 refund_items 表 * * Tmall 每个售后单同时作为一条 refund_item 记录 * 需要在 refunds upsert 完成后调用,以获取 refund_id 映射 * * @param array $raw_data 原始数据数组 * @param array $platform_refund_id_to_local_refund_id_map [platform_refund_id => local db refund id] * @return array */ public function formatRefundItemsFromRaw(array $raw_data, array $platform_refund_id_to_local_refund_id_map): array { $records = isset($raw_data[0]) ? $raw_data : [$raw_data]; $items = []; foreach ($records as $record) { $platform_refund_id = strval($record['refund_id']); $refund_id = $platform_refund_id_to_local_refund_id_map[$platform_refund_id] ?? 0; $tz = $this->getStore()->getTimezoneString(); $raw = \json_encode($record); $items[] = [ 'company_id' => $this->getCompany()->id, 'platform_id' => $this->getPlatform()->id, 'store_id' => $this->getStore()->id, 'refund_id' => $refund_id, 'platform_parent_refund_id' => '', 'platform_refund_id' => $platform_refund_id, 'refund_status_id' => $this->getRefundStatusId($record['status']), 'refund_type_id' => $this->getRefundTypeId($record), 'reason' => $record['reason'] ?? null, 'currency' => 'CNY', 'buyer_user_id' => $record['buyer_open_uid'] ?? null, 'platform_order_id' => strval($record['tid']), 'platform_sub_order_id' => strval($record['oid']), 'platform_product_id' => isset($record['num_iid']) ? strval($record['num_iid']) : null, 'quantity' => $record['num'] ?? 0, 'refund_amount' => (float) ($record['refund_fee'] ?? 0), 'order_created_date' => Carbon::parse($record['created'], $tz)->format('Y-m-d H:i:sP'), 'order_paid_date' => Carbon::parse($record['created'], $tz)->format('Y-m-d H:i:sP'), 'created_date' => Carbon::parse($record['created'], $tz)->format('Y-m-d H:i:sP'), 'updated_date' => isset($record['modified']) ? Carbon::parse($record['modified'], $tz)->format('Y-m-d H:i:sP') : null, 'completed_date' => isset($record['end_time']) ? Carbon::parse($record['end_time'], $tz)->format('Y-m-d H:i:sP') : null, 'raw' => $raw, 'ext' => null, 'created_at' => Carbon::now()->format('Y-m-d H:i:sP'), 'updated_at' => Carbon::now()->format('Y-m-d H:i:sP'), ]; } return $items; } /** * 将 Tmall 退款状态映射为系统退款状态 ID * * @param string $platformStatus * @return int */ public function getRefundStatusId(string $platform_status): int { $map = $this->refundStatusMap(); return $map[$platform_status] ?? RefundStatus::APPLIED->value; } /** * Tmall 退款状态 → 系统退款状态映射 * * @return array */ private function refundStatusMap(): array { return [ TmallRefundStatus::WAIT_SELLER_AGREE->value => RefundStatus::APPLIED->value, TmallRefundStatus::WAIT_BUYER_RETURN_GOODS->value => RefundStatus::SELLER_ACCEPTED->value, TmallRefundStatus::WAIT_SELLER_CONFIRM_GOODS->value => RefundStatus::SELLER_ACCEPTED->value, TmallRefundStatus::SELLER_REFUSE_BUYER->value => RefundStatus::REFUSED->value, TmallRefundStatus::SUCCESS->value => RefundStatus::SUCCESS->value, TmallRefundStatus::CLOSED->value => RefundStatus::CLOSED->value, ]; } /** * 根据 Tmall 售后单数据判断退款类型 * * @param array $record 单条售后单原始数据 * @return int */ public function getRefundTypeId(array $record): int { $has_good_return = $record['has_good_return'] ?? false; $good_status = $record['good_status'] ?? ''; // 买家已退货或等待退货 → 退货退款 if ($has_good_return) { return RefundType::RETURN_AND_REFUND->value; } // 买家未收到货 → 仅退款 if ($good_status === 'BUYER_NOT_RECEIVED') { return RefundType::REFUND_ONLY->value; } // 买家已收货但无须退货 → 退款无须退货 if ($good_status === 'BUYER_RECEIVED') { return RefundType::REFUND_WITHOUT_RETURN->value; } return RefundType::REFUND_ONLY->value; } }