diff --git a/backend/app/Model/Order.php b/backend/app/Model/Order.php index fcd37bc..de1dc0e 100644 --- a/backend/app/Model/Order.php +++ b/backend/app/Model/Order.php @@ -9,10 +9,8 @@ use Hyperf\DbConnection\Model\Model; /** * @property int $id 主键 * @property int $company_id 公司 ID 与 Tools 保持一致 - * @property int $company_id 公司 ID 与 Tools 保持一致 * @property int $platform_id 平台 ID 与 Tools 保持一致 * @property int $store_id 店铺 ID 与 Tools 保持一致 - * @property int $store_id 店铺 ID 与 Tools 保持一致 * @property int $order_status_id 订单状态 ID * @property string $platform_order_id 平台 订单 ID * @property string $buyer_user_id 平台买家 id @@ -30,7 +28,6 @@ use Hyperf\DbConnection\Model\Model; * @property string $voucher_amount 代金券 - 兑换券金额 * @property int $order_type_id 订单类型 ID, 默认为一般订单,部分平台可能有补差价,代金券订单等 * @property string $created_date 订单的创建时间 - * @property string $created_date 订单的创建时间 * @property string $updated_date 订单的更新时间 * @property string $paid_date 订单的付款时间 * @property string $shipping_date 订单的发货时间 @@ -54,10 +51,20 @@ class Order extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['id', 'company_id', 'company_id', 'platform_id', 'store_id', 'store_id', 'order_status_id', 'platform_order_id', 'buyer_user_id', 'payment_method_id', 'presale', 'total_amount', 'total_paid', 'total_discount', 'total_received', 'freight_fee', 'tax_fee', 'discount_fee', 'commission_fee', 'coupon_amount', 'voucher_amount', 'order_type_id', 'created_date', 'created_date', 'updated_date', 'paid_date', 'shipping_date', 'zipcode', 'city', 'province', 'country', 'raw', 'ext', 'created_at', 'updated_at']; + protected array $fillable = ['id', 'company_id', 'platform_id', 'store_id', 'order_status_id', 'platform_order_id', 'buyer_user_id', 'payment_method_id', 'presale', 'total_amount', 'total_paid', 'total_discount', 'total_received', 'freight_fee', 'tax_fee', 'discount_fee', 'commission_fee', 'coupon_amount', 'voucher_amount', 'order_type_id', 'created_date', 'updated_date', 'paid_date', 'shipping_date', 'zipcode', 'city', 'province', 'country', 'raw', 'ext', 'created_at', 'updated_at']; /** * The attributes that should be cast to native types. */ - protected array $casts = ['id' => 'integer', 'company_id' => 'integer', 'company_id' => 'integer', 'platform_id' => 'integer', 'store_id' => 'integer', 'store_id' => 'integer', 'order_status_id' => 'integer', 'payment_method_id' => 'integer', 'presale' => 'boolean', 'order_type_id' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime']; + protected array $casts = ['id' => 'integer', 'company_id' => 'integer', 'platform_id' => 'integer', 'store_id' => 'integer', 'order_status_id' => 'integer', 'payment_method_id' => 'integer', 'presale' => 'boolean', 'order_type_id' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime']; + + + /** + * Get the order items for the order. + */ + public function items() + { + return $this->hasMany(OrderItem::class, 'order_id', 'id'); + } } + diff --git a/backend/app/Model/OrderItem.php b/backend/app/Model/OrderItem.php new file mode 100644 index 0000000..891bab9 --- /dev/null +++ b/backend/app/Model/OrderItem.php @@ -0,0 +1,55 @@ + 'integer', 'company_id' => 'integer', 'platform_id' => 'integer', 'store_id' => 'integer', 'order_id' => 'integer', 'sub_order_type_id' => 'integer', 'product_id' => 'integer', 'quantity' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime']; + + /** + * Get the order that owns the order item. + */ + public function order() + { + return $this->belongsTo(Order::class, 'order_id', 'id'); + } +} diff --git a/backend/app/Platform/Tmall/TmallOrderParser.php b/backend/app/Platform/Tmall/EntityParse/Order.php similarity index 68% rename from backend/app/Platform/Tmall/TmallOrderParser.php rename to backend/app/Platform/Tmall/EntityParse/Order.php index c891405..80edd0e 100644 --- a/backend/app/Platform/Tmall/TmallOrderParser.php +++ b/backend/app/Platform/Tmall/EntityParse/Order.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Platform\Tmall; +namespace App\Platform\Tmall\EntityParse; use App\Model\Company; use App\Model\Model as Entity; @@ -16,7 +16,7 @@ use InvalidArgumentException; * * 展示如何继承 EntityParse 实现自定义解析逻辑 */ -class TmallOrderParser extends EntityParse +class Order extends EntityParse { /** * 公司作用域匹配 @@ -107,12 +107,45 @@ class TmallOrderParser extends EntityParse } /** - * 可选:覆盖唯一标识符提取逻辑 + * 获取实体的唯一键字段(用于 upsert 的 uniqueBy 参数) * - * 如果使用默认的 unique_id 提取逻辑,则无需覆盖此方法 + * 定义订单的唯一约束字段组合 + * + * @return array 唯一键字段名数组 */ - // public function entityUniqueIdentifierExtract(array $metadata): string|int - // { - // return $metadata['custom_id_field'] ?? throw new InvalidArgumentException('custom_id_field not found'); - // } + public function getUniqueBy(): array + { + // 天猫订单的唯一性由店铺 + 平台订单号确定 + return ['store_id', 'platform_order_id']; + } + + /** + * 获取可更新的字段列表(用于 upsert 的 update 参数) + * + * 明确定义哪些字段在更新时可以被修改 + * 排除:主键、唯一键、创建时间、关联 ID 等不应变更的字段 + * + * @return array 可更新字段名数组 + */ + public function getUpdateFields(): array + { + // 方案1:手动指定可更新字段(推荐,最明确) + return [ + 'order_status_id', + 'payment_method_id', + 'buyer_user_id', + 'total_amount', + 'updated_date', + 'raw', + // 根据实际业务需求添加其他可更新字段 + ]; + + // 方案2:动态计算(如果字段较多且经常变动) + // $entity = $this->entityMatch($this->getData()); + // $excludeFields = array_merge( + // ['id', 'created_at', 'created_date', 'company_id', 'platform_id'], + // $this->getUniqueBy() + // ); + // return $this->getTableColumnsExcept($entity, $excludeFields); + } } diff --git a/backend/migrations/2025_12_12_130906_add_foreign_key_to_order_items_table.php b/backend/migrations/2025_12_12_130906_add_foreign_key_to_order_items_table.php new file mode 100644 index 0000000..00d8606 --- /dev/null +++ b/backend/migrations/2025_12_12_130906_add_foreign_key_to_order_items_table.php @@ -0,0 +1,31 @@ +foreign('order_id') + ->references('id') + ->on('orders') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('order_items', function (Blueprint $table) { + $table->dropForeign(['order_id']); + }); + } +};