'处方订单', self::ORDER_TYPE_SHOP => '商城订单', self::ORDER_TYPE_SHOP_PRESCRIPTION => '商城处方订单', ]; // 订单类型 public const TYPE_WECHAT = 1; public const TYPE_ALIPAY = 2; public const TYPE_BANK = 3; public const TYPE_OTHER = 4; public const TYPE = [ self::TYPE_WECHAT => '微信', self::TYPE_ALIPAY => '支付宝', self::TYPE_BANK => '银行卡', self::TYPE_OTHER => '其他', ]; // 是否支付 public const IS_PAY_FALSE = 0; public const IS_PAY_TRUE = 1; public const IS_PAY = [ self::IS_PAY_FALSE => '否', self::IS_PAY_TRUE => '是', ]; // 是否互医订单 public const IS_ONLINE_FALSE = 0; public const IS_ONLINE_TRUE = 1; public const IS_ONLINE = [ self::IS_ONLINE_FALSE => '否', self::IS_ONLINE_TRUE => '是', ]; // 订单状态 const STATUS_UNPAID = 0; const STATUS_WAIT_SEND = 1; const STATUS_WAIT_ACCEPT = 2; const STATUS_WAIT_COMMENT = 3; const STATUS_REFUND = 4; const STATUS_REFUNDING = 5; const STATUS_ACCEPTED = 6; const STATUS_CONFIRM = 7; const STATUS_CANCEL = 9; const STATUS = [ self::STATUS_UNPAID => '未支付', self::STATUS_WAIT_SEND => '待发货', self::STATUS_WAIT_ACCEPT => '待收货', self::STATUS_WAIT_COMMENT => '待评价', self::STATUS_REFUND => '已退款', self::STATUS_REFUNDING => '退款中', self::STATUS_ACCEPTED => '已收货', self::STATUS_CONFIRM => '确认收货', self::STATUS_CANCEL => '已取消', ]; // 取消状态 const CANCEL_STATUS_FALSE = 0; const CANCEL_STATUS_TRUE = 1; const CANCEL_STATUS = [ self::CANCEL_STATUS_FALSE => '未取消', self::CANCEL_STATUS_TRUE => '已取消', ]; // 退款状态 const REFUND_STATUS_NORMAL = 0; const REFUND_STATUS_APPLYING = 1; const REFUND_STATUS_AGREE = 2; const REFUND_STATUS_END = 3; const REFUND_STATUS_PART = 4; const REFUND_STATUS_CANCEL = 9; const REFUND_STATUS = [ self::REFUND_STATUS_NORMAL => '正常', self::REFUND_STATUS_APPLYING => '申请中', self::REFUND_STATUS_AGREE => '同意申请', self::REFUND_STATUS_END => '退款完成', self::REFUND_STATUS_PART => '部分退款完成', self::REFUND_STATUS_CANCEL => '取消退款申请', ]; // 支付方式 public const PAY_METHOD_ONLINE = 1; public const PAY_METHOD_OFFLINE = 2; public const PAY_METHOD = [ self::PAY_METHOD_ONLINE => '线上', self::PAY_METHOD_OFFLINE => '线下', ]; // 支付方式 public const FREE_SHIP_FALSE = 0; public const FREE_SHIP_TRUE = 1; public const FREE_SHIP = [ self::FREE_SHIP_FALSE => '不包邮', self::FREE_SHIP_TRUE => '包邮', ]; /** * @comment 门店 * @return BelongsTo */ public function store(): BelongsTo { return $this->belongsTo(Store::class, 'store_id'); } /** * @comment 订单商品明细 * @return HasMany */ public function items(): HasMany { return $this->hasMany(ProductOrderItem::class, 'product_order_id'); } /** * @comment 退款单 * @return HasMany */ public function refunds(): HasMany { return $this->hasMany(ProductOrderRefund::class, 'order_id'); } /** * @comment 订单日志 * @return HasMany */ public function logs(): HasMany { return $this->hasMany(ProductOrderLog::class, 'p_id'); } /** * @comment 支付单 * @return MorphMany */ public function bills(): MorphMany { return $this->morphMany(Bill::class, 'billable'); } /** * @comment 已支付的支付单 * @return MorphOne */ public function billed(): MorphOne { return $this->morphOne(Bill::class, 'billable')->where('bill_status', Bill::BILL_STATUS_SUCCESSFUL)->latest(); } /** * @comment 物流信息 * @return BelongsTo */ public function expressNo(): BelongsTo { return $this->belongsTo(ExpressNo::class, 'express_no_id'); } /** * @comment 处方 * @return BelongsTo */ public function prescription(): BelongsTo { return $this->belongsTo(Prescription::class, 'p_id'); } /** * status_string * * @comment 状态名称 * @return string */ public function getStatusStringAttribute(): string { return self::STATUS[$this['status']] ?? ''; } /** * type_string * * @comment 支付类型 * @return string */ public function getTypeStringAttribute(): string { return self::TYPE[$this->type] ?? ''; } /** * cancel_status_string * * @comment 取消状态 * @return string */ public function getCancelStatusStringAttribute(): string { return self::CANCEL_STATUS[$this->cancel_status] ?? ''; } /** * refund_status_string * * @comment 退款状态 * @return string */ public function getRefundStatusStringAttribute(): string { return self::CANCEL_STATUS[$this->refund_status] ?? ''; } /** * 支付成功处理 * * @param Bill $bill * @return void */ public function handlePied(Bill $bill): void { $this->is_pay = self::IS_PAY_TRUE; $this->pay_time = strtotime($bill->pay_at); $this->status = self::STATUS_WAIT_SEND; $this->save(); $this->logs()->create([ 'content' => '订单支付成功 - ' . $this->type_string, ]); $this->createFundWater($this); $this->createNotice($this, '您的订单已支付成功'); $this->loadMissing(['items.drugStoreRelation' => fn(Relation $relation) => $relation->where('store_id', $this->store_id)]); foreach ($this->items as $item) { if ($item->drugStoreRelation) { $item->drugStoreRelation->true_sales_volume += $item->number; $item->drugStoreRelation->save(); } } // // 同步数据 // $this->refresh(); // $this->load(['items']); // Artisan::call('data:sync', [ // '--type' => 'product_order_sync', // '--data' => $this->toArray(), // ]); if ($this->is_online == self::IS_ONLINE_TRUE && $this->sync_order_no) { // 同步数据(老) Artisan::call('data:sync-old', [ '--type' => 'syncOrder', '--data' => json_encode([ 'order_no' => $this->sync_order_no, 'status' => 1, // 1已支付 2已取消 3已退款 'time' => $bill->pay_at, ]), ]); } } /** * 退款操作 * * @throws \Throwable */ public function toRefund(int|string|float $refundAmount, $refundNo = null): array { if ($this->is_pay == ProductOrder::IS_PAY_FALSE) { $message = '订单未支付:' . "[productOrderId:$this->id]"; log_s($message, 'order', 'refund'); return json_result($message, [], 1); } if ($this->cancel_status == ProductOrder::CANCEL_STATUS_TRUE) { $message = '订单已取消:' . "[productOrderId:$this->id]"; log_s($message, 'order', 'refund'); return json_result($message, [], 1); } if ($this->refund_status == ProductOrder::REFUND_STATUS_PART) { $message = '订单已退款完成:' . "[productOrderId:$this->id]"; log_s($message, 'order', 'refund'); return json_result($message, [], 1); } if (in_array($this->status, [ ProductOrder::STATUS_UNPAID, ProductOrder::STATUS_REFUND, ProductOrder::STATUS_CANCEL, ])) { $message = '退款失败,订单状态为:' . $this->status_string . "[productOrderId:$this->id]"; log_s($message, 'order', 'refund'); return json_result($message, [], 1); } $this->loadMissing('billed'); if (!$this->billed) { $message = '退款失败,无已支付的支付单:' . "[productOrderId:$this->id]"; log_s($message, 'order', 'refund'); return json_result($message, [], 1); } if ($this->billed->can_refund_amount < $refundAmount) { $message = '退款失败,申请金额超过可退金额不足:' . "[productOrderId:$this->id]"; log_s($message, 'order', 'refund'); return json_result($message, [], 1); } DB::beginTransaction(); try { $data = [ 'refund_amount' => $refundAmount, ]; if ($refundNo) { $data['refund_no'] = $refundNo; } /* @var RefundBill $refundBill */ $refundBill = $this->billed->refunds()->create($data); $refundNo = $refundBill->refund_no; $order = [ 'out_trade_no' => $this->billed->pay_no, 'out_refund_no' => $refundBill->refund_no, 'amount' => [ 'refund' => $refundBill->refund_amount * 100, 'total' => $this->billed->pay_amount * 100, 'currency' => 'CNY', ], ]; $result = Pay::wechat()->refund($order); if (isset($result['code'])) { $message = '退款失败:' . ($result['message'] ?? ''); log_s($message, 'order', 'refund'); return json_result($message, [], 1); } $this->logs()->create([ 'content' => "开始退款:{$this->billed->pay_way_string}[$refundBill->refund_amount]" ]); DB::commit(); $message = '退款申请成功:' . var_export($result, true); log_s($message, 'order', 'refund'); return json_result('退款申请成功', ['refund_no' => $refundNo]); } catch (Exception $exception) { DB::rollBack(); $message = '退款错误:' . "[productOrderId:$this->id]" . $exception->getMessage() . $exception->getTraceAsString(); log_s($message, 'order', 'error'); return json_result($message, [], 1); } } /** * 退款成功处理 * * @param RefundBill $refundBill * @return void */ public function handleRefunded(RefundBill $refundBill): void { $this->status = self::STATUS_REFUND; $this->refund_status = ProductOrder::REFUND_STATUS_END; $this->save(); $refund = ProductOrderRefund::where('refund_no', $refundBill->refund_no)->first(); $refund->update([ 'is_refund' => ProductOrderRefund::IS_REFUND_TRUE, 'refund_time' => $refundBill->refund_at, 'status' => ProductOrderRefund::STATUS_PASS, ]); $this->logs()->create([ 'content' => '订单退款成功 - ' . $this->type_string, ]); $this->createNotice($this, '您的订单已退款成功'); $this->loadMissing(['items.drugstoreDrug' => fn(Relation $relation) => $relation->where('drugstore_id', $this->drugstore_id)]); foreach ($this->items as $item) { if ($item->drugstoreDrug) { $item->drugstoreDrug->stock += $item->number; $item->drugstoreDrug->frozen_number -= $item->number; $item->drugstoreDrug->save(); } } // // 同步数据 // $this->refresh(); // $this->load(['items']); // Artisan::call('data:sync', [ // '--type' => 'product_order_sync', // '--data' => $this->toArray(), // ]); if ($this->is_online == self::IS_ONLINE_TRUE && $this->sync_order_no) { // 同步数据(老) Artisan::call('data:sync-old', [ '--type' => 'syncOrder', '--data' => json_encode([ 'order_no' => $this->sync_order_no, 'status' => 3, // 1已支付 2已取消 3已退款 'time' => $refundBill->refund_at, ]), ]); } } }