PreOrder.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. <?php
  2. namespace app\frontend\modules\order\models;
  3. use app\frontend\models\order\PreOrderPlugin;
  4. use app\frontend\modules\dispatch\discount\EnoughReduce;
  5. use app\frontend\modules\dispatch\models\OrderFreight;
  6. use app\frontend\modules\order\coinExchange\OrderCoinExchangeManager;
  7. use app\frontend\modules\order\discount\OrderFreightDeductionPriceNode;
  8. use app\frontend\modules\order\OrderFee;
  9. use app\frontend\modules\order\serviceFee\OrderServiceFeeManager;
  10. use app\frontend\modules\order\taxFee\OrderTaxFeeManager;
  11. use Illuminate\Http\Request;
  12. use app\common\models\BaseModel;
  13. use app\common\models\DispatchType;
  14. use app\common\models\Member;
  15. use app\common\models\OrderRequest;
  16. use app\common\modules\orderGoods\OrderGoodsCollection;
  17. use app\frontend\models\Order;
  18. use app\frontend\models\order\PreOrderDeduction;
  19. use app\frontend\modules\deduction\OrderDeductManager;
  20. use app\frontend\modules\deduction\OrderDeductionCollection;
  21. use app\frontend\modules\dispatch\models\OrderDispatch;
  22. use app\frontend\modules\dispatch\models\PreOrderAddress;
  23. use app\frontend\modules\order\discount\BaseDiscount;
  24. use app\frontend\modules\order\discount\OrderDiscountPriceNode;
  25. use app\frontend\modules\order\discount\OrderMinDeductionPriceNode;
  26. use app\frontend\modules\order\discount\OrderRestDeductionPriceNode;
  27. use app\frontend\modules\order\OrderDiscount;
  28. use app\common\modules\orderGoods\models\PreOrderGoods;
  29. use app\frontend\modules\order\PriceNode;
  30. use app\frontend\modules\order\PriceNodeTrait;
  31. use app\frontend\modules\order\services\OrderService;
  32. use app\frontend\modules\orderGoods\models\PreOrderGoodsCollection;
  33. use Illuminate\Support\Collection;
  34. /**
  35. * 订单生成类
  36. * Class preOrder
  37. * @package app\frontend\modules\order\services\models
  38. * @property OrderDeductionCollection orderDeductions
  39. * @property Collection orderDiscounts
  40. * @property Collection orderFees
  41. * @property Collection orderTaxFees
  42. * @property Collection orderCoupons
  43. * @property Collection orderSettings
  44. * @property int id
  45. * @property string mark
  46. * @property string pre_id
  47. * @property float price
  48. * @property float goods_price
  49. * @property float order_goods_price
  50. * @property float discount_price
  51. * @property float deduction_price
  52. * @property float dispatch_price
  53. * @property int goods_total
  54. * @property string order_sn
  55. * @property int create_time
  56. * @property int uid
  57. * @property PreOrderAddress orderAddress
  58. * @property int uniacid
  59. * @property PreOrderGoodsCollection orderGoods
  60. * @property Member belongsToMember
  61. * @property DispatchType hasOneDispatchType
  62. */
  63. class PreOrder extends Order
  64. {
  65. use PreOrderTrait;
  66. use PriceNodeTrait;
  67. protected $appends = ['pre_id'];
  68. /**
  69. * @var Member $belongsToMember
  70. */
  71. public $belongsToMember;
  72. /**
  73. * @var OrderFreight 运费类
  74. */
  75. protected $freightManager;
  76. /**
  77. * @var OrderDiscount 优惠类
  78. */
  79. protected $discount;
  80. /**
  81. * @var OrderFee 手续费类
  82. */
  83. protected $orderFeeManager;
  84. /**
  85. * @var OrderTaxFeeManager 税费类
  86. */
  87. protected $orderTaxFeeManager;
  88. /**
  89. * @var OrderDeductManager 抵扣类
  90. */
  91. protected $orderDeductManager;
  92. /**
  93. * @var OrderCoinExchangeManager
  94. */
  95. protected $orderCoinExchangeManager;
  96. /**
  97. * @var OrderServiceFeeManager 服务费类
  98. */
  99. protected $orderServiceFeeManager;
  100. /**
  101. * @var \app\frontend\modules\order\dispatch\order\BaseOrderDispatchType 配送方式
  102. */
  103. protected $orderDispatchType;
  104. /**
  105. * @var Request
  106. */
  107. protected $request;
  108. protected $attributes = ['id' => null];
  109. private $discountWeight = 0;
  110. /**
  111. * @return mixed
  112. * @throws \app\common\exceptions\AppException
  113. */
  114. public function _getPriceNodes()
  115. {
  116. // 订单节点
  117. $nodeSettings = \app\common\modules\shop\ShopConfig::current()->get('shop-foundation.order-price-nodes');
  118. $nodes = collect($nodeSettings)->map(function ($nodeSetting) {
  119. return call_user_func($nodeSetting['class'], $this);
  120. });
  121. $this->discountWeight = 0;
  122. // 订单优惠的节点
  123. $discountNodes = $this->getDiscounts()->map(function (BaseDiscount $discount) {
  124. $this->discountWeight++;
  125. return new OrderDiscountPriceNode($this, $discount, 2000 + $this->discountWeight);
  126. });
  127. //订单运费抵扣节点
  128. $deductionFreightNodes = $this->getOrderDeductions()->map(function (PreOrderDeduction $orderDeduction) {
  129. $this->discountWeight++;
  130. return new OrderFreightDeductionPriceNode($this, $orderDeduction, 8000 + $this->discountWeight);
  131. })->values();
  132. // 订单最低抵扣节点
  133. $deductionMinNodes = $this->getOrderDeductions()->map(function (PreOrderDeduction $orderDeduction) {
  134. return new OrderMinDeductionPriceNode($this, $orderDeduction, 9000 + $this->discountWeight);
  135. });
  136. // 订单剩余抵扣节点
  137. $deductionRestNodes = $this->getOrderDeductions()->map(function (PreOrderDeduction $orderDeduction) {
  138. $a = new OrderRestDeductionPriceNode($this, $orderDeduction, 9100 + $this->discountWeight);
  139. //dump($a->getKey());
  140. return $a;
  141. });
  142. // 按照weight排序
  143. $nodes = $nodes
  144. ->merge($discountNodes)
  145. ->merge($deductionFreightNodes)
  146. ->merge($deductionMinNodes)
  147. ->merge($deductionRestNodes)
  148. ->sortBy(function (PriceNode $priceNode) {
  149. return $priceNode->getWeight();
  150. })->values();
  151. // $nodes->map(function ($a) {dump($a->getKey());});dd($nodes);
  152. return $nodes;
  153. }
  154. function __construct(array $attributes = [])
  155. {
  156. parent::__construct($attributes);
  157. $this->setRelation('orderSettings', $this->newCollection());
  158. }
  159. /**
  160. * @param Member $member
  161. * @param OrderGoodsCollection $orderGoods
  162. * @param Request|null $request
  163. * @return $this
  164. * @throws \app\common\exceptions\ShopException
  165. */
  166. public function init(Member $member, OrderGoodsCollection $orderGoods, Request $request)
  167. {
  168. $this->setRequest($request);
  169. $this->setMember($member);
  170. $this->beforeCreating();
  171. $this->setOrderGoods($orderGoods);
  172. $this->setOrderPlugin();
  173. $this->setGoodsTradeLog();
  174. $this->afterCreating();
  175. $this->initAttributes();
  176. return $this;
  177. }
  178. public function getOrderFeeManager()
  179. {
  180. if (!isset($this->orderFeeManager)) {
  181. $this->orderFeeManager = new OrderFee($this);
  182. }
  183. return $this->orderFeeManager;
  184. }
  185. public function getOrderCoinExchangeManager()
  186. {
  187. if (!isset($this->orderCoinExchangeManager)) {
  188. $this->orderCoinExchangeManager = new OrderCoinExchangeManager($this);
  189. }
  190. return $this->orderCoinExchangeManager;
  191. }
  192. public function getOrderCoinExchanges()
  193. {
  194. return $this->getOrderCoinExchangeManager()->getOrderCoinExchangeCollection();
  195. }
  196. public function getDiscount()
  197. {
  198. if (!isset($this->discount)) {
  199. $this->discount = new OrderDiscount($this);
  200. }
  201. return $this->discount;
  202. }
  203. /**
  204. * 获取订单运费计算类
  205. * @return OrderFreight
  206. */
  207. final public function getFreightManager()
  208. {
  209. if (!isset($this->freightManager)) {
  210. $this->freightManager = $this->_getFreightManager();
  211. }
  212. return $this->freightManager;
  213. }
  214. /**
  215. * 返回指定的运费计算类
  216. * @return OrderFreight
  217. */
  218. protected function _getFreightManager()
  219. {
  220. //默认自定义订单运费
  221. //return new \app\frontend\modules\dispatch\models\DefaultOrderFreight($this,100);
  222. return new OrderFreight($this);
  223. }
  224. // public function getOrderDispatch()
  225. // {
  226. // if (!isset($this->orderDispatch)) {
  227. // $this->orderDispatch = new OrderDispatch($this);
  228. // }
  229. // return $this->orderDispatch;
  230. // }
  231. /**
  232. * @return OrderDeductManager
  233. */
  234. public function getOrderDeductManager()
  235. {
  236. if (!isset($this->orderDeductManager)) {
  237. $this->orderDeductManager = new OrderDeductManager($this);
  238. }
  239. return $this->orderDeductManager;
  240. }
  241. public function getFreightDeduction()
  242. {
  243. return $this->getFreightManager()->orderFreightDeduction();
  244. }
  245. /**
  246. * @return OrderDeductionCollection|static
  247. * @throws \app\common\exceptions\AppException
  248. */
  249. public function getCheckedOrderDeductions()
  250. {
  251. return $this->getOrderDeductManager()->getCheckedOrderDeductions();
  252. }
  253. /**
  254. * @return OrderDeductionCollection
  255. * @throws \app\common\exceptions\AppException
  256. */
  257. public function getOrderDeductions()
  258. {
  259. if (!$this->getRelation('orderDeductions')) {
  260. $this->setRelation('orderDeductions', $this->getOrderDeductManager()->getOrderDeductions());
  261. }
  262. return $this->orderDeductions;
  263. }
  264. public function setRequest(Request $request)
  265. {
  266. $this->request = $request;
  267. }
  268. //todo 为了兼容插件单独的默认配送模版,从order类获取,这样插件订单类好复写
  269. public function getPluginDefaultDispatchId()
  270. {
  271. $defaultDispatch = \app\backend\modules\goods\models\Dispatch::getOneByDefault();
  272. //todo 如果没有默认配送模版 如何处理
  273. trace_log()->freight('订单模板运费', '不存在默认的配送模板');
  274. return $defaultDispatch->id ?: 0;
  275. }
  276. /**
  277. * @param $member
  278. */
  279. public function setMember($member)
  280. {
  281. $this->belongsToMember = $member;
  282. $this->uid = $this->belongsToMember->uid;
  283. $this->uniacid = $this->getUniacid();
  284. }
  285. /**
  286. * 获取request对象
  287. * @return Request
  288. */
  289. public function getRequest()
  290. {
  291. if (!isset($this->request)) {
  292. $this->request = request();
  293. }
  294. return $this->request;
  295. }
  296. /**
  297. * 依赖对象传入之前
  298. * @throws \app\common\exceptions\ShopException
  299. */
  300. public function beforeCreating()
  301. {
  302. $this->dispatch_type_id = $this->getRequest()->input('dispatch_type_id', 0);
  303. $this->setOrderInvoice();
  304. //临时处理,无扩展性
  305. if ($this->getRequest()->input('mark') !== 'undefined') {
  306. $this->mark = $this->getRequest()->input('mark', '');
  307. }
  308. $this->setOrderDispatchType();
  309. $this->setOrderAddress();
  310. if(app('plugins')->isEnabled('pc-terminal') && request()->pc && request()->type == 5){
  311. //pc端限制下单必须绑定手机
  312. $status = \Yunshop\PcTerminal\service\SetService::bindMobileStatus();
  313. if(!$status){
  314. return;
  315. }
  316. $member = \app\frontend\models\Member::current();
  317. if(empty($member)){
  318. throw new \app\common\exceptions\AppException('会员信息错误');
  319. }
  320. if(empty($member->mobile)){
  321. throw new \app\common\exceptions\AppException('请先绑定手机号再下单');
  322. }
  323. }
  324. }
  325. /**
  326. * 订单发票信息
  327. * @throws \app\common\exceptions\ShopException
  328. */
  329. public function setOrderInvoice()
  330. {
  331. $orderInvoice = new PreOrderInvoice();
  332. $orderInvoice->setOrder($this);
  333. }
  334. public function getOrderDispatchType()
  335. {
  336. if (isset($this->orderDispatchType)) {
  337. return $this->orderDispatchType;
  338. }
  339. return $this->setOrderDispatchType();
  340. }
  341. /**
  342. *
  343. */
  344. public function setOrderDispatchType()
  345. {
  346. $dispatchTypeManager = new \app\frontend\modules\order\dispatch\order\OrderDispatchTypeManager($this);
  347. $this->orderDispatchType = $dispatchTypeManager->getOrderDispatchTypeClass();
  348. return $this->orderDispatchType;
  349. }
  350. /**
  351. * @throws \app\common\exceptions\ShopException
  352. */
  353. public function setOrderAddress()
  354. {
  355. if (!is_null($this->orderDispatchType)) {
  356. $orderAddress = $this->orderDispatchType->preOrderAddress();
  357. }
  358. /**
  359. * @var PreOrderAddress $orderAddress
  360. */
  361. if (!$orderAddress) {
  362. $orderAddress = app('OrderManager')->make('PreOrderAddress');
  363. }
  364. $orderAddress->setOrder($this);
  365. }
  366. /**
  367. * 载入订单商品集合
  368. * @param OrderGoodsCollection $orderGoods
  369. */
  370. public function setOrderGoods(OrderGoodsCollection $orderGoods)
  371. {
  372. $this->setRelation('orderGoods', $orderGoods);
  373. $this->orderGoods->each(function ($aOrderGoods) {
  374. /**
  375. * @var PreOrderGoods $aOrderGoods
  376. */
  377. $aOrderGoods->init($this);
  378. });
  379. }
  380. /**
  381. *订单复写数据生成前绑定方法
  382. */
  383. public function afterCreating()
  384. {
  385. }
  386. public function setOrderPlugin()
  387. {
  388. $orderPlugin = new PreOrderPlugin();
  389. $orderPlugin->setOrder($this);
  390. }
  391. public function setGoodsTradeLog()
  392. {
  393. $goods_trade = new PreGoodsTradeLog();
  394. $goods_trade->setOrder($this);
  395. }
  396. /**
  397. * 显示订单数据
  398. * @return array
  399. */
  400. public function toArray()
  401. {
  402. $attributes = parent::toArray();
  403. $attributes = $this->formatAmountAttributes($attributes);
  404. return $attributes;
  405. }
  406. /**
  407. * 初始化属性
  408. * @throws \app\common\exceptions\AppException
  409. */
  410. protected function initAttributes()
  411. {
  412. $attributes = array(
  413. 'price' => $this->getPrice(),//订单最终支付价格
  414. 'order_goods_price' => $this->getOrderGoodsPrice(),//订单商品成交价
  415. 'vip_order_goods_price' => $this->getVipOrderGoodsPrice(),//订单商品成交价
  416. 'goods_price' => $this->getGoodsPrice(),//订单商品原价
  417. 'cost_amount' => $this->getCostPrice(),//订单商品原价
  418. 'discount_price' => $this->getDiscountAmount(),//订单优惠金额
  419. 'fee_amount' => $this->getFeeAmount(),//订单手续费金额
  420. 'service_fee_amount' => $this->getServiceFeeAmount(),//订单服务费金额
  421. 'deduction_price' => $this->getDeductionAmount(),//订单抵扣金额
  422. 'initial_freight' => $this->getInitialFreight(),//订单初始运费金额
  423. 'dispatch_price' => $this->getDispatchAmount(),//订单最终运费
  424. 'tax_fee' => $this->getTaxFeeAmount(),//订单税费金额
  425. 'goods_total' => $this->getGoodsTotal(),//订单商品总数
  426. 'is_virtual' => $this->isVirtual(),//是否是虚拟商品订单
  427. 'no_refund' => $this->noRefund(),
  428. 'order_sn' => OrderService::createOrderSN(),//订单编号
  429. 'create_time' => time(),
  430. 'note' => $this->getParams('note'),//订单备注
  431. 'shop_name' => $this->getShopName(),// 店铺名称
  432. 'need_address' => $this->isNeedAddress(),//订单不需要填写地址
  433. //发票信息应该保存到订单发票表上
  434. 'invoice_type' => $this->getRequest()->input('invoice_type'),//发票类型
  435. 'rise_type' => $this->getRequest()->input('rise_type'),//收件人或单位
  436. 'collect_name' => $this->getRequest()->input('call'),//抬头或单位名称
  437. 'company_number' => $this->getRequest()->input('company_number'),//单位识别号
  438. );
  439. $attributes = array_merge($this->getAttributes(), $attributes);
  440. $this->setRawAttributes($attributes);
  441. }
  442. protected function noRefund()
  443. {
  444. foreach ($this->orderGoods as $goods) {
  445. if ($goods->goods->no_refund) {
  446. return 1;
  447. }
  448. }
  449. return 0;
  450. }
  451. public function beforeSaving()
  452. {
  453. //订单保存前,验证订单地址是否有填写
  454. if (!is_null($this->orderAddress) &&
  455. method_exists($this->orderAddress, 'validateAddress')
  456. && is_callable([$this->orderAddress, 'validateAddress'])
  457. ) {
  458. $this->orderAddress->validateAddress();
  459. }
  460. // 订单保存前,验证配送方式
  461. if (!is_null($this->orderDispatchType) &&
  462. method_exists($this->orderDispatchType, 'validateDelivery')
  463. && is_callable([$this->orderDispatchType, 'validateDelivery'])
  464. ) {
  465. $this->orderDispatchType->validateDelivery();
  466. }
  467. $this->loadPluginsRelations();
  468. $this->setOrderRequest($this->getRequest()->input());
  469. }
  470. //订单插件关系验证和关系保存
  471. protected function loadPluginsRelations()
  472. {
  473. $relations = \app\common\modules\shop\ShopConfig::current()->get('shop-foundation.order-save-relations');
  474. foreach ($relations as $relation) {
  475. if ($relation['class']) {
  476. $relationModel = call_user_func($relation['class'], []);
  477. $relationModel->setOrder($this);
  478. if ($relationModel->validateSave()) {
  479. $this->setRelation($relation['key'], $relationModel);
  480. }
  481. }
  482. }
  483. }
  484. public function setOrderRequest(array $input)
  485. {
  486. $orderRequest = new OrderRequest();
  487. if ($input['address']) {
  488. $input['address'] = urldecode($input['address']);
  489. }
  490. $orderRequest->request = $input;
  491. $orderRequest->ip = $this->request->getClientIp();
  492. $this->setRelation('orderRequest', $orderRequest);
  493. }
  494. public function getCostPrice()
  495. {
  496. //累加所有商品数量
  497. $result = $this->orderGoods->sum(function (PreOrderGoods $aOrderGoods) {
  498. return $aOrderGoods->goods_cost_price;
  499. });
  500. return $result;
  501. }
  502. /**
  503. * 获取url中关于本订单的参数
  504. * @param null $key
  505. * @return mixed
  506. */
  507. public function getParams($key = null)
  508. {
  509. $result = collect(json_decode($this->getRequest()->input('orders'), true))->where('pre_id', $this->pre_id)->first();
  510. if (isset($key)) {
  511. return $result[$key];
  512. }
  513. return $result;
  514. }
  515. /**
  516. * 订单生成前 分组订单的标识(规则: 将goods_id 排序之后用a连接)
  517. * @return string
  518. */
  519. public function getPreIdAttribute()
  520. {
  521. return md5($this->orderGoods->pluck('goods_id')->toJson());
  522. }
  523. /**
  524. * 计算订单成交价格
  525. * 外部调用只计算一次,方法内部计算过程中递归调用会返回计算过程中的金额
  526. * @return float|mixed
  527. * @throws \app\common\exceptions\AppException
  528. */
  529. protected function getPrice()
  530. {
  531. $price = max($this->getPriceAfter($this->getPriceNodes()->last()->getKey()), 0);
  532. //四舍六入五成双 银行家算法,
  533. return round($price,2,PHP_ROUND_HALF_EVEN);
  534. }
  535. /**
  536. * @return float|mixed
  537. * @throws \app\common\exceptions\AppException
  538. */
  539. public function getPriceAttribute()
  540. {
  541. return $this->getPrice();
  542. }
  543. /**
  544. * 获取所有优惠
  545. * @return Collection
  546. */
  547. protected function getDiscounts()
  548. {
  549. return $this->getDiscount()->getDiscounts();
  550. }
  551. /**
  552. * 获取总优惠金额
  553. * @return Collection
  554. */
  555. protected function getDiscountAmount()
  556. {
  557. return $this->getDiscount()->getAmount();
  558. }
  559. /**
  560. * 获取总税费金额
  561. * @return Collection
  562. */
  563. protected function getTaxFeeAmount()
  564. {
  565. return $this->getOrderTaxFeeManager()->getAmount();
  566. }
  567. /**
  568. * 获取总手续费金额
  569. * @return Collection
  570. */
  571. protected function getFeeAmount()
  572. {
  573. return $this->getOrderFeeManager()->getAmount();
  574. }
  575. /**
  576. * 获取总服务费金额
  577. * @return Collection
  578. */
  579. protected function getServiceFeeAmount()
  580. {
  581. return $this->getOrderServiceFeeManager()->getAmount();
  582. }
  583. public function getOrderServiceFeeManager()
  584. {
  585. if (!isset($this->orderServiceFeeManager)) {
  586. $this->orderServiceFeeManager = new OrderServiceFeeManager($this);
  587. }
  588. return $this->orderServiceFeeManager;
  589. }
  590. public function getOrderTaxFeeManager()
  591. {
  592. if (!isset($this->orderTaxFeeManager)) {
  593. $this->orderTaxFeeManager = new OrderTaxFeeManager($this);
  594. }
  595. return $this->orderTaxFeeManager;
  596. }
  597. /**
  598. * 获取订单抵扣金额
  599. * @return int
  600. * @throws \app\common\exceptions\AppException
  601. */
  602. public function getDeductionAmount()
  603. {
  604. return $this->getCheckedOrderDeductions()->sum('amount') ?: 0;
  605. }
  606. /**
  607. * 计算订单最终运费
  608. * @return int|number
  609. */
  610. public function getDispatchAmount()
  611. {
  612. return $this->getFreightManager()->getFinalFreightAmount();
  613. // return $this->getOrderDispatch()->getFreight();
  614. }
  615. /**
  616. * 计算订单初始运费
  617. * @return int|number
  618. */
  619. public function getInitialFreight()
  620. {
  621. return $this->getFreightManager()->getInitialFreightAmount();
  622. }
  623. public function getDispatchAmountAttribute()
  624. {
  625. return $this->getDispatchAmount();
  626. }
  627. public function getInitialFreightAttribute()
  628. {
  629. return $this->getInitialFreight();
  630. }
  631. /**
  632. * 获取满额包邮类
  633. * @return EnoughReduce
  634. * @author: Merlin
  635. * @Time: 2020/11/24 17:27
  636. */
  637. // public function getEnoughReduce()
  638. // {
  639. // return new EnoughReduce($this);
  640. // }
  641. /**
  642. * 公众号
  643. * @return int
  644. */
  645. private function getUniacid()
  646. {
  647. return $this->belongsToMember->uniacid;
  648. }
  649. /**
  650. * 店铺名
  651. * @return string
  652. */
  653. protected function getShopName()
  654. {
  655. return \Setting::get('shop.shop.name') ?: '平台自营';
  656. }
  657. /**
  658. * 是否禁用订单抵扣
  659. * @return bool true 禁用 false 正常
  660. */
  661. public function isDeductionDisable()
  662. {
  663. return false;
  664. }
  665. /**
  666. * 是否禁用订单优惠
  667. * @return bool true 禁用 false 正常
  668. */
  669. public function isDiscountDisable()
  670. {
  671. return false;
  672. }
  673. /**
  674. * 统计订单商品是否有虚拟商品
  675. * @return bool
  676. */
  677. public function isVirtual()
  678. {
  679. if ($this->is_virtual == 1) {
  680. return true;
  681. }
  682. return $this->orderGoods->hasVirtual();
  683. }
  684. /**
  685. * 订单是否需要填写地址
  686. * @return bool true 不需要 false 需要
  687. */
  688. public function isNeedAddress()
  689. {
  690. if ($this->need_address == 1) {
  691. return true;
  692. }
  693. if (!is_null($this->hasOneDispatchType) && !$this->hasOneDispatchType->need_send) {
  694. return false;
  695. }
  696. return $this->orderGoods->hasNeedAddress();
  697. }
  698. /**
  699. * @var array 需要批量更新的字段
  700. */
  701. private $batchSaveRelations = ['orderGoods', 'orderSettings', 'orderCoupons', 'orderDiscounts', 'orderDeductions', 'orderFees', 'orderTaxFees', 'orderServiceFees'];
  702. /**
  703. * 保存关联模型
  704. * @return bool
  705. * @throws \Exception
  706. */
  707. public function push()
  708. {
  709. foreach ($this->relations as $models) {
  710. $models = $models instanceof Collection
  711. ? $models->all() : [$models];
  712. /**
  713. * @var BaseModel $model
  714. */
  715. foreach (array_filter($models) as $model) {
  716. if (!isset($model->order_id) && $model->hasColumn('order_id')) {
  717. $model->order_id = $this->id;
  718. }
  719. }
  720. }
  721. /**
  722. * 一对一关联模型保存
  723. */
  724. $relations = array_except($this->relations, $this->batchSaveRelations);
  725. foreach ($relations as $models) {
  726. $models = $models instanceof Collection
  727. ? $models->all() : [$models];
  728. foreach (array_filter($models) as $model) {
  729. if (!$model->push()) {
  730. return false;
  731. }
  732. }
  733. }
  734. /**
  735. * 多对多关联模型保存
  736. */
  737. $this->insertRelations($this->batchSaveRelations);
  738. return true;
  739. }
  740. /**
  741. * 保存每一种 多对多的关联模型集合
  742. * @param array $relations
  743. */
  744. private function insertRelations($relations = [])
  745. {
  746. foreach ($relations as $relation) {
  747. if ($this->$relation->isNotEmpty()) {
  748. $this->saveManyRelations($relation);
  749. }
  750. }
  751. }
  752. /**
  753. * 保存一种 多对多的关联模型集合
  754. * @param $relation
  755. */
  756. private function saveManyRelations($relation)
  757. {
  758. $attributeItems = $this->$relation->map(function (BaseModel $relation) {
  759. $relation->updateTimestamps();
  760. $beforeSaving = $relation->beforeSaving();
  761. if ($beforeSaving === false) {
  762. return [];
  763. }
  764. return $relation->getAttributes();
  765. });
  766. $attributeItems = collect($attributeItems)->filter();
  767. $this->$relation->first()->insert($attributeItems->toArray());
  768. /**
  769. * @var Collection $ids
  770. */
  771. $ids = $this->$relation()->pluck('id');
  772. $this->$relation->each(function (BaseModel $item) use ($ids) {
  773. $item->id = $ids->shift();
  774. $item->afterSaving();
  775. });
  776. }
  777. }