BaseOrderGoodsPrice.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. <?php
  2. namespace app\frontend\modules\orderGoods\price\option;
  3. /**
  4. * Created by PhpStorm.
  5. * User: shenyang
  6. * Date: 2017/5/19
  7. * Time: 下午6:04
  8. */
  9. use app\common\helpers\Serializer;
  10. use app\frontend\models\order\PreOrderCoinExchange;
  11. use app\frontend\models\orderGoods\PreOrderGoodsCoinExchange;
  12. use app\frontend\modules\deduction\orderGoods\PreOrderGoodsDeduction;
  13. use app\frontend\modules\order\PriceNode;
  14. use app\frontend\modules\order\PriceNodeTrait;
  15. use app\frontend\modules\orderGoods\discount\BaseDiscount;
  16. use app\frontend\modules\orderGoods\GoodsPriceNodeBase;
  17. use app\frontend\modules\orderGoods\OrderGoodsCouponPriceNode;
  18. use app\frontend\modules\orderGoods\OrderGoodsDeductionPriceNode;
  19. use app\frontend\modules\orderGoods\OrderGoodsDiscountPriceNode;
  20. use app\frontend\models\orderGoods\PreOrderGoodsDiscount;
  21. use app\frontend\modules\orderGoods\OrderGoodsTaxfeeNode;
  22. use app\frontend\modules\orderGoods\price\adapter\GoodsAdapterManager;
  23. use app\frontend\modules\orderGoods\taxFee\BaseTaxFee;
  24. abstract class BaseOrderGoodsPrice extends OrderGoodsPrice
  25. {
  26. use PriceNodeTrait;
  27. /**
  28. * @var float
  29. */
  30. private $deductionAmount;
  31. private $deductionCount;
  32. /**
  33. * @var float
  34. */
  35. private $paymentAmount;
  36. /**
  37. * @var float
  38. */
  39. private $price;
  40. protected $priceClass;
  41. private $deductionWeight = 0;
  42. public function _getPriceNodes()
  43. {
  44. // 订单节点
  45. $nodes = collect([
  46. new GoodsPriceNodeBase($this, 1000)
  47. ]);
  48. // 订单优惠的节点
  49. $discountNodes = $this->orderGoods->getDiscounts()->map(function (BaseDiscount $discount) {
  50. return new OrderGoodsDiscountPriceNode($this, $discount);
  51. });
  52. // foreach (\app\common\modules\shop\ShopConfig::current()->get('shop-foundation.goods-discount') as $configItem) {
  53. // $discountNodes->push(new OrderGoodsDiscountPriceNode($this, call_user_func($configItem['class'], $this->orderGoods), $configItem['weight']));
  54. // }
  55. // 订单抵扣节点(!!!不要在循环中自增权重,设置为相同的权重是为,getPriceBeforeByWeight方法更容易编写)
  56. $deductionNodes = $this->orderGoods->getOrderGoodsDeductions()->map(function (PreOrderGoodsDeduction $preOrderGoodsDeduction) {
  57. return new OrderGoodsDeductionPriceNode($this, $preOrderGoodsDeduction, 2200);
  58. });
  59. $taxNodes = $this->orderGoods->getTaxFees()->map(function (BaseTaxFee $taxFee) {
  60. return new OrderGoodsTaxfeeNode($this, $taxFee, 2300);
  61. });
  62. // 按照weight排序
  63. return $nodes->merge($discountNodes)->merge($deductionNodes)->merge($taxNodes)->sortBy(function (PriceNode $priceNode) {
  64. return $priceNode->getWeight();
  65. })->values();
  66. }
  67. /**
  68. * @return mixed
  69. */
  70. abstract protected function goods();
  71. abstract protected function aGoodsPrice();
  72. /**
  73. * 成交价
  74. * @return mixed
  75. */
  76. public function getPrice()
  77. {
  78. if (isset($this->price)) {
  79. return $this->price;
  80. }
  81. if ($this->isCoinExchange()) {
  82. return 0;
  83. }
  84. // 商品销售价 - 等级优惠金额
  85. $this->price = $this->getGoodsPrice();
  86. $this->price = max($this->price, 0);
  87. return $this->price;
  88. }
  89. //todo blank 商品价格适配器
  90. public function goodsPriceManager()
  91. {
  92. if (isset($this->priceClass)) {
  93. return $this->priceClass;
  94. }
  95. $this->priceClass = GoodsAdapterManager::preOrderGoods($this->orderGoods);
  96. return $this->priceClass;
  97. }
  98. public function getVipPrice()
  99. {
  100. if ($this->isCoinExchange()) {
  101. return 0;
  102. }
  103. return $this->getGoodsPrice() - $this->getMemberLevelDiscountAmount();
  104. }
  105. private $isCoinExchange;
  106. /**
  107. * @return bool
  108. */
  109. private function isCoinExchange()
  110. {
  111. if (!isset($this->isCoinExchange)) {
  112. //blank not deduction
  113. if ($this->orderGoods->order->isDeductionDisable()) {
  114. $this->isCoinExchange = false;
  115. return $this->isCoinExchange;
  116. }
  117. if (!$this->orderGoods->goods->hasOneSale->has_all_point_deduct) {
  118. $this->isCoinExchange = false;
  119. } else {
  120. $this->isCoinExchange = true;
  121. $relations = collect(\app\common\modules\shop\ShopConfig::current()->get('shop-foundation.coin-exchange'))->sortBy('weight');
  122. foreach ($relations as $configItem) {
  123. $coinExchange = call_user_func($configItem['class'], $this);
  124. if(!$coinExchange->validate()){
  125. continue;
  126. }
  127. $orderCoinExchange = $coinExchange->setLog();
  128. //todo 权重最大的过了直接断循环
  129. break;
  130. }
  131. if(empty($orderCoinExchange)){
  132. //获取商城设置: 判断 积分、余额 是否有自定义名称
  133. $shopSet = \Setting::get('shop.shop');
  134. // 优惠记录
  135. $preOrderGoodsDiscount = new PreOrderGoodsDiscount([
  136. 'discount_code' => 'coinExchange',
  137. 'amount' => $this->getGoodsPrice() ?: 0,
  138. 'name' => $shopSet['credit1'] ? $shopSet['credit1'] . '全额抵扣' : '积分全额抵扣',
  139. ]);
  140. $preOrderGoodsDiscount->setOrderGoods($this->orderGoods);
  141. // 全额抵扣记录
  142. $orderGoodsCoinExchange = new PreOrderGoodsCoinExchange([
  143. 'code' => 'point',
  144. 'amount' => $this->getGoodsPrice() ?: 0,
  145. 'coin' => $this->orderGoods->goods->hasOneSale->all_point_deduct * $this->orderGoods->total,
  146. 'name' => $shopSet['credit1'] ? $shopSet['credit1'] . '全额抵扣' : '积分全额抵扣',
  147. ]);
  148. $orderGoodsCoinExchange->setOrderGoods($this->orderGoods);
  149. $orderCoinExchange = new PreOrderCoinExchange([
  150. 'code' => 'point',
  151. 'amount' => $this->getGoodsPrice() ?: 0,
  152. 'coin' => $this->orderGoods->goods->hasOneSale->all_point_deduct * $this->orderGoods->total,
  153. 'name' => $shopSet['credit1'] ? $shopSet['credit1'] . '全额' : '积分全额',
  154. 'uid' => $this->orderGoods->uid,
  155. ]);
  156. }
  157. $this->orderGoods->order->getOrderCoinExchanges()->addAndGroupByCode($orderCoinExchange);
  158. }
  159. }
  160. return $this->isCoinExchange;
  161. }
  162. /**
  163. * 获取订单商品支付金额
  164. * @return float|mixed
  165. * @throws \app\common\exceptions\AppException
  166. */
  167. public function getPaymentAmount()
  168. {
  169. if (!isset($this->paymentAmount)) {
  170. $this->paymentAmount = $this->getPriceAfter($this->getPriceNodes()->last()->getKey());
  171. $this->paymentAmount = max($this->paymentAmount, 0);
  172. }
  173. return $this->paymentAmount;
  174. }
  175. /**
  176. * 销售价(商品的原销售价)
  177. * @return mixed
  178. */
  179. public function getGoodsPrice()
  180. {
  181. return $this->aGoodsPrice() * $this->orderGoods->total;
  182. }
  183. /**
  184. * 成本价
  185. * @return mixed
  186. */
  187. public function getGoodsCostPrice()
  188. {
  189. return $this->goods()->cost_price * $this->orderGoods->total;
  190. }
  191. /**
  192. * 市场价
  193. * @return mixed
  194. */
  195. public function getGoodsMarketPrice()
  196. {
  197. return $this->goods()->market_price * $this->orderGoods->total;
  198. }
  199. /**
  200. * 优惠券价
  201. * @return int
  202. */
  203. public function getCouponAmount()
  204. {
  205. if (!isset($this->orderGoods->coupons)) {
  206. return 0;
  207. }
  208. return $this->orderGoods->coupons->sum('amount');
  209. }
  210. /**
  211. * 获取订单商品抵扣金额
  212. * @return float
  213. */
  214. public function getDeductionAmount()
  215. {
  216. if ($this->deductionCount != $this->orderGoods->getOrderGoodsDeductions()->count()) {
  217. $this->deductionCount = $this->orderGoods->getOrderGoodsDeductions()->count();
  218. trace_log()->deduction('订单商品计算者', "订单商品计算所有已用的抵扣金额");
  219. $this->deductionAmount = $this->orderGoods->getOrderGoodsDeductions()->getUsedPoint()->getMoney();
  220. }
  221. return $this->deductionAmount;
  222. }
  223. protected $vipDiscountAmount;
  224. protected $vipDiscountLog;
  225. public function getMemberLevelDiscountAmount()
  226. {
  227. if (!isset($this->vipDiscountAmount)) {
  228. $this->vipDiscountAmount = $this->_getVipDiscountAmount($this->goodsPriceManager());
  229. $this->vipDiscountLog = $this->goods()->vipDiscountLog;
  230. }
  231. return $this->vipDiscountAmount;
  232. }
  233. public function getVipDiscountLog()
  234. {
  235. if (!isset($this->vipDiscountLog)) {
  236. $this->getMemberLevelDiscountAmount();
  237. }
  238. return $this->vipDiscountLog;
  239. }
  240. /**
  241. * 商品的会员等级折扣金额
  242. * @return mixed
  243. */
  244. protected function _getVipDiscountAmount($price)
  245. {
  246. return $this->goods()->getVipDiscountAmount($price) * $this->orderGoods->total;
  247. }
  248. /**
  249. * 不可用
  250. * 商品的会员等级折扣金额(缓存)
  251. * @return mixed
  252. */
  253. public function getVipDiscountAmount($price)
  254. {
  255. return 0;
  256. if (!isset($this->vipDiscountAmount)) {
  257. $this->vipDiscountAmount = $this->_getVipDiscountAmount($price);
  258. if ($this->vipDiscountAmount) {
  259. $preOrderGoodsDiscount = new PreOrderGoodsDiscount([
  260. 'discount_code' => $this->goods()->vipDiscountLog->code,
  261. 'amount' => $this->vipDiscountAmount ?: 0,
  262. 'name' => $this->goods()->vipDiscountLog->name,
  263. ]);
  264. $preOrderGoodsDiscount->setOrderGoods($this->orderGoods);
  265. }
  266. }
  267. return $this->vipDiscountAmount;
  268. }
  269. }