Refund.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. namespace app\common\model;
  3. use app\common\service\OrderRefundService;
  4. use think\db\Query;
  5. use think\Model;
  6. /**
  7. * 短信验证码
  8. * @property Orders orders
  9. * @property User user
  10. * @property int refund_status
  11. * @method static static|Query FilterRefund($status=null)
  12. * @method static static|Query FilterTs()
  13. */
  14. class Refund Extends Model
  15. {
  16. protected $name='order_info_refund';
  17. const REFUND_ING=10;
  18. const REFUND_PASS=20;
  19. const REFUND_REJECT=30;
  20. const REFUND_CANCEL=40;
  21. public static $refundStatus=[
  22. self::REFUND_ING=>'申请处理中',
  23. self::REFUND_PASS=>'申请通过',
  24. self::REFUND_REJECT=>'申请驳回',
  25. self::REFUND_CANCEL=>'已取消',
  26. ];
  27. /**
  28. * @return string[]
  29. */
  30. public static function getRefundStatus(): array
  31. {
  32. return self::$refundStatus;
  33. }
  34. const REFUND_TYPE_MONEY=1;
  35. const REFUND_TYPE_ALL=2;
  36. const REFUND_TYPE_GOODS=3;
  37. const REFUND_TYPE_CANCEL=4;
  38. const REFUND_TYPE_HHBX=5;
  39. public static $refundTypes=[
  40. self::REFUND_TYPE_MONEY=>'仅退款',
  41. self::REFUND_TYPE_ALL=>'退款退货',
  42. self::REFUND_TYPE_GOODS=>'仅退货',
  43. self::REFUND_TYPE_CANCEL=>'取消订单',
  44. self::REFUND_TYPE_HHBX=>'换货保修',
  45. ];
  46. public static $refundTypeGoods=[self::REFUND_TYPE_ALL,self::REFUND_TYPE_GOODS];
  47. public static $refundTypeMoney=[self::REFUND_TYPE_MONEY,self::REFUND_TYPE_CANCEL,self::REFUND_TYPE_ALL];
  48. const REASON_QU=1;
  49. public static $reasons=[
  50. self::REASON_QU=>'质量问题',
  51. 2=>'7天无理由退货(退回运费需客户承担)',
  52. 3=>'协商一致退款',
  53. 4=>'快递运输破损',
  54. 5=>'其他',
  55. ];
  56. const TH_TYPE_NONE=0;
  57. const TH_TYPE_SELF_SEND=1;
  58. const TH_TYPE_SELF_FEE=2;
  59. const TH_TYPE_FREE=3;
  60. public static $goodsTypes=[
  61. self::TH_TYPE_NONE=>'无需退货',
  62. self::TH_TYPE_SELF_SEND=>'自行邮寄',
  63. self::TH_TYPE_SELF_FEE=>'拍维修费',
  64. self::TH_TYPE_FREE=>'一年以内免费保修',
  65. ];
  66. /**
  67. * @return string[]
  68. */
  69. public static function getReasons(): array
  70. {
  71. $reasons=self::$reasons;
  72. $arr=[];
  73. foreach ($reasons as $key=>$value){
  74. $arr[$key]=compact('key','value');
  75. }
  76. return $arr;
  77. }
  78. /**
  79. * @return string[]
  80. */
  81. public static function getRefundBys(): array
  82. {
  83. $obj=self::$goodsTypes;
  84. $arr=[];
  85. foreach ($obj as $key=>$value){
  86. $arr[$key]=compact('key','value');
  87. }
  88. return $arr;
  89. }
  90. /**
  91. * @return string[]
  92. */
  93. public static function getRefundTypes(): array
  94. {
  95. return self::$refundTypes;
  96. }
  97. /**
  98. * @return int[]
  99. */
  100. public static function getRefundTypeGoods(): array
  101. {
  102. return self::$refundTypeGoods;
  103. }
  104. /**
  105. * @return int[]
  106. */
  107. public static function getRefundTypeMoney(): array
  108. {
  109. return self::$refundTypeMoney;
  110. }
  111. protected $autoWriteTimestamp=true;
  112. public function orderInfo(){
  113. return $this->belongsTo(OrderInfo::class);
  114. }
  115. public function orders(){
  116. return $this->belongsTo(Orders::class,'order_id');
  117. }
  118. public function user(){
  119. return $this->belongsTo(User::class);
  120. }
  121. public function allowCancel(){
  122. return in_array($this['refund_status'],[
  123. self::REFUND_ING,
  124. ]);
  125. }
  126. public function makeCancel(){
  127. $this['refund_status']=self::REFUND_CANCEL;
  128. $this->save();
  129. $this->orderInfo()->save([
  130. 'refund_id'=>null,
  131. ]);
  132. }
  133. #根据订单状态选择售后
  134. public static function makeRefundConfig(OrderInfo $orderInfo,$delKeys=true,$inject=true){
  135. $order=$orderInfo->orders;
  136. $refundConfig=[];
  137. #未发货
  138. if($order['status']==$order::S_WAIT_SEND){
  139. $refundConfig['refund_type']=[
  140. self::REFUND_TYPE_CANCEL=>'取消订单',
  141. ];
  142. $refundConfig['type']=[
  143. self::TH_TYPE_NONE=>'无需退货',
  144. ];
  145. $refundConfig['reason']=array_values(Refund::getReasons());
  146. $refundConfig['req_amount']=1;
  147. $refundConfig['req_order']=0;
  148. }
  149. #已发货
  150. elseif(in_array($order['status'],[$order::S_WAIT_REC,$order::S_OVER])){
  151. #七天内可以退货退款
  152. if(time()<$order['send_time']+7*86400){
  153. $refundConfig['refund_type']=[
  154. self::REFUND_TYPE_ALL=>'退款退货',
  155. ];
  156. $refundConfig['type']=[
  157. self::TH_TYPE_FREE=>'自行邮寄',
  158. ];
  159. $refundConfig['reason']=array_values(Refund::getReasons());
  160. $refundConfig['req_amount']=1;
  161. $refundConfig['req_order']=0;
  162. }else{
  163. $refundConfig['refund_type']=[
  164. self::REFUND_TYPE_HHBX=>'换货保修',
  165. ];
  166. $refundConfig['req_order']=0;
  167. #一年内
  168. if(time()<strtotime('+1year',$order['send_time'])){
  169. $refundConfig['type']=[
  170. self::TH_TYPE_FREE=>'一年以内免费保修',
  171. ];
  172. }else{
  173. $refundConfig['type']=[
  174. self::TH_TYPE_SELF_FEE=>'拍维修费',
  175. ];
  176. $refundConfig['req_order']=1;
  177. $refundConfig['req_order_goods']=Goods::getFixGoods();
  178. }
  179. $refundConfig['reason']=array_values(Refund::getReasons());
  180. $refundConfig['req_amount']=0;
  181. }
  182. }
  183. if($delKeys) {
  184. if (!empty($refundConfig['refund_type'])) {
  185. $data = [];
  186. foreach ($refundConfig['refund_type'] as $key => $value) {
  187. $data[] = compact('key', 'value');
  188. }
  189. $refundConfig['refund_type'] = $data;
  190. }
  191. if (!empty($refundConfig['type'])) {
  192. $data = [];
  193. foreach ($refundConfig['type'] as $key => $value) {
  194. $data[] = compact('key', 'value');
  195. }
  196. $refundConfig['type'] = $data;
  197. }
  198. }
  199. if($inject){
  200. $orderInfo['refund_config']=$refundConfig?:null;
  201. }
  202. return $refundConfig;
  203. }
  204. public function allowAudit(){
  205. return $this['refund_status']==self::REFUND_ING;
  206. }
  207. #退款相关
  208. /**
  209. * 退款金额
  210. */
  211. public function getRefundAmount(){
  212. return $this['amount'];
  213. }
  214. public function refundResult($succ,$remark=''){
  215. if(is_bool($succ)){
  216. $this['pay_status']=$succ?1:2;
  217. }else{
  218. $this['pay_status']=$succ;
  219. }
  220. $this['pay_remark']=$remark;
  221. $this->save();
  222. }
  223. public function isRefundMoney(){
  224. return in_array($this['refund_type'],self::getRefundTypeMoney());
  225. }
  226. #end
  227. public function makeAudit($pass){
  228. $this['refund_status']=$pass?self::REFUND_PASS:self::REFUND_REJECT;
  229. $refundMoney=false;
  230. if($pass){
  231. #如果退货
  232. if(in_array($this['refund_type'],self::getRefundTypeGoods())){
  233. $this->orderInfo()->update(['is_return_goods'=>1]);
  234. }
  235. #如果退款,执行退款
  236. if(in_array($this['refund_type'],self::getRefundTypeMoney())){
  237. $this['order_no']=order_no('TK');
  238. $refundMoney=true;
  239. }
  240. }
  241. if(!$this->save()){
  242. throw_user('保存失败');
  243. }
  244. if($refundMoney){
  245. $payment=$this->orders->payment??null;
  246. if($payment){
  247. $refund=new OrderRefundService();
  248. $refund->setPayment($payment);
  249. $refund->setRefund($this);
  250. $refund->setBody("订单[{$this->orders->order_no}]退款");
  251. $refund->pay();
  252. }
  253. }
  254. SiteMsg::sendMsg(
  255. $pass?SiteMsg::TYPE_ORDER_REFUND_PASS:SiteMsg::TYPE_ORDER_REFUND_REJECT,
  256. $this->user
  257. );
  258. #总订单
  259. $order=$this->orders;
  260. if($order && $order->status<Orders::S_OVER){
  261. $has=OrderInfo::where('order_id',$this['order_id'])
  262. ->filterHasUnRefund()
  263. ->find();
  264. if(!$has){
  265. $order->makeCancel();
  266. }
  267. }
  268. }
  269. /**
  270. * 售后中及已售后的
  271. * @param Query $query
  272. * @param null $status 1进行中2已完成
  273. */
  274. public function scopeFilterRefund(Query $query,$status=null){
  275. if(is_null($status)) {
  276. $query->whereBetween("{$this->getTable()}.refund_status", [self::REFUND_ING, self::REFUND_PASS]);
  277. }elseif ($status==1){
  278. $query->where("{$this->getTable()}.refund_status", self::REFUND_ING);
  279. }elseif ($status==2){
  280. $query->where("{$this->getTable()}.refund_status", self::REFUND_PASS);
  281. }
  282. }
  283. /**
  284. * 投诉类型的售后
  285. * @param Query $query
  286. */
  287. public function scopeFilterTs(Query $query){
  288. $query->where("{$this->getTable()}.reason1",self::REASON_QU);
  289. }
  290. protected static function init()
  291. {
  292. self::beforeInsert(function (self $refund){
  293. $refund['refund_status']=self::REFUND_ING;
  294. });
  295. self::afterUpdate(function (self $refund){
  296. if($refund->refund_status==self::REFUND_PASS && $refund->isRefundMoney()){
  297. Transaction::addTransaction($refund);
  298. }
  299. });
  300. }
  301. }