AutoCalculatePriceTrait.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. <?php
  2. namespace addons\TinyShop\common\traits;
  3. use common\helpers\ArrayHelper;
  4. use common\helpers\BcHelper;
  5. use addons\TinyShop\common\models\order\OrderProduct;
  6. use addons\TinyShop\common\forms\PreviewForm;
  7. /**
  8. * 自动计算优惠
  9. *
  10. * Trait AutoCalculatePriceTrait
  11. * @package addons\TinyShop\common\traits
  12. */
  13. trait AutoCalculatePriceTrait
  14. {
  15. /**
  16. * @var int
  17. */
  18. private $marketing_money = 0;
  19. /**
  20. * @param PreviewForm $form
  21. * @return PreviewForm
  22. */
  23. public function calculatePrice(PreviewForm $form)
  24. {
  25. $this->marketing_money = 0;
  26. // 所有数据
  27. $allData = [];
  28. // sku 所有数据
  29. $skuData = [];
  30. foreach ($form->groupOrderProducts as $product_id => $groupOrderProduct) {
  31. $allData[] = [
  32. 'uuid' => $product_id,
  33. 'original_money' => $groupOrderProduct['product_money'], // 原始金额
  34. 'surplus_money' => $groupOrderProduct['product_money'], // 剩余金额
  35. 'discount_money' => 0, // 已优惠金额
  36. 'cate_id' => [], // 商品商家分类
  37. 'platform_cate_id' => [], // 平台分类
  38. 'merchant_id' => $groupOrderProduct['merchant_id'], // 商家ID
  39. ];
  40. /** @var OrderProduct $orderProduct */
  41. foreach ($groupOrderProduct['products'] as $orderProduct) {
  42. $skuData[] = [
  43. 'uuid' => $orderProduct->sku_id,
  44. 'product_id' => $orderProduct->id,
  45. 'original_money' => $orderProduct->product_money, // 原始金额
  46. 'surplus_money' => $orderProduct->product_money, // 剩余金额
  47. 'discount_money' => 0, // 已优惠金额
  48. 'cate_id' => [], // 商品商家分类
  49. 'platform_cate_id' => [], // 平台分类
  50. 'merchant_id' => $groupOrderProduct['merchant_id'], // 商家ID
  51. ];
  52. }
  53. }
  54. $tmpMarketingDetails = $form->marketingDetails;
  55. list($allData, $form->marketingDetails) = $this->filterData($allData, $form->marketingDetails);
  56. // 把优惠的金额分配到商品上面
  57. $allData = ArrayHelper::arrayKey($allData, 'uuid');
  58. $skuMarketingDetails = [];
  59. foreach ($form->groupOrderProducts as $product_id => &$groupOrderProduct) {
  60. if (isset($allData[$product_id]) && $allData[$product_id]['discount_money'] > 0) {
  61. $groupOrderProduct['product_money'] = BcHelper::sub($groupOrderProduct['product_money'], $allData[$product_id]['discount_money']);
  62. $skuMarketingDetails[] = [
  63. 'uuid' => ArrayHelper::getColumn($groupOrderProduct['products'], 'sku_id'),
  64. 'discount_money' => $allData[$product_id]['discount_money']
  65. ];
  66. }
  67. }
  68. // 计算总优惠
  69. $form->product_money = BcHelper::sub($form->product_money, $this->marketing_money);
  70. $form->product_money < 0 && $form->product_money = 0;
  71. $form->marketing_money += $this->marketing_money;
  72. // 继续分配到最终商品上
  73. list($skuData) = $this->filterData($skuData, $skuMarketingDetails);
  74. $skuData = ArrayHelper::arrayKey($skuData, 'uuid');
  75. foreach ($form->groupOrderProducts as $product_id => &$groupOrderProduct) {
  76. foreach ($groupOrderProduct['products'] as $orderProduct) {
  77. if (isset($skuData[$orderProduct->sku_id]) && $skuData[$orderProduct->sku_id]['discount_money'] > 0) {
  78. $orderProduct->product_money = BcHelper::sub($orderProduct->product_money, $skuData[$orderProduct->sku_id]['discount_money']);
  79. $orderProduct->price = BcHelper::div($orderProduct->product_money, $orderProduct->num);
  80. }
  81. }
  82. }
  83. // 初始化数据
  84. unset($allData, $skuData, $skuMarketingDetails, $tmpMarketingDetails);
  85. return $form;
  86. }
  87. /**
  88. * @param array $allData 所有数据
  89. * @param array $marketingDetails 优惠数组
  90. * @return array
  91. */
  92. protected function filterData($allData, $marketingDetails)
  93. {
  94. if (empty($marketingDetails) || empty($allData)) {
  95. return [$allData, $marketingDetails];
  96. }
  97. // 可用的优惠券
  98. $usableMarketingDetails = [];
  99. foreach ($marketingDetails as &$marketingDetail) {
  100. if (isset($marketingDetail['used']) && $marketingDetail['used'] === true) {
  101. continue;
  102. }
  103. if (isset($marketingDetail['discount_money']) && $marketingDetail['discount_money'] > 0) {
  104. $marketingDetail['used'] = true;
  105. !isset($marketingDetail['uuid']) && $marketingDetail['uuid'] = []; // 指定ID
  106. !isset($marketingDetail['cate_id']) && $marketingDetail['cate_id'] = []; // 指定分类
  107. !isset($marketingDetail['platform_cate_id']) && $marketingDetail['platform_cate_id'] = []; // 指定平台分类
  108. !isset($marketingDetail['merchant_id']) && $marketingDetail['merchant_id'] = []; // 指定商家
  109. $usableMarketingDetails[] = $marketingDetail;
  110. }
  111. }
  112. if (empty($usableMarketingDetails)) {
  113. return [$allData, $marketingDetails];
  114. }
  115. // 匹配优惠符合的
  116. foreach ($usableMarketingDetails as &$usableMarketingDetail) {
  117. $usableData = [];
  118. foreach ($allData as $key => $datum) {
  119. $verifyStatus = true;
  120. // 验证ID匹配
  121. if (!empty($usableMarketingDetail['uuid']) && !in_array($datum['uuid'], $usableMarketingDetail['uuid'])) {
  122. $verifyStatus = false;
  123. }
  124. // 验证商家ID匹配
  125. if (!empty($usableMarketingDetail['merchant_id']) && !in_array($datum['merchant_id'], $usableMarketingDetail['merchant_id'])) {
  126. $verifyStatus = false;
  127. }
  128. // 验证分类匹配
  129. if (!empty($usableMarketingDetail['cate_id']) && empty(array_intersect($datum['cate_id'], $usableMarketingDetail['cate_id']))) {
  130. $verifyStatus = false;
  131. }
  132. // 验证平台分类匹配
  133. if (!empty($usableMarketingDetail['platform_cate_id']) && empty(array_intersect($datum['platform_cate_id'], $usableMarketingDetail['platform_cate_id']))) {
  134. $verifyStatus = false;
  135. }
  136. $verifyStatus == true && $usableData[$key] = $datum;
  137. }
  138. // 开始计算优惠
  139. if (!empty($usableData)) {
  140. $usableData = $this->allocationPrice($usableMarketingDetail['discount_money'], $usableData);
  141. // 重新赋值
  142. foreach ($usableData as $k => $usableDatum) {
  143. $allData[$k] = $usableDatum;
  144. }
  145. }
  146. }
  147. return [$allData, $marketingDetails];
  148. }
  149. /**
  150. * 分配
  151. *
  152. * @param float $discountMoney 优惠总金额
  153. * @param array $usableData 待计算的数据
  154. */
  155. protected function allocationPrice($discountMoney, &$usableData)
  156. {
  157. $count = count($usableData);
  158. $totalMoney = 0;
  159. foreach ($usableData as $usableDatum) {
  160. $totalMoney = BcHelper::add($totalMoney, $usableDatum['surplus_money']);
  161. }
  162. // 超出优惠
  163. if ($discountMoney >= $totalMoney) {
  164. foreach ($usableData as &$usableDatum) {
  165. $usableDatum['discount_money'] = $usableDatum['surplus_money'];
  166. $usableDatum['surplus_money'] = 0;
  167. }
  168. // 记录营销金额
  169. $this->marketing_money = $totalMoney;
  170. return $usableData;
  171. }
  172. // ----------- 开始计算优惠 优惠百分比 ------------ //
  173. // 百分比率
  174. $percentage = BcHelper::div($discountMoney, $totalMoney, 20);
  175. foreach ($usableData as &$usableDatum) {
  176. if ($usableDatum['surplus_money'] <= 0 || $discountMoney <= 0) {
  177. continue;
  178. }
  179. // 优惠金额
  180. $tmpDiscount = BcHelper::mul($usableDatum['surplus_money'], $percentage);
  181. // 剩余优惠金额
  182. $discountMoney = BcHelper::sub($discountMoney, $tmpDiscount);
  183. // 剩余余额
  184. $usableDatum['surplus_money'] = BcHelper::sub($usableDatum['surplus_money'], $tmpDiscount);
  185. // 已优惠金额
  186. $usableDatum['discount_money'] = BcHelper::add($usableDatum['discount_money'], $tmpDiscount);
  187. // 记录营销金额
  188. $this->marketing_money = BcHelper::add($this->marketing_money, $tmpDiscount);
  189. }
  190. // 判断是否还有剩余
  191. if ($discountMoney > 0) {
  192. foreach ($usableData as &$usableDatum) {
  193. if ($usableDatum['surplus_money'] <= 0 || $discountMoney <= 0) {
  194. continue;
  195. }
  196. // 剩余金额大于优惠金额
  197. if ($usableDatum['surplus_money'] >= $discountMoney) {
  198. // 剩余余额
  199. $usableDatum['surplus_money'] = BcHelper::sub($usableDatum['surplus_money'], $discountMoney);
  200. // 已优惠金额
  201. $usableDatum['discount_money'] = BcHelper::add($usableDatum['discount_money'], $discountMoney);
  202. // 记录营销金额
  203. $this->marketing_money = BcHelper::add($this->marketing_money, $discountMoney);
  204. // 剩余优惠金额
  205. $discountMoney = 0;
  206. } else {
  207. // 剩余优惠金额
  208. $discountMoney = BcHelper::sub($discountMoney, $usableDatum['surplus_money']);;
  209. // 已优惠金额
  210. $usableDatum['discount_money'] = BcHelper::add($usableDatum['discount_money'], $usableDatum['surplus_money']);
  211. // 记录营销金额
  212. $this->marketing_money = BcHelper::add($this->marketing_money, $usableDatum['surplus_money']);
  213. // 剩余余额
  214. $usableDatum['surplus_money'] = 0;
  215. }
  216. }
  217. }
  218. return $usableData;
  219. }
  220. }
粤ICP备19079148号