OrderGoods.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * Author: 芸众商城 www.yunzshop.com
  5. * Date: 2017/3/2
  6. * Time: 上午11:24
  7. */
  8. namespace app\common\models;
  9. use app\common\events\order\HiddenOrderCommentEvent;
  10. use app\common\exceptions\AppException;
  11. use app\common\models\comment\CommentConfig;
  12. use app\common\models\goods\GoodsDispatch;
  13. use app\common\models\order\OrderGoodsChangePriceLog;
  14. use app\common\models\orderGoods\OrderGoodsDeduction;
  15. use app\common\models\orderGoods\OrderGoodsDiscount;
  16. use app\common\models\orderGoods\OrderGoodsExpansion;
  17. use app\common\models\refund\RefundApply;
  18. use app\common\models\refund\RefundGoodsLog;
  19. use app\frontend\modules\orderGoods\stock\GoodsStock;
  20. use app\framework\Database\Eloquent\Builder;
  21. use Illuminate\Database\Eloquent\Collection;
  22. use Yunshop\Merchant\common\models\MerchantGoods;
  23. /**
  24. * Class OrderGoods
  25. * @package app\common\models
  26. * @property int comment_status
  27. * @property int total
  28. * @property int goods_id
  29. * @property int is_refund
  30. * @property int goods_option_id
  31. * @property Goods goods
  32. * @property GoodsOption goodsOption
  33. * @property Collection orderGoodsDeductions
  34. * @property Collection manyRefundedGoodsLog
  35. * @method static self byIsRefund()
  36. */
  37. class OrderGoods extends BaseModel
  38. {
  39. public $table = 'yz_order_goods';
  40. protected $hidden = ['order_id','manyRefundedGoodsLog','hasOneRefund'];
  41. protected $appends = ['buttons','after_sales'];
  42. protected $fillable = [];
  43. protected $guarded = ['id'];
  44. protected $attributes = [
  45. 'goods_option_id' => 0,
  46. 'goods_option_title' => '',
  47. 'comment_status' => 0
  48. ];
  49. protected $search_fields = ['title'];
  50. const CAN_REFUND = 0;//未退过款
  51. const FIRST_REFUND = 1; //首次退款
  52. // const MANY_REFUND = 2; //重复退款
  53. // const FINAL_REFUND = 3;//最终
  54. /**
  55. * 获取支付商品名称
  56. * @return string
  57. */
  58. public function getPayTitleAttribute()
  59. {
  60. return $this->goods->alias?: $this->title;
  61. }
  62. /**
  63. * 订单商品售后信息显示数组
  64. * @return array
  65. */
  66. public function getAfterSalesAttribute()
  67. {
  68. $after_sales = [
  69. 'refund_id' => $this->refund_id?:0,
  70. 'refund_type_name' => '',
  71. 'refund_status_name' => '已退款',
  72. 'refunded_total' => '',
  73. 'complete_quantity' => $this->getRefundTotal(), //已退款完成数量
  74. ];
  75. if ($this->refund_id) {
  76. $after_sales['refund_type_name'] = $this->hasOneRefund->refund_type_name;
  77. $after_sales['refund_status_name'] = $this->hasOneRefund->status_name;
  78. $after_sales['refunded_total'] = $this->manyRefundedGoodsLog
  79. ->where('refund_id', $this->refund_id)
  80. ->sum('refund_total');
  81. $after_sales['complete_quantity'] = $after_sales['complete_quantity'] - $after_sales['refunded_total'];
  82. } else {
  83. //过滤换货售后
  84. $after_sales['refunded_total'] = $after_sales['complete_quantity'];
  85. }
  86. return $after_sales;
  87. }
  88. public function getRefundTotal()
  89. {
  90. return $this->manyRefundedGoodsLog
  91. ->where('refund_type','!=', RefundApply::REFUND_TYPE_EXCHANGE_GOODS)
  92. // ->where('status','!=', RefundGoodsLog::CANCEL_STATUS)
  93. ->sum('refund_total');
  94. }
  95. /**
  96. * 前端商品评论按钮
  97. * @return array
  98. */
  99. public function getButtonsAttribute()
  100. {
  101. if($this->order->uid != \YunShop::app()->getMemberId()){
  102. return [];
  103. }
  104. $result = [];
  105. $config = CommentConfig::getSetConfig();
  106. if ($this->order->status != 3) {
  107. return $result;
  108. }
  109. event($event = new HiddenOrderCommentEvent($this));
  110. //开启评价
  111. if ($config->is_order_comment_entrance && $event->isShow()) {
  112. if ($this->comment_status == 0) {
  113. $result[] = [
  114. 'name' => '评价',
  115. 'api' => '',//goods.comment.create-comment-page
  116. 'value' => '0'
  117. ];
  118. } elseif ($this->comment_status == 1) {
  119. $result[] = [
  120. 'name' => '查看评价',
  121. 'api' => '',
  122. 'value' => '2'
  123. ];
  124. //开启追评
  125. if ($config->is_additional_comment) {
  126. $result[] = [
  127. 'name' => '追评',
  128. 'api' => '',
  129. 'value' => '1'
  130. ];
  131. }
  132. } else {
  133. $result[] = [
  134. 'name' => '查看评价',
  135. 'api' => '',
  136. 'value' => '2'
  137. ];
  138. }
  139. }
  140. return $result;
  141. }
  142. public function orderGoodsDeductions()
  143. {
  144. return $this->hasMany(OrderGoodsDeduction::class,'order_goods_id');
  145. }
  146. public function orderGoodsDiscounts()
  147. {
  148. return $this->hasMany(OrderGoodsDiscount::class,'order_goods_id');
  149. }
  150. public function hasOneGoods()
  151. {
  152. return $this->hasOne($this->getNearestModel('Goods'), 'id', 'goods_id');
  153. }
  154. public function hasOneOrder()
  155. {
  156. return $this->hasOne(Order::class, 'id', 'order_id');
  157. }
  158. public function order()
  159. {
  160. return $this->hasOne(Order::class, 'id', 'order_id');
  161. }
  162. public function hasOneMerchantGoods()
  163. {
  164. return $this->hasOne(MerchantGoods::class, 'goods_id', 'goods_id');
  165. }
  166. //商品
  167. public function goods()
  168. {
  169. //todo blank 如果订单未支付时删除了商品,再支付会报错,原因是修改商品库存时关联商品模型为null,解决方式如下:
  170. // return $this->belongsTo(Goods::class)->withTrashed();
  171. return $this->belongsTo(Goods::class);
  172. }
  173. public function belongsToGood()
  174. {
  175. return $this->belongsTo(self::getNearestModel('Goods'), 'goods_id', 'id');
  176. }
  177. //商品规格
  178. public function goodsOption()
  179. {
  180. return $this->hasOne(app('GoodsManager')->make('GoodsOption'), 'id', 'goods_option_id');
  181. }
  182. public function hasOneGoodsDispatch()
  183. {
  184. return $this->hasOne(GoodsDispatch::class, 'goods_id', 'goods_id');
  185. }
  186. public function hasOneComment()
  187. {
  188. return $this->hasOne(\app\frontend\modules\goods\models\Comment::class, 'id', 'comment_id');
  189. }
  190. public function orderGoodsChangePriceLogs()
  191. {
  192. return $this->hasMany(OrderGoodsChangePriceLog::class, 'order_id', 'id');
  193. }
  194. public function hasOneRefund()
  195. {
  196. return $this->hasOne(\app\common\models\refund\RefundApply::class, 'id', 'refund_id');
  197. }
  198. /**
  199. * 已售后订单商品记录
  200. * @return \Illuminate\Database\Eloquent\Relations\HasMany
  201. */
  202. public function manyRefundedGoodsLog()
  203. {
  204. return $this->hasMany(RefundGoodsLog::class, 'order_goods_id', 'id');
  205. }
  206. public function scopeOrderGoods(Builder $query)
  207. {
  208. return $query->select([
  209. 'id', 'order_id', 'goods_id', 'refund_id','is_refund','goods_price', 'total', 'goods_option_title',
  210. 'price', 'goods_market_price', 'goods_cost_price', 'thumb', 'title', 'goods_sn',
  211. 'payment_amount','deduction_amount','vip_price','product_sn','type'
  212. ])->with(['goods'=>function ($query) {
  213. //在这里添加'weight','product_sn','goods_sn'字段,因为快递打印那边要用
  214. return $query->select(['id','title','status','type','thumb','sku','market_price','price','cost_price','weight','product_sn','goods_sn','alias']);
  215. }]);
  216. }
  217. //已退过款商品
  218. public function scopeByIsRefund(Builder $query)
  219. {
  220. return $query->where('is_refund', '>', OrderGoods::CAN_REFUND);
  221. }
  222. /**
  223. * 订单商品是否已退过款
  224. * @return mixed
  225. */
  226. public function isRefund()
  227. {
  228. return $this->is_refund > self::CAN_REFUND;
  229. }
  230. /**
  231. * 商品已退款次数
  232. */
  233. public function refundNumber()
  234. {
  235. return $this->is_refund;
  236. }
  237. public function isOption()
  238. {
  239. return !empty($this->goods_option_id);
  240. }
  241. /**
  242. * @throws AppException
  243. */
  244. public function stockEnough()
  245. {
  246. if($this->isOption()){
  247. // 规格
  248. if (!$this->goodsOption->stockEnough($this->total)) {
  249. throw new AppException('(ID:' . $this->goods_id . ')商品库存不足');
  250. }
  251. }else{
  252. // 普通商品
  253. if (!$this->goods->stockEnough($this->total)) {
  254. throw new AppException('(ID:' . $this->goods_id . ')商品库存不足');
  255. }
  256. }
  257. }
  258. public function expansion()
  259. {
  260. return $this->hasMany(OrderGoodsExpansion::class);
  261. }
  262. public function getExpansion($key = '')
  263. {
  264. if (!$key) {
  265. return $this->expansion;
  266. }
  267. return isset($this->expansion->where('key', $key)->first()['value']) ? $this->expansion->where('key', $key)->first()['value'] : null;
  268. }
  269. /**
  270. * 订单商品是否包邮
  271. * @return bool true 包邮
  272. */
  273. public function isFreeShipping()
  274. {
  275. if (isset($this->goods->hasOneSale) && $this->goods->hasOneSale->isFree($this)) {
  276. return true;
  277. }
  278. return false;
  279. }
  280. private $goodsStock;
  281. public function goodsStock()
  282. {
  283. if (!isset($this->goodsStock)) {
  284. $this->goodsStock = new GoodsStock($this);
  285. }
  286. return $this->goodsStock;
  287. }
  288. }