OrderRefund.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\index\model;
  13. use app\index\model\OrderRefundImage;
  14. use app\index\service\User as UserService;
  15. use app\api\model\OrderGoods as OrderGoodsModel;
  16. use app\common\model\OrderRefund as OrderRefundModel;
  17. use app\common\enum\order\refund\RefundType as RefundTypeEnum;
  18. use app\common\enum\order\refund\AuditStatus as AuditStatusEnum;
  19. use app\common\enum\order\refund\RefundStatus as RefundStatusEnum;
  20. use cores\exception\BaseException;
  21. /**
  22. * 售后单模型
  23. * Class OrderRefund
  24. * @package app\api\model
  25. */
  26. class OrderRefund extends OrderRefundModel
  27. {
  28. /**
  29. * 隐藏字段
  30. * @var array
  31. */
  32. protected $hidden = [
  33. 'store_id',
  34. 'update_time'
  35. ];
  36. /**
  37. * 追加字段
  38. * @var array
  39. */
  40. protected $append = [
  41. 'state_text', // 售后单状态文字描述
  42. ];
  43. /**
  44. * 售后单状态文字描述
  45. * @param $value
  46. * @param $data
  47. * @return string
  48. */
  49. public function getStateTextAttr($value, $data): string
  50. {
  51. // 已完成
  52. if ($data['status'] == RefundStatusEnum::COMPLETED) {
  53. $text = [RefundTypeEnum::RETURN => '已同意退货并已退款', RefundTypeEnum::EXCHANGE => '已同意换货'];
  54. return $text[$data['type']];
  55. }
  56. // 已取消
  57. if ($data['status'] == RefundStatusEnum::CANCELLED) {
  58. return '已取消';
  59. }
  60. // 已拒绝
  61. if ($data['status'] == RefundStatusEnum::REJECTED) {
  62. // return '已拒绝';
  63. return $data['type'] == RefundTypeEnum::RETURN ? '已拒绝退货退款' : '已拒绝换货';
  64. }
  65. // 进行中
  66. if ($data['status'] == RefundStatusEnum::NORMAL) {
  67. if ($data['audit_status'] == AuditStatusEnum::WAIT) {
  68. return '等待审核中';
  69. }
  70. if ($data['type'] == RefundTypeEnum::RETURN) {
  71. return $data['is_user_send'] ? '已发货,待平台确认' : '已同意退货,请及时发货';
  72. }
  73. }
  74. return $value;
  75. }
  76. /**
  77. * 获取用户售后单列表
  78. * @param int $state 售后单状态 -1为全部
  79. * @return \think\Paginator
  80. * @throws \app\common\exception\BaseException
  81. * @throws \think\db\exception\DbException
  82. * @throws BaseException
  83. */
  84. public function getList(int $state = -1): \think\Paginator
  85. {
  86. // 检索查询条件
  87. $filter = [];
  88. // 售后单状态
  89. $state > -1 && $filter[] = ['status', '=', $state];
  90. // 当前用户ID
  91. $userId = UserService::getCurrentLoginUserId();
  92. // 查询列表记录
  93. return $this->with(['orderGoods.image'])
  94. ->where($filter)
  95. ->where('user_id', '=', $userId)
  96. ->order(['create_time' => 'desc'])
  97. ->paginate(15);
  98. }
  99. /**
  100. * 获取当前用户的售后单详情
  101. * @param int $orderRefundId 售后单ID
  102. * @param bool $isWith 是否关联
  103. * @return static|null
  104. * @throws BaseException
  105. */
  106. public static function getDetail(int $orderRefundId, bool $isWith = false): ?OrderRefund
  107. {
  108. // 关联查询
  109. $with = $isWith ? ['orderGoods' => ['image'], 'images.file', 'address', 'express'] : [];
  110. // 获取记录
  111. $detail = static::detail([
  112. 'user_id' => UserService::getCurrentLoginUserId(),
  113. 'order_refund_id' => $orderRefundId
  114. ], $with);
  115. if (empty($detail)) throwError('未找到该售后单');
  116. return $detail;
  117. }
  118. /**
  119. * 获取当前用户的售后单数量(进行中的)
  120. * @return int
  121. * @throws BaseException
  122. */
  123. public static function getCountByUnderway(): int
  124. {
  125. $userId = UserService::getCurrentLoginUserId();
  126. return (new static)->where('user_id', '=', $userId)
  127. ->where('status', '=', 0)
  128. ->count();
  129. }
  130. /**
  131. * 订单商品详情
  132. * @param int $orderGoodsId 订单商品ID
  133. * @return \app\common\model\OrderGoods|null
  134. * @throws BaseException
  135. */
  136. public function getRefundGoods(int $orderGoodsId)
  137. {
  138. $goods = OrderGoodsModel::detail($orderGoodsId);
  139. if (isset($goods['refund']) && !empty($goods['refund'])) {
  140. throwError('当前商品已申请售后');
  141. }
  142. return $goods;
  143. }
  144. /**
  145. * 用户发货
  146. * @param $data
  147. * @return false|int
  148. */
  149. public function delivery(array $data)
  150. {
  151. if (
  152. $this['type'] != RefundTypeEnum::RETURN
  153. || $this['audit_status'] != AuditStatusEnum::REVIEWED
  154. || $this['is_user_send'] != 0
  155. ) {
  156. $this->error = '当前售后单不合法,不允许该操作';
  157. return false;
  158. }
  159. if ($data['expressId'] <= 0) {
  160. $this->error = '请选择物流公司';
  161. return false;
  162. }
  163. if (empty($data['expressNo'])) {
  164. $this->error = '请填写物流单号';
  165. return false;
  166. }
  167. return $this->save([
  168. 'is_user_send' => 1,
  169. 'send_time' => time(),
  170. 'express_id' => (int)$data['expressId'],
  171. 'express_no' => $data['expressNo'],
  172. ]);
  173. }
  174. /**
  175. * 新增售后单记录
  176. * @param int $orderGoodsId 订单商品ID
  177. * @param array $data 用户提交的表单数据
  178. * @return mixed
  179. * @throws BaseException
  180. */
  181. public function apply(int $orderGoodsId, array $data)
  182. {
  183. // 订单商品详情
  184. $goods = $this->getRefundGoods($orderGoodsId);
  185. return $this->transaction(function () use ($orderGoodsId, $data, $goods) {
  186. // 新增售后单记录
  187. $this->save([
  188. 'order_goods_id' => $orderGoodsId,
  189. 'order_id' => $goods['order_id'],
  190. 'user_id' => UserService::getCurrentLoginUserId(),
  191. 'type' => $data['type'],
  192. 'apply_desc' => $data['content'],
  193. 'audit_status' => AuditStatusEnum::WAIT,
  194. 'status' => 0,
  195. 'store_id' => self::$storeId
  196. ]);
  197. // 记录凭证图片关系
  198. if (isset($data['images']) && !empty($data['images'])) {
  199. $this->saveImages((int)$this['order_refund_id'], $data['images']);
  200. }
  201. return true;
  202. });
  203. }
  204. /**
  205. * 记录售后单图片
  206. * @param int $orderRefundId 售后单ID
  207. * @param array $images 图片列表
  208. * @return bool
  209. */
  210. private function saveImages(int $orderRefundId, array $images)
  211. {
  212. // 生成评价图片数据
  213. $data = [];
  214. foreach ($images as $imageId) {
  215. $data[] = [
  216. 'order_refund_id' => $orderRefundId,
  217. 'image_id' => $imageId,
  218. 'store_id' => self::$storeId
  219. ];
  220. }
  221. return !empty($data) && (new OrderRefundImage)->addAll($data) !== false;
  222. }
  223. }