TransferOrder.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <?php
  2. namespace App\Module\Transfer\Models;
  3. use App\Module\Transfer\Casts\TransferOrderCast;
  4. use App\Module\Transfer\Casts\CallbackDataCast;
  5. use App\Module\Transfer\Enums\TransferStatus;
  6. use App\Module\Transfer\Enums\TransferType;
  7. use UCore\ModelCore;
  8. /**
  9. * 划转订单模型
  10. *
  11. * field start
  12. * @property int $id 主键ID
  13. * @property int $transfer_app_id 划转应用ID
  14. * @property int $out_id 外部应用ID
  15. * @property string $out_order_id 外部订单ID(外部应用的订单ID,传入或回调获取)
  16. * @property string $out_user_id 外部用户ID
  17. * @property int $user_id 内部用户ID
  18. * @property int $currency_id 货币类型ID
  19. * @property int $fund_id 资金账户类型ID
  20. * @property \App\Module\Transfer\Enums\TransferType $type 订单类型(1=转入,2=转出)
  21. * @property \App\Module\Transfer\Enums\TransferStatus $status 订单状态
  22. * @property float $out_amount 外部金额
  23. * @property float $amount 内部金额
  24. * @property float $exchange_rate 使用汇率
  25. * @property \App\Module\Transfer\Casts\CallbackDataCast $callback_data 回调数据
  26. * @property string $error_message 错误信息
  27. * @property string $remark 备注信息
  28. * @property \Carbon\Carbon $processed_at 处理时间
  29. * @property \Carbon\Carbon $callback_at 回调时间
  30. * @property \Carbon\Carbon $completed_at 完成时间
  31. * @property \Carbon\Carbon $created_at 创建时间
  32. * @property \Carbon\Carbon $updated_at 更新时间
  33. * @property \Carbon\Carbon $deleted_at 删除时间
  34. * @property float $fee_rate 使用的手续费率
  35. * @property float $fee_amount 手续费金额
  36. * @property float $actual_amount 实际到账金额(扣除手续费后)
  37. * @property float $totle_amount 支付扣除金额
  38. * field end
  39. *
  40. */
  41. class TransferOrder extends ModelCore
  42. {
  43. /**
  44. * 数据表名
  45. */
  46. protected $table = 'transfer_orders';
  47. // attrlist start
  48. protected $fillable = [
  49. 'id',
  50. 'transfer_app_id',
  51. 'out_id',
  52. 'out_order_id',
  53. 'out_user_id',
  54. 'user_id',
  55. 'currency_id',
  56. 'fund_id',
  57. 'type',
  58. 'status',
  59. 'out_amount',
  60. 'amount',
  61. 'exchange_rate',
  62. 'callback_data',
  63. 'error_message',
  64. 'remark',
  65. 'processed_at',
  66. 'callback_at',
  67. 'completed_at',
  68. 'fee_rate',
  69. 'fee_amount',
  70. 'actual_amount',
  71. 'totle_amount',
  72. ];
  73. // attrlist end
  74. /**
  75. * 属性类型转换
  76. */
  77. protected $casts = [
  78. 'id' => 'integer',
  79. 'transfer_app_id' => 'integer',
  80. 'out_id' => 'integer',
  81. 'user_id' => 'integer',
  82. 'currency_id' => 'integer',
  83. 'fund_id' => 'integer',
  84. 'type' => TransferType::class,
  85. 'status' => TransferStatus::class,
  86. 'out_amount' => 'decimal:10',
  87. 'amount' => 'decimal:10',
  88. 'exchange_rate' => 'decimal:4',
  89. 'fee_rate' => 'decimal:4',
  90. 'fee_amount' => 'decimal:4',
  91. 'actual_amount' => 'decimal:4',
  92. 'callback_data' => CallbackDataCast::class,
  93. 'processed_at' => 'datetime',
  94. 'callback_at' => 'datetime',
  95. 'completed_at' => 'datetime',
  96. 'created_at' => 'datetime',
  97. 'updated_at' => 'datetime',
  98. 'deleted_at' => 'datetime',
  99. ];
  100. /**
  101. * 软删除
  102. */
  103. protected $dates = ['deleted_at'];
  104. /**
  105. * 隐藏字段
  106. */
  107. protected $hidden = [];
  108. /**
  109. * 关联划转应用
  110. */
  111. public function transferApp()
  112. {
  113. return $this->belongsTo(TransferApp::class, 'transfer_app_id');
  114. }
  115. /**
  116. * 获取类型文本
  117. */
  118. public function getTypeTextAttribute(): string
  119. {
  120. return $this->type->getDescription();
  121. }
  122. /**
  123. * 获取状态文本
  124. */
  125. public function getStatusTextAttribute(): string
  126. {
  127. return $this->status->getDescription();
  128. }
  129. /**
  130. * 获取状态颜色
  131. */
  132. public function getStatusColorAttribute(): string
  133. {
  134. return $this->status->getColor();
  135. }
  136. /**
  137. * 获取类型颜色
  138. */
  139. public function getTypeColorAttribute(): string
  140. {
  141. return $this->type->getColor();
  142. }
  143. /**
  144. * 判断是否为转入订单
  145. */
  146. public function isTransferIn(): bool
  147. {
  148. return $this->type === TransferType::IN;
  149. }
  150. /**
  151. * 判断是否为转出订单
  152. */
  153. public function isTransferOut(): bool
  154. {
  155. return $this->type === TransferType::OUT;
  156. }
  157. /**
  158. * 判断是否为最终状态
  159. */
  160. public function isFinalStatus(): bool
  161. {
  162. return $this->status->isFinal();
  163. }
  164. /**
  165. * 判断是否可以重试
  166. */
  167. public function canRetry(): bool
  168. {
  169. return $this->status->canRetry();
  170. }
  171. /**
  172. * 更新状态
  173. */
  174. public function updateStatus(TransferStatus $status, string $message = null): bool
  175. {
  176. $data = ['status' => $status];
  177. if ($message) {
  178. $data['error_message'] = $message;
  179. }
  180. // 设置时间戳
  181. switch ($status) {
  182. case TransferStatus::PROCESSING:
  183. $data['processed_at'] = now();
  184. break;
  185. case TransferStatus::CALLBACK:
  186. $data['callback_at'] = now();
  187. break;
  188. case TransferStatus::COMPLETED:
  189. case TransferStatus::FAILED:
  190. $data['completed_at'] = now();
  191. break;
  192. }
  193. return $this->update($data);
  194. }
  195. /**
  196. * 判断是否收取了手续费
  197. */
  198. public function hasFee(): bool
  199. {
  200. return $this->fee_amount > 0;
  201. }
  202. /**
  203. * 获取手续费率百分比文本
  204. */
  205. public function getFeeRatePercentAttribute(): string
  206. {
  207. return number_format($this->fee_rate * 100, 2) . '%';
  208. }
  209. /**
  210. * 获取手续费金额格式化文本
  211. */
  212. public function getFeeAmountTextAttribute(): string
  213. {
  214. return number_format($this->fee_amount, 4);
  215. }
  216. /**
  217. * 获取实际到账金额格式化文本
  218. */
  219. public function getActualAmountTextAttribute(): string
  220. {
  221. return number_format($this->actual_amount, 4);
  222. }
  223. /**
  224. * 设置手续费信息
  225. *
  226. * @param float $feeRate 手续费率
  227. * @param string $feeAmount 手续费金额
  228. * @param string $actualAmount 实际到账金额
  229. */
  230. public function setFeeInfo(float $feeRate, string $feeAmount, string $actualAmount): void
  231. {
  232. $this->fee_rate = $feeRate;
  233. $this->fee_amount = $feeAmount;
  234. $this->actual_amount = $actualAmount;
  235. }
  236. /**
  237. * 计算手续费信息(基于关联的应用配置)
  238. */
  239. public function calculateFeeFromApp(): array
  240. {
  241. if (!$this->transferApp) {
  242. return [
  243. 'fee_rate' => 0.0000,
  244. 'fee_amount' => '0.0000',
  245. 'actual_amount' => $this->amount,
  246. ];
  247. }
  248. if ($this->isTransferIn()) {
  249. return $this->transferApp->calculateInFee($this->amount);
  250. } else {
  251. return $this->transferApp->calculateOutFee($this->amount);
  252. }
  253. }
  254. }