You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
385 lines
12 KiB
385 lines
12 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Dictionary\Order\NotifyStatus;
|
|
use App\Dictionary\Order\PayMode;
|
|
use App\Dictionary\Order\PayType;
|
|
use App\Dictionary\Order\SourceId;
|
|
use App\Dictionary\Order\Status;
|
|
use App\Dictionary\Order\Type;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
|
|
|
/**
|
|
* @method where(string $string, string $id)
|
|
* @method create(array $order_info)
|
|
*/
|
|
class Order extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
protected $table = 'orders';
|
|
|
|
/**
|
|
* The attributes that should be hidden for serialization.
|
|
*
|
|
* @var array<int, string>
|
|
*/
|
|
protected $fillable = [
|
|
'relate_id',
|
|
'order_id',
|
|
'his_order_id',
|
|
'transaction_id',
|
|
'status',
|
|
'notify_status',
|
|
'type',
|
|
'pay_type',
|
|
'pay_mode',
|
|
'fee',
|
|
'self_fee',
|
|
'reduce_fee',
|
|
'refund_fee',
|
|
'open_id',
|
|
'patient_id',
|
|
'patient_name',
|
|
'source_id',
|
|
'payment_at',
|
|
'refunded_at',
|
|
];
|
|
|
|
/**
|
|
* The attributes that should be cast.
|
|
*
|
|
* @var array<string, string>
|
|
*/
|
|
protected $casts = [
|
|
'id' => 'integer',
|
|
'relate_id' => 'integer',
|
|
'status' => 'integer',
|
|
'type' => 'integer',
|
|
'pay_type' => 'integer',
|
|
'pay_mode' => 'integer',
|
|
'fee' => 'integer',
|
|
'self_fee' => 'integer',
|
|
'reduce_fee' => 'integer',
|
|
'refund_fee' => 'integer',
|
|
'source_id' => 'integer',
|
|
'payment_at' => 'datetime',
|
|
'refunded_at' => 'datetime',
|
|
];
|
|
|
|
/**
|
|
* Relationships Patient.
|
|
*/
|
|
public function patient(): belongsTo
|
|
{
|
|
return $this->belongsTo(Patient::class, 'patient_id', 'patient_id');
|
|
}
|
|
|
|
/**
|
|
* Relationships Self Order.
|
|
*/
|
|
public function order(): HasMany
|
|
{
|
|
return $this->hasMany(__CLASS__, 'relate_id');
|
|
}
|
|
|
|
/**
|
|
* Relationships RegistrationRecord Model.
|
|
* @return HasOne
|
|
*/
|
|
public function registrationRecord(): HasOne
|
|
{
|
|
return $this->hasOne(RegistrationRecord::class, 'relate_order_id');
|
|
}
|
|
|
|
/**
|
|
* Relationships OutpatientPaymentRecord Model.
|
|
* @return hasMany
|
|
*/
|
|
public function outpatientPaymentRecord(): hasMany
|
|
{
|
|
return $this->hasMany(OutpatientPaymentRecord::class, 'relate_order_id');
|
|
}
|
|
|
|
/**
|
|
* 获取订单ID
|
|
* @param PayType $pay_type 支付类型
|
|
* @param string $user W 微信 D 大机器 X 小机器 H his
|
|
* @return string
|
|
*/
|
|
public function getOrderId(PayType $pay_type, string $user = 'D'): string
|
|
{
|
|
$order_id = $pay_type->order(). $user. date('YmdHis'). mt_rand(100, 999);
|
|
if ($this->where('order_id', $order_id)->first()) {
|
|
return $this->getOrderId($pay_type, $user);
|
|
}
|
|
|
|
return $order_id;
|
|
}
|
|
|
|
/**
|
|
* 获取退款订单ID
|
|
* @param string $order_id 原订单ID
|
|
* @param string $source_flag 退款来源标志 _ 程序自动冲正 R 人工退费 H His退款
|
|
* @return string
|
|
*/
|
|
public function getRefundOrderId(string $order_id, string $source_flag = '_'): string
|
|
{
|
|
$refund_order_id = $order_id. $source_flag. mt_rand(100, 999);
|
|
if ($this->where('order_id', $refund_order_id)->first()) {
|
|
return $this->getRefundOrderId($order_id);
|
|
}
|
|
|
|
return $refund_order_id;
|
|
}
|
|
|
|
/**
|
|
* 获取订单详情by id
|
|
* @param string $id
|
|
* @return mixed
|
|
*/
|
|
public function getOrderInfoById(string $id): mixed
|
|
{
|
|
return $this->where('id', $id)->with('patient')->first();
|
|
}
|
|
|
|
/**
|
|
* 获取订单详情by order_id
|
|
* @param string $order_id
|
|
* @return mixed
|
|
*/
|
|
public function getOrderInfoByOrderId(string $order_id): mixed
|
|
{
|
|
return $this->where('order_id', $order_id)->with('patient')->first();
|
|
}
|
|
|
|
/**
|
|
* 创建订单
|
|
* @param string $order_id
|
|
* @param PayType $pay_type
|
|
* @param float $fee
|
|
* @param float $reduce_fee
|
|
* @param string $open_id
|
|
* @param string $patient_id
|
|
* @param string $patient_name
|
|
* @param Type $order_type
|
|
* @param SourceId $source_id
|
|
* @param array $record_info
|
|
* @return mixed
|
|
*/
|
|
public function createOrder(string $order_id, PayType $pay_type, float $fee, float $reduce_fee, string $open_id, string $patient_id, string $patient_name, Type $order_type, SourceId $source_id, array $record_info = []): mixed
|
|
{
|
|
|
|
$order_info = [
|
|
'relate_id' => 0,
|
|
'order_id' => $order_id,
|
|
'his_order_id' => '',
|
|
'transaction_id' => '',
|
|
'status' => Status::NORMAL->value,
|
|
'notify_status' => NotifyStatus::NO_ACCEPTED->value,
|
|
'type' => $order_type->value,
|
|
'pay_type' => $pay_type,
|
|
'pay_mode' => PayMode::PAYMENT->value,
|
|
'fee' => $fee, //分
|
|
'reduce_fee' => $reduce_fee, //分
|
|
'self_fee' => $fee - $reduce_fee, //分
|
|
'refund_fee' => 0,
|
|
'open_id' => $open_id,
|
|
'patient_id' => $patient_id,
|
|
'patient_name' => $patient_name,
|
|
'source_id' => $source_id,
|
|
];
|
|
|
|
// 操作订单记录进行创建操作
|
|
if (in_array($order_type->value, [
|
|
Type::TODAY_REGISTRATION->value,
|
|
Type::APPOINTMENT_REGISTRATION->value,
|
|
Type::OUTPATIENT_PAYMENT->value
|
|
])) {
|
|
$result = $this->create($order_info);
|
|
|
|
if (!empty($result) && !empty($record_info)) {
|
|
switch ($order_type->value) {
|
|
case Type::TODAY_REGISTRATION->value:
|
|
case Type::APPOINTMENT_REGISTRATION->value:
|
|
$result->registrationRecord()->create($record_info);
|
|
break;
|
|
case Type::OUTPATIENT_PAYMENT->value:
|
|
$result->outpatientPaymentRecord()->createMany($record_info);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
return $this->create($order_info);
|
|
}
|
|
|
|
/**
|
|
* 创建退费/冲正订单
|
|
* @param int $relate_order_id
|
|
* @param string $order_id
|
|
* @param PayType $pay_type
|
|
* @param float $fee
|
|
* @param string $open_id
|
|
* @param string $patient_id
|
|
* @param string $patient_name
|
|
* @param Type $order_type
|
|
* @param SourceId $source_id
|
|
* @return mixed
|
|
*/
|
|
public function createRefundOReverseOrder(int $relate_order_id, string $order_id, PayType $pay_type, float $fee, string $open_id, string $patient_id, string $patient_name, Type $order_type, SourceId $source_id): mixed
|
|
{
|
|
$order_info = [
|
|
'relate_id' => $relate_order_id,
|
|
'order_id' => $order_id,
|
|
'his_order_id' => '',
|
|
'transaction_id' => '',
|
|
'status' => Status::NORMAL->value,
|
|
'notify_status' => NotifyStatus::NO_ACCEPTED->value,
|
|
'type' => $order_type,
|
|
'pay_type' => $pay_type,
|
|
'pay_mode' => PayMode::REFUND->value,
|
|
'fee' => $fee, //分
|
|
'reduce_fee' => 0, //分
|
|
'self_fee' => 0, //分
|
|
'refund_fee' => 0,
|
|
'open_id' => $open_id,
|
|
'patient_id' => $patient_id,
|
|
'patient_name' => $patient_name,
|
|
'source_id' => $source_id,
|
|
];
|
|
|
|
return $this->create($order_info);
|
|
}
|
|
|
|
/**
|
|
* 订单确认
|
|
* @param string $order_id
|
|
* @param string $his_order_id
|
|
* @param array $response
|
|
*/
|
|
public function orderConfirm(string $order_id, string $his_order_id = '', array $response = []): void
|
|
{
|
|
$order = $this->where('order_id', $order_id)->first();
|
|
|
|
!empty($his_order_id) && $order->his_order_id = $his_order_id;
|
|
$order->status = Status::SUCCESS->value;
|
|
$order->save();
|
|
|
|
if (in_array($order->type, [Type::TODAY_REGISTRATION->value, Type::APPOINTMENT_REGISTRATION->value, Type::OUTPATIENT_PAYMENT->value]) && !empty($response)) {
|
|
switch ($order->type) {
|
|
case Type::TODAY_REGISTRATION->value:
|
|
case Type::APPOINTMENT_REGISTRATION->value:
|
|
$record = $order->registrationRecord;
|
|
$extra_info = json_decode($record->extra_info, true);
|
|
$extra_info['confirm_response'] = $response;
|
|
|
|
$record->update(['extra_info' => json_encode($extra_info, JSON_UNESCAPED_UNICODE)]);
|
|
break;
|
|
case Type::OUTPATIENT_PAYMENT->value:
|
|
$record = $order->outpatientPaymentRecord;
|
|
$extra_info = json_decode($record->extra_info, true);
|
|
$extra_info['confirm_response'] = $response;
|
|
|
|
foreach ($record as $v) {
|
|
$v->update(['extra_info' => json_encode($extra_info, JSON_UNESCAPED_UNICODE)]);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 修改订单状态
|
|
* @param string $order_id
|
|
* @param Status $status
|
|
*/
|
|
public function changeOrderStatus(string $order_id, Status $status): void
|
|
{
|
|
$order = $this->where('order_id', $order_id)->first();
|
|
$order->status = $status;
|
|
$order->save();
|
|
}
|
|
|
|
/**
|
|
* 订单异常(用户交钱成功,his业务确认异常
|
|
* @param string $order_id
|
|
*/
|
|
public function abnormalOrderOpera(string $order_id): void
|
|
{
|
|
$order = $this->where('order_id', $order_id)->first();
|
|
$order->status = Status::ABNORMAL->value;
|
|
$order->save();
|
|
}
|
|
|
|
/**
|
|
* 订单冲正(用户交钱成功,his业务确认失败)
|
|
* @param string $order_id
|
|
* @param float $refund_fee 此处是元
|
|
* @param bool $is_success 退款是否成功
|
|
*/
|
|
public function reverseOrderOpera(string $order_id, float $refund_fee, bool $is_success): void
|
|
{
|
|
$r_order = $this->where('order_id', $order_id)->first();
|
|
|
|
//原订单
|
|
if ($is_success) {
|
|
$order = $this->where('id', $r_order->relate_id)->first();
|
|
$order->refund_fee += $refund_fee * 100;
|
|
$order->status = Status::REVERSE->value;
|
|
$order->save();
|
|
}
|
|
|
|
// 保存退费/冲正订单
|
|
$r_order->status = $is_success ? Status::SUCCESS->value : Status::FAILURE->value;
|
|
$r_order->refunded_at = date('Y-m-d H:i:s');
|
|
$r_order->save();
|
|
}
|
|
|
|
/**
|
|
* 挂号订单解锁
|
|
* @param string $order_id
|
|
* @return void
|
|
*/
|
|
public function regOrderUnlock(string $order_id): void
|
|
{
|
|
$order = $this->where('order_id', $order_id)->with('registrationRecord')->first();
|
|
|
|
$order->registrationRecord->lock_status = 2;
|
|
$order->registrationRecord->unlock_at = date('Y-m-d H:i:s');
|
|
$order->registrationRecord->save();
|
|
|
|
$order->status = Status::FAILURE->value;
|
|
$order->save();
|
|
}
|
|
|
|
/**
|
|
* 订单取消预结算
|
|
* @param string $order_id
|
|
* @return void
|
|
*/
|
|
public function outpatientOderCancelPreSettle(string $order_id): void
|
|
{
|
|
$order = $this->where('order_id', $order_id)->with('outpatientPaymentRecord')->first();
|
|
|
|
$order->outpatientPaymentRecord->pre_settle_status = 2;
|
|
$order->outpatientPaymentRecord->cancel_pre_settle_at = date('Y-m-d H:i:s');
|
|
$order->outpatientPaymentRecord->save();
|
|
|
|
$order->status = Status::FAILURE->value;
|
|
$order->save();
|
|
}
|
|
}
|
|
|