OrderCreate.php 94 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace app\model\order;
  11. use addon\coupon\model\Coupon;
  12. use addon\freeshipping\model\Freeshipping;
  13. use addon\manjian\model\Manjian;
  14. use addon\supermember\model\MemberCard;
  15. use addon\supermember\model\MemberLevelOrder;
  16. use app\model\express\Local;
  17. use app\model\goods\Goods;
  18. use app\model\member\Member;
  19. use app\model\member\MemberAccount;
  20. use app\model\member\MemberLevel;
  21. use app\model\store\Store;
  22. use app\model\system\Cron;
  23. use think\facade\Cache;
  24. use app\model\express\Express;
  25. use app\model\system\Pay;
  26. use app\model\goods\Cart;
  27. use app\model\member\MemberAddress;
  28. use app\model\express\Config as ExpressConfig;
  29. use app\model\BaseModel;
  30. use app\model\message\Message;
  31. use addon\pointcash\model\Config as PointCashConfig;
  32. use think\facade\Db;
  33. /**
  34. * 订单创建(普通订单)
  35. *
  36. * @author Administrator
  37. *
  38. */
  39. class OrderCreate extends BaseModel
  40. {
  41. use OrderCreateTool;
  42. private $goods_money = 0; //商品金额
  43. private $delivery_money = 0; //配送费用
  44. private $coupon_money = 0; //优惠券金额
  45. private $adjust_money = 0; //调整金额
  46. private $invoice_money = 0; //发票费用
  47. private $promotion_money = 0; //优惠金额
  48. private $order_money = 0; //订单金额
  49. private $pay_money = 0; //支付总价
  50. private $is_virtual = 0; //是否是虚拟类订单
  51. private $order_name = ''; //订单详情
  52. private $goods_num = 0; //商品种数
  53. private $error = 0; //是否有错误
  54. private $error_msg = ''; //错误描述
  55. private $error_show = false;
  56. private $pay_type = 'ONLINE_PAY';
  57. private $invoice_delivery_money = 0;
  58. private $balance_money = 0;
  59. private $member_balance_money = 0; //会员账户余额(计算过程中会逐次减少)
  60. private $point_money = 0; // 积分抵现金额
  61. private $recommend_member_card; // 推荐会员卡
  62. private $member_card_money = 0; // 会员卡开卡金额
  63. /**
  64. * 订单创建
  65. * @param unknown $data
  66. */
  67. public function create($data)
  68. {
  69. //查询出会员相关信息
  70. $calculate_data = $this->calculate($data);
  71. if (isset($calculate_data[ 'code' ]) && $calculate_data[ 'code' ] < 0)
  72. return $calculate_data;
  73. if ($this->error > 0) {
  74. return $this->error([ 'error_code' => $this->error ], $this->error_msg);
  75. }
  76. if (!empty($calculate_data[ 'invoice_type' ])) {
  77. if ($calculate_data[ 'invoice_type' ] == 1 && $calculate_data[ 'invoice_full_address' ] == '') {
  78. //物流,同城
  79. if ($calculate_data[ 'shop_goods_list' ][ 'delivery' ][ 'delivery_type' ] == 'express' || $calculate_data[ 'shop_goods_list' ][ 'delivery' ][ 'delivery_type' ] == 'local') {
  80. $calculate_data[ 'invoice_full_address' ] = $calculate_data[ 'member_address' ][ 'full_address' ] . $calculate_data[ 'member_address' ][ 'address' ];
  81. $calculate_data[ 'shop_goods_list' ][ 'invoice_full_address' ] = $calculate_data[ 'member_address' ][ 'full_address' ] . $calculate_data[ 'member_address' ][ 'address' ];
  82. }
  83. //门店
  84. if ($calculate_data[ 'shop_goods_list' ][ 'delivery' ][ 'delivery_type' ] == 'store') {
  85. $delivery_store_info = json_decode($calculate_data[ 'shop_goods_list' ][ 'delivery_store_info' ], true);
  86. $calculate_data[ 'invoice_full_address' ] = $delivery_store_info[ 'full_address' ];
  87. $calculate_data[ 'shop_goods_list' ][ 'invoice_full_address' ] = $delivery_store_info[ 'full_address' ];
  88. }
  89. }
  90. }
  91. $pay = new Pay();
  92. $out_trade_no = $pay->createOutTradeNo($data[ 'member_id' ]);
  93. model('order')->startTrans();
  94. //循环生成多个订单
  95. try {
  96. $pay_money = 0;
  97. $order_item = $calculate_data[ 'shop_goods_list' ]; //订单数据主体
  98. $item_delivery = $order_item[ 'delivery' ] ?? [];
  99. $delivery_type = $item_delivery[ 'delivery_type' ] ?? '';
  100. $site_id = $data[ 'site_id' ];
  101. $express_type_list = ( new \app\model\express\Config() )->getExpressTypeList($site_id);
  102. $delivery_type_name = $express_type_list[ $delivery_type ] ?? '';
  103. //订单主表
  104. $order_type = $this->orderType($order_item, $calculate_data);
  105. $order_no = $this->createOrderNo($order_item[ 'site_id' ], $data[ 'member_id' ]);
  106. $data_order = [
  107. 'order_no' => $order_no,
  108. 'site_id' => $order_item[ 'site_id' ],
  109. 'site_name' => $order_item[ 'site_name' ],
  110. 'order_from' => $data[ 'order_from' ],
  111. 'order_from_name' => $data[ 'order_from_name' ],
  112. 'order_type' => $order_type[ 'order_type_id' ],
  113. 'order_type_name' => $order_type[ 'order_type_name' ],
  114. 'order_status_name' => $order_type[ 'order_status' ][ 'name' ],
  115. 'order_status_action' => json_encode($order_type[ 'order_status' ], JSON_UNESCAPED_UNICODE),
  116. 'out_trade_no' => $out_trade_no,
  117. 'member_id' => $data[ 'member_id' ],
  118. 'name' => $calculate_data[ 'member_address' ][ 'name' ] ?? '',
  119. 'mobile' => $calculate_data[ 'member_address' ][ 'mobile' ] ?? '',
  120. 'telephone' => $calculate_data[ 'member_address' ][ 'telephone' ] ?? '',
  121. 'province_id' => $calculate_data[ 'member_address' ][ 'province_id' ] ?? '',
  122. 'city_id' => $calculate_data[ 'member_address' ][ 'city_id' ] ?? '',
  123. 'district_id' => $calculate_data[ 'member_address' ][ 'district_id' ] ?? '',
  124. 'community_id' => $calculate_data[ 'member_address' ][ 'community_id' ] ?? '',
  125. 'address' => $calculate_data[ 'member_address' ][ 'address' ] ?? '',
  126. 'full_address' => $calculate_data[ 'member_address' ][ 'full_address' ] ?? '',
  127. 'longitude' => $calculate_data[ 'member_address' ][ 'longitude' ] ?? '',
  128. 'latitude' => $calculate_data[ 'member_address' ][ 'latitude' ] ?? '',
  129. 'buyer_ip' => request()->ip(),
  130. 'goods_money' => $order_item[ 'goods_money' ],
  131. 'delivery_money' => $order_item[ 'delivery_money' ],
  132. 'coupon_id' => $order_item[ 'coupon_id' ] ?? 0,
  133. 'coupon_money' => $order_item[ 'coupon_money' ] ?? 0,
  134. 'adjust_money' => $order_item[ 'adjust_money' ],
  135. 'invoice_money' => $order_item[ 'invoice_money' ],
  136. 'promotion_money' => $order_item[ 'promotion_money' ],
  137. 'order_money' => $order_item[ 'order_money' ],
  138. 'balance_money' => $order_item[ 'balance_money' ],
  139. 'point_money' => $calculate_data[ 'point_money' ],
  140. 'pay_money' => $order_item[ 'pay_money' ],
  141. 'create_time' => time(),
  142. 'is_enable_refund' => 0,
  143. 'order_name' => $order_item[ 'order_name' ],
  144. 'goods_num' => $order_item[ 'goods_num' ],
  145. 'delivery_type' => $delivery_type,
  146. 'delivery_type_name' => $delivery_type_name,
  147. 'delivery_store_id' => $order_item[ 'delivery_store_id' ] ?? 0,
  148. 'delivery_store_name' => $order_item[ 'delivery_store_name' ] ?? '',
  149. 'delivery_store_info' => $order_item[ 'delivery_store_info' ] ?? '',
  150. 'buyer_message' => $order_item[ 'buyer_message' ],
  151. 'invoice_delivery_money' => $order_item[ 'invoice_delivery_money' ] ?? 0,
  152. 'taxpayer_number' => $order_item[ 'taxpayer_number' ] ?? '',
  153. 'invoice_rate' => $order_item[ 'invoice_rate' ] ?? 0,
  154. 'invoice_content' => $order_item[ 'invoice_content' ] ?? '',
  155. 'invoice_full_address' => $order_item[ 'invoice_full_address' ] ?? '',
  156. 'is_invoice' => $order_item[ 'is_invoice' ] ?? 0,
  157. 'invoice_type' => $order_item[ 'invoice_type' ] ?? 0,
  158. 'invoice_title' => $order_item[ 'invoice_title' ] ?? '',
  159. 'is_tax_invoice' => $order_item[ 'is_tax_invoice' ] ?? '',
  160. 'invoice_email' => $order_item[ 'invoice_email' ] ?? '',
  161. 'invoice_title_type' => $order_item[ 'invoice_title_type' ] ?? 0,
  162. 'buyer_ask_delivery_time' => $order_item[ 'buyer_ask_delivery_time' ] ?? '',//定时达
  163. 'member_card_money' => $this->member_card_money,
  164. 'store_id' => $order_item[ 'store_id' ]
  165. ];
  166. $order_id = model('order')->add($data_order);
  167. if ($data[ 'jielong_id' ]) {
  168. model('promotion_jielong_order')->add([
  169. 'order_no' => $order_no,
  170. 'site_id' => $order_item[ 'site_id' ],
  171. 'site_name' => $order_item[ 'site_name' ],
  172. 'jielong_id' => $data[ 'jielong_id' ],
  173. 'order_from' => $data[ 'order_from' ],
  174. 'order_from_name' => $data[ 'order_from_name' ],
  175. 'order_type' => $order_type[ 'order_type_id' ],
  176. 'order_type_name' => $order_type[ 'order_type_name' ],
  177. 'order_status_name' => $order_type[ 'order_status' ][ 'name' ],
  178. 'order_status_action' => json_encode($order_type[ 'order_status' ], JSON_UNESCAPED_UNICODE),
  179. 'member_id' => $data[ 'member_id' ],
  180. 'name' => $calculate_data[ 'member_address' ][ 'name' ] ?? '',
  181. 'mobile' => $calculate_data[ 'member_address' ][ 'mobile' ] ?? '',
  182. 'telephone' => $calculate_data[ 'member_address' ][ 'telephone' ] ?? '',
  183. 'province_id' => $calculate_data[ 'member_address' ][ 'province_id' ] ?? '',
  184. 'city_id' => $calculate_data[ 'member_address' ][ 'city_id' ] ?? '',
  185. 'district_id' => $calculate_data[ 'member_address' ][ 'district_id' ] ?? '',
  186. 'community_id' => $calculate_data[ 'member_address' ][ 'community_id' ] ?? '',
  187. 'address' => $calculate_data[ 'member_address' ][ 'address' ] ?? '',
  188. 'full_address' => $calculate_data[ 'member_address' ][ 'full_address' ] ?? '',
  189. 'longitude' => $calculate_data[ 'member_address' ][ 'longitude' ] ?? '',
  190. 'latitude' => $calculate_data[ 'member_address' ][ 'latitude' ] ?? '',
  191. 'buyer_ip' => request()->ip(),
  192. 'buyer_ask_delivery_time' => isset($order_item[ 'buyer_ask_delivery_time' ]) ? strtotime($order_item[ 'buyer_ask_delivery_time' ]) : 0,
  193. 'buyer_message' => $order_item[ 'buyer_message' ],
  194. 'num' => $order_item[ 'goods_num' ],
  195. 'goods_money' => $order_item[ 'goods_money' ],
  196. 'delivery_money' => $order_item[ 'delivery_money' ],
  197. 'promotion_money' => $order_item[ 'promotion_money' ],
  198. 'coupon_id' => $order_item[ 'coupon_id' ] ?? 0,
  199. 'coupon_money' => $order_item[ 'coupon_money' ] ?? 0,
  200. 'order_money' => $order_item[ 'order_money' ],
  201. 'delivery_type' => $delivery_type,
  202. 'delivery_type_name' => $delivery_type_name,
  203. 'create_time' => time(),
  204. 'relate_order_id' => $order_id,
  205. ]);
  206. }
  207. $pay_money += $order_item[ 'pay_money' ];
  208. //订单项目表
  209. foreach ($order_item[ 'goods_list' ] as $k_order_goods => $order_goods) {
  210. $data_order_goods = array (
  211. 'order_id' => $order_id,
  212. 'site_id' => $order_item[ 'site_id' ],
  213. 'order_no' => $order_no,
  214. 'member_id' => $data[ 'member_id' ],
  215. 'sku_id' => $order_goods[ 'sku_id' ],
  216. 'sku_name' => $order_goods[ 'sku_name' ],
  217. 'sku_image' => $order_goods[ 'sku_image' ],
  218. 'sku_no' => $order_goods[ 'sku_no' ],
  219. 'is_virtual' => $order_goods[ 'is_virtual' ],
  220. 'goods_class' => $order_goods[ 'goods_class' ],
  221. 'goods_class_name' => $order_goods[ 'goods_class_name' ],
  222. 'price' => $order_goods[ 'price' ],
  223. 'cost_price' => $order_goods[ 'cost_price' ],
  224. 'num' => $order_goods[ 'num' ],
  225. 'goods_money' => $order_goods[ 'goods_money' ],
  226. 'cost_money' => $order_goods[ 'cost_price' ] * $order_goods[ 'num' ],
  227. 'goods_id' => $order_goods[ 'goods_id' ],
  228. 'delivery_status' => 0,
  229. 'delivery_status_name' => '未发货',
  230. 'real_goods_money' => $order_goods[ 'real_goods_money' ],
  231. 'coupon_money' => $order_goods[ 'coupon_money' ],
  232. 'promotion_money' => $order_goods[ 'promotion_money' ],
  233. 'goods_name' => $order_goods[ 'goods_name' ],
  234. 'sku_spec_format' => $order_goods[ 'sku_spec_format' ],
  235. 'use_point' => $order_goods[ 'use_point' ] ?? 0,
  236. 'point_money' => $order_goods[ 'point_money' ] ?? 0.00,
  237. 'create_time' => time(),
  238. 'store_id' => $order_item[ 'store_id' ],
  239. 'card_item_id' => isset($data[ 'member_goods_card' ]) && isset($data[ 'member_goods_card' ][ $order_goods[ 'sku_id' ] ]) ? $data[ 'member_goods_card' ][ $order_goods[ 'sku_id' ] ] : 0,
  240. 'card_promotion_money' => $order_goods[ 'card_promotion_money' ] ?? 0.00
  241. );
  242. $order_goods_id = model('order_goods')->add($data_order_goods);
  243. $calculate_data[ 'shop_goods_list' ][ 'goods_list' ][ $k_order_goods ][ 'order_goods_id' ] = $order_goods_id;
  244. // 使用次卡
  245. if ($data_order_goods[ 'card_item_id' ]) {
  246. $card_use_res = ( new \addon\cardservice\model\MemberCard() )->cardUse([
  247. 'item_id' => $data_order_goods[ 'card_item_id' ],
  248. 'num' => $order_goods[ 'card_use_num' ],
  249. 'type' => 'order',
  250. 'relation_id' => $order_goods_id,
  251. 'store_id' => $data_order_goods[ 'store_id' ]
  252. ]);
  253. if ($card_use_res[ 'code' ] != 0) {
  254. model('order')->rollback();
  255. return $card_use_res;
  256. }
  257. }
  258. }
  259. //todo 满减送
  260. if (!empty($order_item[ 'manjian_rule_list' ])) {
  261. $mansong_data = [];
  262. foreach ($order_item[ 'manjian_rule_list' ] as $item) {
  263. // 检测是否有赠送内容
  264. if (isset($item[ 'rule' ][ 'point' ]) || isset($item[ 'rule' ][ 'coupon' ])) {
  265. array_push($mansong_data, [
  266. 'manjian_id' => $item[ 'manjian_info' ][ 'manjian_id' ],
  267. 'site_id' => $order_item[ 'site_id' ],
  268. 'manjian_name' => $item[ 'manjian_info' ][ 'manjian_name' ],
  269. 'point' => isset($item[ 'rule' ][ 'point' ]) ? round($item[ 'rule' ][ 'point' ]) : 0,
  270. 'coupon' => $item[ 'rule' ][ 'coupon' ] ?? 0,
  271. 'coupon_num' => $item[ 'rule' ][ 'coupon_num' ] ?? '',
  272. 'order_id' => $order_id,
  273. 'member_id' => $data[ 'member_id' ],
  274. 'order_sku_ids' => !empty($item[ 'sku_ids' ]) ? implode($item[ 'sku_ids' ]) : '',
  275. ]);
  276. }
  277. }
  278. if (!empty($mansong_data)) {
  279. model('promotion_mansong_record')->addList($mansong_data);
  280. }
  281. }
  282. //todo 优惠券(新)
  283. //优惠券
  284. if ($data_order[ 'coupon_id' ] > 0 && $data_order[ 'coupon_money' ] > 0) {
  285. //优惠券处理方案
  286. $member_coupon_model = new Coupon();
  287. $coupon_use_result = $member_coupon_model->useCoupon($data_order[ 'coupon_id' ], $data[ 'member_id' ], $order_id); //使用优惠券
  288. if ($coupon_use_result[ 'code' ] < 0) {
  289. model('order')->rollback();
  290. return $this->error('', 'COUPON_ERROR');
  291. }
  292. }
  293. //订单生成后操作
  294. $result_list = event('OrderCreate', [ 'order_id' => $order_id, 'site_id' => $data[ 'site_id' ], 'create_data' => $calculate_data ]);
  295. if (!empty($result_list)) {
  296. foreach ($result_list as $k => $v) {
  297. if (!empty($v) && $v[ 'code' ] < 0) {
  298. model('order')->rollback();
  299. return $v;
  300. }
  301. }
  302. }
  303. $config_model = new Config();
  304. $balance_config = $config_model->getBalanceConfig($order_item[ 'site_id' ]);
  305. //扣除余额(统一扣除)
  306. if ($calculate_data[ 'balance_money' ] > 0 && $balance_config[ 'data' ][ 'value' ][ 'balance_show' ] == 1) {
  307. $calculate_data[ 'order_id' ] = $order_id;
  308. $balance_result = $this->useBalance($calculate_data, $order_item[ 'site_id' ]);
  309. if ($balance_result[ 'code' ] < 0) {
  310. model('order')->rollback();
  311. return $balance_result;
  312. }
  313. }
  314. // 扣除抵现积分
  315. if ($calculate_data[ 'is_point' ] && $calculate_data[ 'shop_goods_list' ][ 'max_usable_point' ] > 0) {
  316. $member_account_model = new MemberAccount();
  317. $point_result = $member_account_model->addMemberAccount($calculate_data[ 'site_id' ], $calculate_data[ 'member_id' ], 'point', -$calculate_data[ 'shop_goods_list' ][ 'max_usable_point' ], 'pointcash', $order_id, '订单消费扣除');
  318. if ($point_result[ 'code' ] < 0) {
  319. model('order')->rollback();
  320. return $point_result;
  321. }
  322. }
  323. // 是否同时开通会员卡
  324. if (!empty($this->recommend_member_card) && $calculate_data[ 'is_open_card' ]) {
  325. $member_level_order = new MemberLevelOrder();
  326. $level_order_result = $member_level_order->create([ 'out_trade_no' => $out_trade_no, 'member_id' => $data[ 'member_id' ], 'site_id' => $order_item[ 'site_id' ], 'level_id' => $this->recommend_member_card[ 'level_id' ], 'period_unit' => $data[ 'member_card_unit' ] ]);
  327. if ($level_order_result[ 'code' ] < 0) {
  328. model('order')->rollback();
  329. return $level_order_result;
  330. }
  331. model('order')->update([ 'member_card_order' => $level_order_result[ 'data' ][ 'order_id' ] ], [ [ 'order_id', '=', $order_id ] ]);
  332. }
  333. //记录订单日志 start
  334. $order_common_model = new OrderCommon();
  335. //获取用户信息
  336. $member_info = model('member')->getInfo([ 'member_id' => $data[ 'member_id' ] ], 'nickname');
  337. $buyer_name = !empty($member_info[ 'nickname' ]) ? '【' . $member_info[ 'nickname' ] . '】' : '';
  338. $log_data = [
  339. 'order_id' => $order_id,
  340. 'action' => '买家' . $buyer_name . '下单了',
  341. 'uid' => $data[ 'member_id' ],
  342. 'nick_name' => $member_info[ 'nickname' ],
  343. 'action_way' => 1,
  344. 'order_status' => 0,
  345. 'order_status_name' => $order_type[ 'order_status' ][ 'name' ]
  346. ];
  347. $order_common_model->addOrderLog($log_data);
  348. //记录订单日志 end
  349. //生成整体付费支付单据
  350. $pay->addPay($calculate_data[ 'site_id' ], $out_trade_no, $this->pay_type, $this->order_name, $this->order_name, $this->pay_money, '', 'OrderPayNotify', '');
  351. $this->addOrderCronClose($order_id, $data[ 'site_id' ]); //增加关闭订单自动事件
  352. Cache::tag('order_create_member_' . $data[ 'member_id' ])->clear();
  353. $cart_ids = $data[ 'cart_ids' ] ?? '';
  354. if (!empty($cart_ids)) {
  355. $cart = new Cart();
  356. $data_cart = [
  357. 'cart_id' => $cart_ids,
  358. 'member_id' => $data[ 'member_id' ]
  359. ];
  360. if (addon_is_exit('jielong')) {
  361. $jielong_cart = new \addon\jielong\model\Cart();
  362. //删除购物车
  363. if ($data[ 'jielong_id' ]) {
  364. $jielong_cart->deleteCart($data_cart);
  365. } else {
  366. $cart->deleteCart($data_cart);
  367. }
  368. } else {
  369. $cart->deleteCart($data_cart);
  370. }
  371. }
  372. //库存处理(卡密商品支付后在扣出库存)//todo 可以再商品中设置扣除库存步骤
  373. $order_stock_model = new OrderStock();
  374. foreach ($order_item[ 'goods_list' ] as $k_order_goods => $order_goods) {
  375. $item_goods_class = $order_goods[ 'goods_class' ];
  376. $stock_result = $this->skuDecStock($order_goods, $order_item[ 'store_id' ]);
  377. if ($stock_result[ 'code' ] != 0) {
  378. model('order')->rollback();
  379. return $stock_result;
  380. }
  381. //库存变化
  382. // $stock_result = $goods_stock_model->decStock(['sku_id' => $order_goods['sku_id'], 'num' => $order_goods['num']]);
  383. // if ($stock_result['code'] != 0) {
  384. // model('order')->rollback();
  385. // return $stock_result;
  386. // }
  387. }
  388. model('order')->commit();
  389. //订单生成的消息
  390. $message_model = new Message();
  391. $message_model->sendMessage([ 'keywords' => 'ORDER_CREATE', 'order_id' => $order_id, 'site_id' => $calculate_data[ 'site_id' ] ]);
  392. return $this->success($out_trade_no);
  393. } catch (\Exception $e) {
  394. model('order')->rollback();
  395. return $this->error('', $e->getMessage() . $e->getFile() . $e->getLine());
  396. }
  397. }
  398. public function verifyArea($data)
  399. {
  400. //查询出会员相关信息
  401. $calculate_data = $this->calculate($data);
  402. if (isset($calculate_data[ 'code' ]) && $calculate_data[ 'code' ] < 0)
  403. return $calculate_data;
  404. if ($this->error > 0) {
  405. return $this->error([ 'error_code' => $this->error ], $this->error_msg);
  406. }
  407. if (!empty($data[ 'delivery' ][ 'delivery_type' ]) && $data[ 'delivery' ][ 'delivery_type' ] == 'store') {
  408. //商品列表信息
  409. $shop_goods_list = $this->getOrderGoodsCalculate($data);
  410. $goods_lists = $shop_goods_list[ 'goods_list' ];
  411. $res = event('GoodsSkuStock', [ 'goodslist' => $goods_lists, 'data' => $data ]);
  412. if (!empty($res)) {
  413. return $this->error([ 'error_code' => 11 ], '当前门店库存不足,请选择其他门店');
  414. }
  415. }
  416. return $this->success(1);
  417. }
  418. /**
  419. * 生成订单编号
  420. *
  421. * @param array $site_id
  422. */
  423. public function createOrderNo($site_id, $member_id = 0)
  424. {
  425. $time_str = date('YmdHi');
  426. $max_no = Cache::get($site_id . '_' . $member_id . '_' . $time_str);
  427. if (!isset($max_no) || empty($max_no)) {
  428. $max_no = 1;
  429. } else {
  430. $max_no = $max_no + 1;
  431. }
  432. $order_no = $time_str . $member_id . sprintf('%03d', $max_no);
  433. Cache::set($site_id . '_' . $member_id . '_' . $time_str, $max_no);
  434. return $order_no;
  435. }
  436. /**
  437. * 订单类型判断
  438. * @param unknown $shop_goods
  439. */
  440. public function orderType($shop_goods, $data)
  441. {
  442. if ($data[ 'is_virtual' ] == 1) {
  443. $order = new VirtualOrder();
  444. return [
  445. 'order_type_id' => 4,
  446. 'order_type_name' => '虚拟订单',
  447. 'order_status' => $order->order_status[ 0 ]
  448. ];
  449. } else {
  450. if ($shop_goods[ 'delivery' ][ 'delivery_type' ] == 'express') {
  451. $order = new Order();
  452. return [
  453. 'order_type_id' => 1,
  454. 'order_type_name' => '普通订单',
  455. 'order_status' => $order->order_status[ 0 ]
  456. ];
  457. } elseif ($shop_goods[ 'delivery' ][ 'delivery_type' ] == 'store') {
  458. $order = new StoreOrder();
  459. return [
  460. 'order_type_id' => 2,
  461. 'order_type_name' => '自提订单',
  462. 'order_status' => $order->order_status[ 0 ]
  463. ];
  464. } elseif ($shop_goods[ 'delivery' ][ 'delivery_type' ] == 'local') {
  465. $order = new LocalOrder();
  466. return [
  467. 'order_type_id' => 3,
  468. 'order_type_name' => '外卖订单',
  469. 'order_status' => $order->order_status[ 0 ]
  470. ];
  471. }
  472. }
  473. }
  474. /**
  475. * 订单计算
  476. * @param unknown $data
  477. */
  478. public function calculate($data)
  479. {
  480. $data = $this->initMemberAddress($data); //初始化地址
  481. $data = $this->initMemberAccount($data); //初始化会员账户
  482. $data = $this->initStore($data);//初始化门店信息
  483. //余额付款
  484. if ($data[ 'is_balance' ] > 0) {
  485. $this->member_balance_money = $data[ 'member_account' ][ 'balance_total' ] ?? 0;
  486. }
  487. //传输购物车id组合','隔开要进行拆单
  488. // if (!empty($data[ 'cart_ids' ])) {
  489. //商品列表信息
  490. $shop_goods_list = $this->getOrderGoodsCalculate($data);
  491. if ($shop_goods_list[ 'goods_list' ][ 0 ][ 'is_virtual' ]) {
  492. $this->is_virtual = 1;
  493. } else {
  494. $this->is_virtual = 0;
  495. }
  496. $data[ 'shop_goods_list' ] = $this->shopOrderCalculate($shop_goods_list, $data);
  497. $payment_event_data = event('OrderPayment', $data);
  498. if (!empty($payment_event_data)) {
  499. $data = array_merge($data, ...$payment_event_data);
  500. }
  501. // } else {
  502. // //商品列表信息
  503. // $shop_goods_list = $this->getOrderGoodsCalculate($data);
  504. // //判断是否是虚拟订单
  505. // if ($shop_goods_list[ 'goods_list' ][ 0 ][ 'is_virtual' ]) {
  506. // $this->is_virtual = 1;
  507. // } else {
  508. // $this->is_virtual = 0;
  509. // }
  510. // $data[ 'shop_goods_list' ] = $this->shopOrderCalculate($shop_goods_list, $data);
  511. // }
  512. //todo 统一检测库存(创建订单操作时扣除库存同理)
  513. // 商品限购判断
  514. foreach ($shop_goods_list[ 'limit_purchase' ] as $item) {
  515. if ($item[ 'min_buy' ] > 0 && $item[ 'num' ] < $item[ 'min_buy' ]) {
  516. $this->setError(1, "商品“{$item['goods_name']}”{$item['min_buy']}件起售");
  517. break;
  518. }
  519. if ($item[ 'is_limit' ] == 1 && $item[ 'max_buy' ] > 0) { // 商品做限制购买
  520. if ($item[ 'limit_type' ] == 1) { // 单次限制
  521. if ($item[ 'num' ] > $item[ 'max_buy' ]) {
  522. $this->setError(1, "商品“{$item['goods_name']}”每人限购{$item['max_buy']}件");
  523. break;
  524. }
  525. } else { // 长期限制
  526. $goods_model = new Goods();
  527. $purchased_num = $goods_model->getGoodsPurchasedNum($item[ 'goods_id' ], $data[ 'member_id' ]);
  528. if (( $purchased_num + $item[ 'num' ] ) > $item[ 'max_buy' ]) {
  529. $this->setError(1, "商品“{$item['goods_name']}”每人限购{$item['max_buy']}件,您已购买{$purchased_num}件");
  530. break;
  531. }
  532. }
  533. }
  534. }
  535. $coupon_list = $this->getOrderCouponList($data);
  536. $data[ 'shop_goods_list' ][ 'coupon_list' ] = $coupon_list;
  537. //总结计算
  538. $data[ 'delivery_money' ] = $this->delivery_money;
  539. $data[ 'coupon_money' ] = $this->coupon_money;
  540. $data[ 'adjust_money' ] = $this->adjust_money;
  541. $data[ 'invoice_money' ] = $this->invoice_money;
  542. $data[ 'invoice_delivery_money' ] = $this->invoice_delivery_money;
  543. $data[ 'promotion_money' ] = $this->promotion_money;
  544. $data[ 'order_money' ] = $this->order_money;
  545. $data[ 'balance_money' ] = $this->balance_money;
  546. $data[ 'pay_money' ] = $this->pay_money;
  547. $data[ 'goods_money' ] = $this->goods_money;
  548. $data[ 'goods_num' ] = $this->goods_num;
  549. $data[ 'is_virtual' ] = $this->is_virtual;
  550. $data[ 'point_money' ] = $this->point_money;
  551. $data[ 'member_card_money' ] = $this->member_card_money;
  552. $data[ 'recommend_member_card' ] = $this->recommend_member_card;
  553. if ($this->error_show) {
  554. $data[ 'error_msg' ] = $this->error_msg;
  555. }
  556. return $data;
  557. }
  558. /**
  559. * 待付款订单
  560. * @param unknown $data
  561. */
  562. public function orderPayment($data)
  563. {
  564. $site_id = $data[ 'site_id' ];
  565. $calculate_data = $this->calculate($data);
  566. $express_type = [];
  567. if ($this->is_virtual == 0) {
  568. $trade_result = event('OrderCreateCommonData', [ 'type' => 'trade', 'data' => $calculate_data ], true);
  569. if (!empty($trade_result)) {
  570. if ($trade_result[ 'code' ] >= 0) {
  571. $express_type = $trade_result[ 'data' ];
  572. }
  573. } else {
  574. $shop_goods_list = $calculate_data[ 'shop_goods_list' ];
  575. foreach ($shop_goods_list[ 'deliver_sort' ] as $type) {
  576. // 物流
  577. if ($type == 'express') {
  578. if ($shop_goods_list[ 'express_config' ][ 'is_use' ] == 1) {
  579. $title = $shop_goods_list[ 'express_config' ][ 'value' ][ 'express_name' ];
  580. if ($title == '') {
  581. $title = Express::express_type[ 'express' ][ 'title' ];
  582. }
  583. $express_type[] = [ 'title' => $title, 'name' => 'express' ];
  584. }
  585. }
  586. // 自提
  587. if ($type == 'store') {
  588. if ($shop_goods_list[ 'store_config' ][ 'is_use' ] == 1) {
  589. //根据坐标查询门店
  590. $store_model = new Store();
  591. $store_condition = array (
  592. [ 'site_id', '=', $site_id ],
  593. [ 'is_pickup', '=', 1 ],
  594. [ 'status', '=', 1 ],
  595. [ 'is_frozen', '=', 0 ],
  596. );
  597. $latlng = array (
  598. 'lat' => $data[ 'latitude' ],
  599. 'lng' => $data[ 'longitude' ],
  600. );
  601. $store_list_result = $store_model->getLocationStoreList($store_condition, '*', $latlng);
  602. $store_list = $store_list_result[ 'data' ];
  603. $title = $shop_goods_list[ 'store_config' ][ 'value' ][ 'store_name' ];
  604. if ($title == '') {
  605. $title = Express::express_type[ 'store' ][ 'title' ];
  606. }
  607. $express_type[] = [ 'title' => $title, 'name' => 'store', 'store_list' => $store_list ];
  608. }
  609. }
  610. // 外卖
  611. if ($type == 'local') {
  612. if ($shop_goods_list[ 'local_config' ][ 'is_use' ] == 1) {
  613. //查询本店的通讯地址
  614. $title = $shop_goods_list[ 'local_config' ][ 'value' ][ 'local_name' ];
  615. if ($title == '') {
  616. $title = '外卖配送';
  617. }
  618. $store_model = new Store();
  619. $store_condition = array (
  620. [ 'site_id', '=', $site_id ],
  621. );
  622. if (addon_is_exit('store', $site_id)) {
  623. $store_condition[] = [ 'is_o2o', '=', 1 ];
  624. $store_condition[] = [ 'status', '=', 1 ];
  625. $store_condition[] = [ 'is_frozen', '=', 0 ];
  626. } else {
  627. $store_condition[] = [ 'is_default', '=', 1 ];
  628. }
  629. $latlng = array (
  630. 'lat' => $data[ 'latitude' ],
  631. 'lng' => $data[ 'longitude' ],
  632. );
  633. $store_list_result = $store_model->getLocationStoreList($store_condition, '*', $latlng);
  634. $store_list = $store_list_result[ 'data' ];
  635. $express_type[] = [ 'title' => $title, 'name' => 'local', 'store_list' => $store_list ];
  636. }
  637. }
  638. }
  639. }
  640. }
  641. $calculate_data[ 'shop_goods_list' ][ 'express_type' ] = $express_type;
  642. $payment_event_data = event('OrderPayment', $calculate_data);
  643. if (!empty($payment_event_data)) {
  644. $calculate_data = array_merge($calculate_data, ...$payment_event_data);
  645. }
  646. return $calculate_data;
  647. }
  648. public function expressPayment()
  649. {
  650. }
  651. /**
  652. * 初始化收货地址
  653. * @param $data
  654. * @return mixed
  655. */
  656. public function initMemberAddress($data)
  657. {
  658. $delivery_type = $data[ 'delivery' ][ 'delivery_type' ] ?? '';
  659. if (empty($data[ 'member_address' ])) {
  660. $member_address = new MemberAddress();
  661. $type = 1;
  662. if ($delivery_type == 'local') {
  663. $type = 2;
  664. }
  665. $address = $member_address->getMemberAddressInfo([ [ 'member_id', '=', $data[ 'member_id' ] ], [ 'is_default', '=', 1 ], [ 'type', '=', $type ] ]);
  666. $data[ 'member_address' ] = $address[ 'data' ];
  667. }
  668. if (!empty($data[ 'member_address' ])) {
  669. if ($delivery_type == 'local') {
  670. //外卖订单 如果收货地址没有定位的话,就不取用地址
  671. $type = $data[ 'member_address' ][ 'type' ] ?? 1;
  672. if ($type == 1) {
  673. $data[ 'member_address' ] = '';
  674. }
  675. }
  676. }
  677. return $data;
  678. }
  679. /**
  680. * 获取商品的计算信息
  681. * @param unknown $data
  682. */
  683. public function getOrderGoodsCalculate($data)
  684. {
  685. $shop_goods = $this->getCartGoodsList($data);
  686. $shop_goods[ 'promotion_money' ] = 0;
  687. $shop_goods_list = $shop_goods;
  688. // 会员卡项抵扣
  689. $shop_goods_list = $this->memberGoodsCardPromotion($shop_goods_list, $data);
  690. //满减优惠
  691. $shop_goods_list = $this->manjianPromotion($shop_goods_list);
  692. return $shop_goods_list;
  693. }
  694. /**
  695. * 获取购物车商品列表信息
  696. * @param unknown $cart_ids
  697. */
  698. public function getCartGoodsList($data)
  699. {
  700. $site_id = $data[ 'site_id' ];
  701. $cart_ids = $data[ 'cart_ids' ] ?? [];
  702. $member_id = $data[ 'member_id' ];
  703. $condition = array (
  704. [ 'ngs.site_id', '=', $site_id ],
  705. [ 'ngs.is_delete', '=', 0 ]
  706. //todo 订单上下架状态
  707. );
  708. $goods_model = new Goods();
  709. //组装商品列表
  710. $field = 'ngs.sku_id,ngs.is_limit, ngs.limit_type, ngs.sku_name, ngs.sku_no,
  711. ngs.price, ngs.discount_price, ngs.cost_price, ngs.stock, ngs.weight, ngs.volume, ngs.sku_image,
  712. ngs.site_id, ngs.goods_state, ngs.is_virtual,
  713. ngs.is_free_shipping, ngs.shipping_template, ngs.goods_class, ngs.goods_class_name, ngs.goods_id,ns.site_name,ngs.sku_spec_format,ngs.goods_name,ngs.max_buy,ngs.min_buy,ngs.support_trade_type, ngs.is_unify_price';
  714. $alias = 'ngs';
  715. $join = [
  716. // [
  717. // 'goods_sku ngs',
  718. // 'ngc.sku_id = ngs.sku_id',
  719. // 'inner'
  720. // ],
  721. [
  722. 'site ns',
  723. 'ngs.site_id = ns.site_id',
  724. 'inner'
  725. ]
  726. ];
  727. $jielong_id = $data[ 'jielong_id' ] ?? 0;
  728. if (!empty($cart_ids)) {
  729. $field .= ',ngc.member_id, ngc.sku_id, ngc.num';
  730. if ($jielong_id > 0) {
  731. $join[] = [
  732. 'promotion_jielong_cart ngc',
  733. 'ngc.sku_id = ngs.sku_id',
  734. 'inner'
  735. ];
  736. } else {
  737. $field .= ',ngc.form_data';
  738. $join[] = [
  739. 'goods_cart ngc',
  740. 'ngc.sku_id = ngs.sku_id',
  741. 'inner'
  742. ];
  743. }
  744. $condition[] = [ 'ngc.cart_id', 'in', $cart_ids ];
  745. $condition[] = [ 'ngc.member_id', '=', $member_id ];
  746. } else {
  747. $sku_id = $data[ 'sku_id' ];
  748. $num = $data[ 'num' ];
  749. $field .= ',' . $num . ' as num';
  750. $condition[] = [
  751. 'ngs.sku_id', '=', $sku_id
  752. ];
  753. }
  754. //只有存在收银插件的情况下才会进行吧此项业务(todo 钩子实现)
  755. $store_id = $data[ 'store_id' ] ?? 0;
  756. // if (addon_is_exit('cashier')){
  757. //
  758. // if($store_id > 0){
  759. // $join[] = [
  760. // 'store_goods_sku sgs',
  761. // 'sgs.sku_id = ngs.sku_id',
  762. // 'inner'
  763. // ];
  764. // $field .= ',sgs.stock,sgs.price';//门店库存权重高
  765. // $condition[] = ['sgs.status', '=', 1];//上架
  766. // $condition[] = ['sgs.store_id', '=', $store_id];
  767. // }
  768. // }
  769. $delivery_array = $data[ 'delivery' ] ?? [];
  770. $goods_list = model('goods_sku')->getList($condition, $field, '', $alias, $join);
  771. $shop_goods_list = [];
  772. if (!empty($goods_list)) {
  773. $express_type_list = ( new \app\model\express\Config() )->getExpressTypeList($data[ 'site_id' ]);
  774. foreach ($goods_list as $k => $v) {
  775. if ($v[ 'num' ] < 1) {
  776. $this->setError(1, '商品项的购买数量不能小于1');
  777. }
  778. // if ($v[ 'site_id' ] != $site_id) {
  779. // return $this->error([], '不存在的商品!');
  780. // }
  781. $goods_item = $v;
  782. $goods_item[ 'delivery' ] = $delivery_array;
  783. $goods_item[ 'store_id' ] = $store_id;
  784. //整理创建订单时商品的相关价格库存, 有错误的话还回记录错误['error' => [''error_code' => 1, 'message' => '']]
  785. $goods_calculate = event('OrderGoodsCalculate', $goods_item, true);
  786. if (!empty($goods_calculate)) {
  787. if ($goods_calculate[ 'code' ] < 0) {
  788. return $goods_calculate;
  789. }
  790. $v = $goods_calculate[ 'data' ];
  791. }
  792. //todo 要核验 当前门店 当前产品是否已经配置上架
  793. //todo 未上架未配置 要记录原因,并且不能生成订单
  794. $price = $this->getGoodsPrice($v, $data)[ 'data' ] ?? 0;
  795. // $price_result = $goods_model->getGoodsPrice($v[ 'sku_id' ], $member_id);
  796. // $price_info = $price_result[ 'data' ];
  797. // $price = $price_info[ 'price' ];
  798. // 是否存在推荐会员卡
  799. if (!empty($this->recommend_member_card)) {
  800. //todo 当前业务门店不存在,所以这儿的价格不作处理
  801. $card_price_result = $goods_model->getMemberCardGoodsPrice($v[ 'sku_id' ], $this->recommend_member_card[ 'level_id' ]);
  802. $card_price_info = $card_price_result[ 'data' ];
  803. $card_price = $card_price_info[ 'price' ];
  804. if ($card_price > 0 && $card_price < $price) {
  805. $this->recommend_member_card[ 'discount_money' ] += ( $price - $card_price ) * $v[ 'num' ];
  806. if ($data[ 'is_open_card' ]) $price = $card_price;//todo 这儿应该把discount_price 也同步一下的
  807. }
  808. }
  809. $v[ 'form_data' ] = !empty($v[ 'form_data' ]) ? json_decode($v[ 'form_data' ], true) : '';
  810. $v[ 'price' ] = $price;
  811. //实现要注意 discount_price 字段只存在显示作用
  812. if ($store_id > 0) {
  813. $v[ 'discount_price' ] = $price;
  814. }
  815. $v[ 'goods_money' ] = $price * $v[ 'num' ];
  816. $v[ 'real_goods_money' ] = $v[ 'goods_money' ];
  817. $v[ 'coupon_money' ] = 0; //优惠券金额
  818. $v[ 'promotion_money' ] = 0; //优惠金额
  819. if (!empty($shop_goods_list)) {
  820. $shop_goods_list[ 'goods_list' ][] = $v;
  821. $shop_goods_list[ 'order_name' ] = string_split($shop_goods_list[ 'order_name' ], ',', $v[ 'sku_name' ]);
  822. $shop_goods_list[ 'goods_num' ] += $v[ 'num' ];
  823. $shop_goods_list[ 'goods_money' ] += $v[ 'goods_money' ];
  824. $shop_goods_list[ 'goods_list_str' ] = $shop_goods_list[ 'goods_list_str' ] . ';' . $v[ 'sku_id' ] . ':' . $v[ 'num' ];
  825. // 商品限购处理
  826. if (isset($shop_goods_list[ 'limit_purchase' ][ 'goods_' . $v[ 'goods_id' ] ])) {
  827. $shop_goods_list[ 'limit_purchase' ][ 'goods_' . $v[ 'goods_id' ] ][ 'num' ] += $v[ 'num' ];
  828. } else {
  829. $shop_goods_list[ 'limit_purchase' ][ 'goods_' . $v[ 'goods_id' ] ] = [
  830. 'goods_id' => $v[ 'goods_id' ],
  831. 'goods_name' => $v[ 'sku_name' ],
  832. 'num' => $v[ 'num' ],
  833. 'is_limit' => $v[ 'is_limit' ],
  834. 'limit_type' => $v[ 'limit_type' ],
  835. 'max_buy' => $v[ 'max_buy' ],
  836. 'min_buy' => $v[ 'min_buy' ]
  837. ];
  838. }
  839. } else {
  840. $shop_goods_list[ 'site_id' ] = $site_id;
  841. $shop_goods_list[ 'site_name' ] = $v[ 'site_name' ];
  842. $shop_goods_list[ 'goods_money' ] = $v[ 'goods_money' ];
  843. $shop_goods_list[ 'goods_list_str' ] = $v[ 'sku_id' ] . ':' . $v[ 'num' ];
  844. $shop_goods_list[ 'order_name' ] = string_split('', ',', $v[ 'sku_name' ]);
  845. $shop_goods_list[ 'goods_num' ] = $v[ 'num' ];
  846. $shop_goods_list[ 'goods_list' ][] = $v;
  847. // 商品限购处理
  848. $shop_goods_list[ 'limit_purchase' ][ 'goods_' . $v[ 'goods_id' ] ] = [
  849. 'goods_id' => $v[ 'goods_id' ],
  850. 'goods_name' => $v[ 'sku_name' ],
  851. 'num' => $v[ 'num' ],
  852. 'is_limit' => $v[ 'is_limit' ],
  853. 'limit_type' => $v[ 'limit_type' ],
  854. 'max_buy' => $v[ 'max_buy' ],
  855. 'min_buy' => $v[ 'min_buy' ]
  856. ];
  857. }
  858. if (isset($data[ 'delivery' ][ 'delivery_type' ]) && !empty($data[ 'delivery' ][ 'delivery_type' ]) && strpos($v[ 'support_trade_type' ], $data[ 'delivery' ][ 'delivery_type' ]) === false) {
  859. $delivery_type_name = $express_type_list[ $data[ 'delivery' ][ 'delivery_type' ] ] ?? '';
  860. $this->setError(1, '有商品不支持' . $delivery_type_name);
  861. }
  862. //有错误也会导致商品无法购买
  863. $item_error = $v[ 'error' ] ?? [];
  864. if (!empty($item_error)) {
  865. $this->setError(1, $item_error[ 'message' ]);
  866. }
  867. }
  868. }
  869. return $shop_goods_list;
  870. }
  871. /**
  872. * 获取立即购买商品信息
  873. * @param unknown $data
  874. * @return multitype:string number unknown mixed
  875. */
  876. public function getShopGoodsList($data)
  877. {
  878. $join = [
  879. [
  880. 'site ns',
  881. 'ngs.site_id = ns.site_id',
  882. 'inner'
  883. ]
  884. ];
  885. $field = 'sku_id, sku_name, sku_no, price, discount_price,cost_price, stock, volume, weight, sku_image, ngs.site_id, goods_state, is_virtual, is_free_shipping, shipping_template,goods_class, goods_class_name, goods_id, ns.site_name,sku_spec_format,goods_name,max_buy,min_buy,is_limit,limit_type,support_trade_type';
  886. $sku_info = model('goods_sku')->getInfo([ [ 'sku_id', '=', $data[ 'sku_id' ] ], [ 'ngs.site_id', '=', $data[ 'site_id' ] ] ], $field, 'ngs', $join);
  887. if (empty($sku_info)) {
  888. return $this->error([], '不存在的商品!');
  889. }
  890. $goods_model = new Goods();
  891. $price_result = $goods_model->getGoodsPrice($data[ 'sku_id' ], $data[ 'member_id' ]);
  892. $price_info = $price_result[ 'data' ];
  893. $price = $price_info[ 'price' ];
  894. // 是否存在推荐会员卡
  895. if (!empty($this->recommend_member_card)) {
  896. $card_price_result = $goods_model->getMemberCardGoodsPrice($data[ 'sku_id' ], $this->recommend_member_card[ 'level_id' ]);
  897. $card_price_info = $card_price_result[ 'data' ];
  898. $card_price = $card_price_info[ 'price' ];
  899. if ($card_price > 0 && $card_price < $price) {
  900. $this->recommend_member_card[ 'discount_money' ] = ( $price - $card_price ) * $data[ 'num' ];
  901. if ($data[ 'is_open_card' ]) $price = $card_price;
  902. }
  903. }
  904. $sku_info[ 'num' ] = $data[ 'num' ];
  905. $goods_money = $price * $data[ 'num' ];
  906. $sku_info[ 'price' ] = $price;
  907. $sku_info[ 'goods_money' ] = $goods_money;
  908. $sku_info[ 'real_goods_money' ] = $goods_money;
  909. $sku_info[ 'coupon_money' ] = 0; //优惠券金额
  910. $sku_info[ 'promotion_money' ] = 0; //优惠金额
  911. $sku_info[ 'stock' ] = numberFormat($sku_info[ 'stock' ]);
  912. $goods_list[] = $sku_info;
  913. $shop_goods = [
  914. 'goods_money' => $goods_money,
  915. 'site_id' => $sku_info[ 'site_id' ],
  916. 'site_name' => $sku_info[ 'site_name' ],
  917. 'goods_list_str' => $sku_info[ 'sku_id' ] . ':' . $sku_info[ 'num' ],
  918. 'goods_list' => $goods_list,
  919. 'order_name' => $sku_info[ 'sku_name' ],
  920. 'goods_num' => $sku_info[ 'num' ],
  921. 'limit_purchase' => [
  922. 'goods_' . $sku_info[ 'goods_id' ] => [
  923. 'goods_id' => $sku_info[ 'goods_id' ],
  924. 'goods_name' => $sku_info[ 'sku_name' ],
  925. 'is_limit' => $sku_info[ 'is_limit' ],
  926. 'limit_type' => $sku_info[ 'limit_type' ],
  927. 'num' => $sku_info[ 'num' ],
  928. 'max_buy' => $sku_info[ 'max_buy' ],
  929. 'min_buy' => $sku_info[ 'min_buy' ]
  930. ]
  931. ]
  932. ];
  933. if (isset($data[ 'delivery' ][ 'delivery_type' ]) && !empty($data[ 'delivery' ][ 'delivery_type' ]) && strpos($sku_info[ 'support_trade_type' ], $data[ 'delivery' ][ 'delivery_type' ]) === false) {
  934. $express_type_list = ( new \app\model\express\Config() )->getExpressTypeList($data[ 'site_id' ]);
  935. $delivery_type_name = $express_type_list[ $data[ 'delivery' ][ 'delivery_type' ] ] ?? '';
  936. $this->setError(1, '有商品不支持' . $delivery_type_name);
  937. }
  938. return $shop_goods;
  939. }
  940. /**
  941. * 获取店铺订单计算
  942. * @param unknown $site_id 店铺id
  943. * @param unknown $goods_money 商品总价
  944. * @param unknown $goods_list 店铺商品列表
  945. * @param unknown $data 传输生成订单数据
  946. */
  947. public function shopOrderCalculate($shop_goods, $data)
  948. {
  949. $site_id = $data[ 'site_id' ];
  950. //交易配置
  951. $config_model = new Config();
  952. $order_config_result = $config_model->getOrderEventTimeConfig($site_id);
  953. $order_config = $order_config_result[ 'data' ];
  954. $shop_goods[ 'order_config' ] = $order_config[ 'value' ] ?? [];
  955. //定义计算金额
  956. $goods_money = $shop_goods[ 'goods_money' ]; //商品金额
  957. $delivery_money = 0; //配送费用
  958. $promotion_money = $shop_goods[ 'promotion_money' ]; //优惠费用(满减)
  959. $coupon_money = 0; //优惠券费用
  960. $adjust_money = 0; //调整金额
  961. $invoice_money = 0; //发票金额
  962. $order_money = 0; //订单金额
  963. $balance_money = 0; //会员余额
  964. $pay_money = 0; //应付金额
  965. $store_id = $data[ 'store_id' ];
  966. //计算邮费
  967. if ($this->is_virtual == 1) {
  968. //虚拟订单 运费为0
  969. $delivery_money = 0;
  970. $shop_goods[ 'delivery' ][ 'delivery_type' ] = '';
  971. } else {
  972. $express_config_model = new ExpressConfig();
  973. $deliver_type = $express_config_model->getDeliverTypeSort($site_id)[ 'data' ];
  974. $shop_goods[ 'deliver_sort' ] = explode(',', $deliver_type[ 'value' ][ 'deliver_type' ]);
  975. //查询店铺是否开启快递配送
  976. $express_config_result = $express_config_model->getExpressConfig($site_id);
  977. $express_config = $express_config_result[ 'data' ];
  978. $shop_goods[ 'express_config' ] = $express_config;
  979. //查询店铺是否开启门店自提
  980. $store_config_result = $express_config_model->getStoreConfig($site_id);
  981. $store_config = $store_config_result[ 'data' ];
  982. $shop_goods[ 'store_config' ] = $store_config;
  983. //查询店铺是否开启外卖配送
  984. $local_config_result = $express_config_model->getLocalDeliveryConfig($site_id);
  985. $local_config = $local_config_result[ 'data' ];
  986. $shop_goods[ 'local_config' ] = $local_config;
  987. $trade_calc_result = event('OrderCreateCommonData', [ 'type' => 'trade_calc', 'shop_goods' => $shop_goods, 'data' => $data ], true);
  988. if (!empty($trade_calc_result)) {
  989. $trade_calc = $trade_calc_result[ 'data' ];
  990. $shop_goods = $trade_calc[ 'shop_goods' ];
  991. $delivery_money = $trade_calc[ 'delivery_money' ];
  992. $trade_calc_error = $trade_calc[ 'error' ];
  993. if (!empty($trade_calc_error)) {
  994. $this->setError($trade_calc_error[ 'error' ] ?? 1, $trade_calc_error[ 'error_msg' ] ?? '', $trade_calc_error[ 'priority' ] ?? 0);
  995. }
  996. } else {
  997. //如果本地配送开启, 则查询出本地配送的配置
  998. if ($shop_goods[ 'local_config' ][ 'is_use' ] == 1 && isset($data[ 'delivery' ][ 'store_id' ])) {
  999. $local_model = new Local();
  1000. $local_info_result = $local_model->getLocalInfo([ [ 'site_id', '=', $site_id ], [ 'store_id', '=', $data[ 'delivery' ][ 'store_id' ] ] ]);
  1001. $local_info = $local_info_result[ 'data' ];
  1002. $shop_goods[ 'local_config' ][ 'info' ] = $local_info;
  1003. } else {
  1004. $shop_goods[ 'local_config' ][ 'info' ] = [];
  1005. }
  1006. $delivery_array = $data[ 'delivery' ] ?? [];
  1007. $delivery_type = $delivery_array[ 'delivery_type' ] ?? 'express';
  1008. if ($delivery_type == 'store') {
  1009. if (isset($data[ 'delivery' ][ 'delivery_type' ]) && $data[ 'delivery' ][ 'delivery_type' ] == 'store') {
  1010. //门店自提
  1011. $delivery_money = 0;
  1012. $shop_goods[ 'delivery' ][ 'delivery_type' ] = 'store';
  1013. if ($shop_goods[ 'store_config' ][ 'is_use' ] == 0) {
  1014. $this->setError(1, '门店自提方式未开启!');
  1015. }
  1016. if (empty($data[ 'delivery' ][ 'store_id' ])) {
  1017. $this->setError(1, '门店未选择!');
  1018. }
  1019. $shop_goods[ 'delivery' ][ 'store_id' ] = $data[ 'delivery' ][ 'store_id' ];
  1020. $shop_goods[ 'buyer_ask_delivery_time' ] = $data[ 'buyer_ask_delivery_time' ];
  1021. $shop_goods = $this->storeOrderData($shop_goods, $data);
  1022. $store_id = $data[ 'delivery' ][ 'store_id' ] ?? 0;
  1023. }
  1024. } else {
  1025. if (empty($data[ 'member_address' ])) {
  1026. $delivery_money = 0;
  1027. $shop_goods[ 'delivery' ][ 'delivery_type' ] = 'express';
  1028. $this->setError(1, '未配置默认收货地址!');
  1029. } else {
  1030. if (!isset($data[ 'delivery' ][ 'delivery_type' ]) || $data[ 'delivery' ][ 'delivery_type' ] == 'express') {
  1031. if ($shop_goods[ 'express_config' ][ 'is_use' ] == 1) {
  1032. //物流配送
  1033. $express = new Express();
  1034. $express_fee_result = $express->calculate($shop_goods, $data);
  1035. if ($express_fee_result[ 'code' ] < 0) {
  1036. $this->setError(1, $express_fee_result[ 'message' ]);
  1037. $delivery_fee = 0;
  1038. } else {
  1039. $delivery_fee = $express_fee_result[ 'data' ][ 'delivery_fee' ];
  1040. }
  1041. } else {
  1042. $this->setError(1, '物流配送方式未开启!');
  1043. $delivery_fee = 0;
  1044. }
  1045. $delivery_money = $delivery_fee;
  1046. $shop_goods[ 'delivery' ][ 'delivery_type' ] = 'express';
  1047. } else if ($data[ 'delivery' ][ 'delivery_type' ] == 'local') {
  1048. //外卖配送
  1049. $delivery_money = 0;
  1050. $shop_goods[ 'delivery' ][ 'delivery_type' ] = 'local';
  1051. if ($shop_goods[ 'local_config' ][ 'is_use' ] == 0) {
  1052. $this->setError(1, '外卖配送方式未开启!');
  1053. } else {
  1054. if (empty($data[ 'delivery' ][ 'store_id' ])) {
  1055. $this->setError(1, '门店未选择!');
  1056. }
  1057. $local_delivery_time = 0;
  1058. if (!empty($data[ 'buyer_ask_delivery_time' ])) {
  1059. $local_delivery_time = $data[ 'buyer_ask_delivery_time' ];
  1060. }
  1061. $shop_goods[ 'buyer_ask_delivery_time' ] = $local_delivery_time;
  1062. $local_model = new Local();
  1063. $local_result = $local_model->calculate($shop_goods, $data);
  1064. $shop_goods[ 'delivery' ][ 'start_money' ] = 0;
  1065. if ($local_result[ 'code' ] < 0) {
  1066. $shop_goods[ 'delivery' ][ 'start_money' ] = $local_result[ 'data' ][ 'start_money_array' ][ 0 ] ?? 0;
  1067. $this->setError($local_result[ 'data' ][ 'code' ], $local_result[ 'message' ], 1);
  1068. } else {
  1069. $delivery_money = $local_result[ 'data' ][ 'delivery_money' ];
  1070. if (!empty($local_result[ 'data' ][ 'error_code' ])) {
  1071. $this->setError($local_result[ 'data' ][ 'code' ], $local_result[ 'data' ][ 'error' ], 1);
  1072. }
  1073. }
  1074. $shop_goods[ 'delivery' ][ 'error' ] = $this->error;
  1075. $shop_goods[ 'delivery' ][ 'error_msg' ] = $this->error_msg;
  1076. $store_id = $data[ 'delivery' ][ 'store_id' ] ?? 0;
  1077. }
  1078. }
  1079. }
  1080. }
  1081. }
  1082. }
  1083. //满额包邮插件
  1084. $shop_goods = $this->freeShippingCalculate($shop_goods, $data);
  1085. //会员等级包邮权益
  1086. $shop_goods = $this->memberLevelCalculate($shop_goods, $data);
  1087. //是否符合免邮
  1088. $is_free_delivery = $shop_goods[ 'is_free_delivery' ] ?? false;
  1089. if ($is_free_delivery) {
  1090. $delivery_money = 0;
  1091. }
  1092. $shop_goods[ 'delivery_money' ] = $delivery_money;
  1093. $order_money = $shop_goods[ 'goods_money' ] + $delivery_money - $promotion_money;
  1094. $shop_goods[ 'order_money' ] = $order_money; //订单总金额
  1095. //优惠券活动(采用站点id:coupon_id)
  1096. $shop_goods = $this->couponPromotion($shop_goods, $data);
  1097. $coupon_money = $shop_goods[ 'coupon_money' ] ?? 0;
  1098. $order_money = $shop_goods[ 'order_money' ];
  1099. // 积分抵现
  1100. $shop_goods[ 'max_usable_point' ] = 0;
  1101. $point_money = 0;
  1102. if ($data[ 'member_account' ][ 'point' ] > 0 && addon_is_exit('pointcash', $site_id)) {
  1103. $shop_goods = $this->getMaxUsablePoint($shop_goods, $data);
  1104. $point_money = $shop_goods[ 'point_money' ] ?? 0;
  1105. $order_money = $shop_goods[ 'order_money' ];
  1106. }
  1107. //发票相关
  1108. $shop_goods = $this->invoice($shop_goods, $data);
  1109. // 会员卡开卡金额
  1110. $member_card_money = $this->calculateMemberCardMoney($data);
  1111. $order_money = $order_money + $shop_goods[ 'invoice_money' ] + $shop_goods[ 'invoice_delivery_money' ] + $member_card_money;
  1112. //理论上是多余的操作
  1113. if ($order_money < 0) {
  1114. $order_money = 0;
  1115. }
  1116. //余额抵扣(判断是否使用余额)
  1117. if ($this->member_balance_money > 0) {
  1118. $temp_order_money = $order_money;
  1119. if ($temp_order_money <= $this->member_balance_money) {
  1120. $balance_money = $temp_order_money;
  1121. } else {
  1122. $balance_money = $this->member_balance_money;
  1123. }
  1124. } else {
  1125. $balance_money = 0;
  1126. }
  1127. $pay_money = $order_money - $balance_money; //计算出实际支付金额
  1128. //判断是否存在支付金额为0的订单
  1129. $this->member_balance_money -= $balance_money; //预减少账户余额
  1130. $this->balance_money += $balance_money; //累计余额
  1131. //总结计算
  1132. $shop_goods[ 'store_id' ] = $store_id;
  1133. $shop_goods[ 'goods_money' ] = $goods_money;
  1134. $shop_goods[ 'delivery_money' ] = $delivery_money;
  1135. $shop_goods[ 'adjust_money' ] = $adjust_money;
  1136. // $shop_goods['invoice_money'] = $invoice_money;
  1137. $shop_goods[ 'promotion_money' ] = $promotion_money;
  1138. $shop_goods[ 'order_money' ] = $order_money;
  1139. $shop_goods[ 'balance_money' ] = $balance_money;
  1140. $shop_goods[ 'pay_money' ] = $pay_money;
  1141. $this->goods_money += $goods_money;
  1142. $this->delivery_money += $delivery_money;
  1143. $this->coupon_money += $coupon_money;
  1144. $this->adjust_money += $adjust_money;
  1145. $this->invoice_money += $shop_goods[ 'invoice_money' ];
  1146. $this->invoice_delivery_money += $shop_goods[ 'invoice_delivery_money' ];
  1147. $this->promotion_money += $promotion_money;
  1148. $this->order_money += $order_money;
  1149. $this->pay_money += $pay_money;
  1150. $this->goods_num += $shop_goods[ 'goods_num' ];
  1151. $this->order_name = string_split($this->order_name, ',', $shop_goods[ 'order_name' ]);
  1152. $this->point_money += $point_money;
  1153. $this->member_card_money += $member_card_money;
  1154. //买家留言
  1155. if (isset($data[ 'buyer_message' ]) && isset($data[ 'buyer_message' ])) {
  1156. $item_buyer_message = $data[ 'buyer_message' ];
  1157. $shop_goods[ 'buyer_message' ] = $item_buyer_message;
  1158. } else {
  1159. $shop_goods[ 'buyer_message' ] = '';
  1160. }
  1161. return $shop_goods;
  1162. }
  1163. /**
  1164. * 发票信息
  1165. * @param $shop_goods
  1166. * @param $data
  1167. */
  1168. public function invoice($shop_goods, $data)
  1169. {
  1170. $invoice_status = $shop_goods[ 'order_config' ][ 'invoice_status' ] ?? 0;
  1171. $shop_goods[ 'invoice_status' ] = $invoice_status;
  1172. $invoice_money = 0;
  1173. $invoice_delivery_money = 0;
  1174. if ($invoice_status == 1) {
  1175. $invoice_content = $shop_goods[ 'order_config' ][ 'invoice_content' ] ?? '';
  1176. $invoice_content_array = explode(',', $invoice_content);
  1177. $shop_goods[ 'invoice' ][ 'invoice_content_array' ] = $invoice_content_array;
  1178. $shop_goods[ 'invoice' ][ 'invoice_delivery_money' ] = $shop_goods[ 'order_config' ][ 'invoice_money' ] ?? 0;
  1179. $shop_goods[ 'invoice' ][ 'invoice_rate' ] = $shop_goods[ 'order_config' ][ 'invoice_rate' ] ?? 0;
  1180. $shop_goods[ 'invoice' ][ 'invoice_type' ] = $shop_goods[ 'order_config' ][ 'invoice_type' ] ?? '1,2';
  1181. $is_invoice = $data[ 'is_invoice' ] ?? 0;
  1182. $shop_goods[ 'is_invoice' ] = $is_invoice;
  1183. //是否需要发票
  1184. if ($is_invoice) {
  1185. $promotion_money = $shop_goods[ 'promotion_money' ];//优惠金额
  1186. $coupon_money = $shop_goods[ 'coupon_money' ] ?? 0;//优惠券金额
  1187. $point_money = $shop_goods[ 'point_money' ] ?? 0;//积分抵现金额
  1188. $real_goods_money = $shop_goods[ 'goods_money' ] - $promotion_money - $coupon_money - $point_money;
  1189. $invoice_money = round($real_goods_money * $shop_goods[ 'invoice' ][ 'invoice_rate' ] / 100, 2);
  1190. $invoice_type = $data[ 'invoice_type' ] ?? 1;
  1191. if ($invoice_type == 1) {
  1192. $invoice_delivery_money = $shop_goods[ 'invoice' ][ 'invoice_delivery_money' ];
  1193. $shop_goods[ 'invoice_full_address' ] = !empty($data[ 'invoice_full_address' ]) ? $data[ 'invoice_full_address' ] : '';
  1194. // if (empty($data[ 'invoice_full_address' ])) {
  1195. // $this->setError(1, '发票邮寄地址不能为空!');
  1196. // } else {
  1197. // $shop_goods[ 'invoice_full_address' ] = $data[ 'invoice_full_address' ];
  1198. // }
  1199. } else {
  1200. if (empty($data[ 'invoice_email' ])) {
  1201. $this->setError(1, '发票邮箱不能为空!');
  1202. } else {
  1203. $shop_goods[ 'invoice_email' ] = $data[ 'invoice_email' ];
  1204. }
  1205. }
  1206. if (empty($data[ 'invoice_title' ]) || empty($data[ 'invoice_type' ]) || empty($data[ 'invoice_content' ] || $data[ 'invoice_title_type' ] == 0)) {
  1207. $this->setError(1, '发票相关项不能为空!');
  1208. }
  1209. //企业抬头 必须填写税号
  1210. if ($data[ 'invoice_title_type' ] == 2 && empty($data[ 'taxpayer_number' ])) {
  1211. $this->setError(1, '发票相关项不能为空!');
  1212. }
  1213. $shop_goods[ 'invoice_title_type' ] = $data[ 'invoice_title_type' ];
  1214. $shop_goods[ 'is_tax_invoice' ] = $data[ 'is_tax_invoice' ];
  1215. $shop_goods[ 'taxpayer_number' ] = $data[ 'taxpayer_number' ];
  1216. $shop_goods[ 'invoice_title' ] = $data[ 'invoice_title' ];
  1217. $shop_goods[ 'invoice_type' ] = $data[ 'invoice_type' ];
  1218. $shop_goods[ 'invoice_content' ] = $data[ 'invoice_content' ];
  1219. $shop_goods[ 'invoice_rate' ] = $shop_goods[ 'invoice' ][ 'invoice_rate' ];
  1220. }
  1221. }
  1222. $shop_goods[ 'invoice_money' ] = $invoice_money;
  1223. $shop_goods[ 'invoice_delivery_money' ] = $invoice_delivery_money;
  1224. return $shop_goods;
  1225. }
  1226. /**
  1227. * 计算会员卡开卡金额
  1228. * @param $data
  1229. */
  1230. public function calculateMemberCardMoney($data)
  1231. {
  1232. $money = 0;
  1233. if (!empty($this->recommend_member_card) && $data[ 'is_open_card' ]) {
  1234. $charge_rule = $this->recommend_member_card[ 'charge_rule' ];
  1235. $money = $charge_rule[ $data[ 'member_card_unit' ] ] ?? 0;
  1236. }
  1237. return $money;
  1238. }
  1239. /**
  1240. * 增加订单自动关闭事件
  1241. * @param $order_id
  1242. */
  1243. public function addOrderCronClose($order_id, $site_id)
  1244. {
  1245. //计算订单自动关闭时间
  1246. $config_model = new Config();
  1247. $order_config_result = $config_model->getOrderEventTimeConfig($site_id);
  1248. $order_config = $order_config_result[ 'data' ];
  1249. $now_time = time();
  1250. if ($order_config[ 'value' ][ 'auto_close' ] > 0) {
  1251. $execute_time = $now_time + $order_config[ 'value' ][ 'auto_close' ] * 60; //自动关闭时间
  1252. $cron_model = new Cron();
  1253. $res = $cron_model->addCron(1, 0, '订单自动关闭', 'CronOrderClose', $execute_time, $order_id);
  1254. // 订单催付通知
  1255. // 未付款订单将会在订单关闭前10分钟对买家进行催付提醒
  1256. if ($this->pay_money > 0) {
  1257. $cron_model->addCron(1, 0, '订单催付通知', 'CronOrderUrgePayment', $execute_time - 600, $order_id);
  1258. }
  1259. }
  1260. }
  1261. /**
  1262. * 使用余额
  1263. * @param $data
  1264. * @param $site_id
  1265. * @param string $from_type
  1266. * @return array
  1267. */
  1268. public function useBalance($data, $site_id, $from_type = 'order')
  1269. {
  1270. $this->pay_type = 'BALANCE';
  1271. $member_model = new Member();
  1272. // $result = $member_model->checkPayPassword($data['member_id'], $data['pay_password']);
  1273. // if ($result['code'] >= 0) {
  1274. $balance_money = $data[ 'member_account' ][ 'balance_money' ]; //储值余额
  1275. $balance = $data[ 'member_account' ][ 'balance' ]; //现金余额
  1276. $member_account_model = new MemberAccount();
  1277. $surplus_banance = $data[ 'balance_money' ];
  1278. //优先扣除储值余额
  1279. if ($balance > 0) {
  1280. if ($balance >= $surplus_banance) {
  1281. $real_balance = $surplus_banance;
  1282. } else {
  1283. $real_balance = $balance;
  1284. }
  1285. $result = $member_account_model->addMemberAccount($site_id, $data[ 'member_id' ], 'balance', -$real_balance, $from_type, $data[ 'order_id' ], '订单消费扣除');
  1286. $surplus_banance -= $real_balance;
  1287. }
  1288. // if($balance_money > 0){
  1289. // if($balance_money > $surplus_banance){
  1290. // $real_balance_money = $surplus_banance;
  1291. // }else{
  1292. // $real_balance_money = $balance_money;
  1293. // }
  1294. // $result = $member_account_model->addMemberAccount($data['member_id'], 'balance', -$real_balance, 'order', '余额抵扣','订单余额抵扣,扣除储值余额:'.$real_balance);
  1295. // }
  1296. if ($surplus_banance > 0) {
  1297. $result = $member_account_model->addMemberAccount($site_id, $data[ 'member_id' ], 'balance_money', -$surplus_banance, $from_type, $data[ 'order_id' ], '订单消费扣除');
  1298. }
  1299. return $result;
  1300. // } else {
  1301. // return $result;
  1302. // }
  1303. }
  1304. /**
  1305. * 初始化会员账户
  1306. * @param $data
  1307. * @return mixed
  1308. */
  1309. public function initMemberAccount($data)
  1310. {
  1311. $site_id = $data[ 'site_id' ];
  1312. $member_model = new Member();
  1313. $member_info_result = $member_model->getMemberDetail($data[ 'member_id' ], $site_id);
  1314. $member_info = $member_info_result[ 'data' ];
  1315. if (!empty($member_info)) {
  1316. if (!empty($member_info[ 'pay_password' ])) {
  1317. $is_pay_password = 1;
  1318. } else {
  1319. $is_pay_password = 0;
  1320. }
  1321. unset($member_info[ 'pay_password' ]);
  1322. $member_info[ 'is_pay_password' ] = $is_pay_password;
  1323. $data[ 'member_account' ] = $member_info;
  1324. // 查询推荐会员卡
  1325. if ($member_info[ 'member_level_type' ] == 0 && addon_is_exit('supermember', $site_id)) {
  1326. $store_id = $data[ 'store_id' ] ?? 0;
  1327. //todo 门店线上不参与推荐会员卡关联购买
  1328. if (addon_is_exit('store') && $store_id > 0) {
  1329. $member_card_model = new MemberCard();
  1330. $recommend_member_card = $member_card_model->getRecommendMemberCard($site_id);
  1331. if (!empty($recommend_member_card[ 'data' ])) {
  1332. $recommend_member_card[ 'data' ][ 'discount_money' ] = 0;
  1333. $recommend_member_card[ 'data' ][ 'charge_rule' ] = json_decode($recommend_member_card[ 'data' ][ 'charge_rule' ], true);
  1334. $this->recommend_member_card = $recommend_member_card[ 'data' ];
  1335. }
  1336. }
  1337. }
  1338. }
  1339. return $data;
  1340. }
  1341. /****************************************************************************** 满减 start *****************************************************************************/
  1342. /**
  1343. * 满减优惠
  1344. * @param $data
  1345. */
  1346. public function manjianPromotion($calculate_data)
  1347. {
  1348. $calculate_data[ 'manjian_rule_list' ] = [];
  1349. //先查询全部商品的满减套餐 进行中
  1350. $manjian_model = new Manjian();
  1351. $all_info_result = $manjian_model->getManjianInfo([ [ 'manjian_type', '=', 1 ], [ 'site_id', '=', $calculate_data[ 'site_id' ] ], [ 'status', '=', 1 ] ], 'manjian_name,type,goods_ids,rule_json,manjian_id');
  1352. $all_info = $all_info_result[ 'data' ];
  1353. $goods_list = $calculate_data[ 'goods_list' ];
  1354. //存在全场满减(不考虑部分满减情况)
  1355. if (!empty($all_info)) {
  1356. $discount_array = $this->getManjianDiscountMoney($all_info, $calculate_data);
  1357. $all_info[ 'discount_array' ] = $discount_array;
  1358. //判断有没有优惠
  1359. $temp_goods_list = $this->distributionGoodsDemiscount($goods_list, $calculate_data[ 'goods_money' ], $discount_array[ 'real_discount_money' ], isset($discount_array[ 'rule' ][ 'free_shipping' ]));
  1360. $goods_list = $temp_goods_list;
  1361. $manjian_list[] = $all_info;
  1362. $discount_money = $discount_array[ 'real_discount_money' ];
  1363. $calculate_data[ 'goods_list' ] = $goods_list;
  1364. $calculate_data[ 'promotion_money' ] += $discount_money;
  1365. if (!empty($discount_array[ 'rule' ])) {
  1366. $calculate_data[ 'manjian_rule_list' ][] = [
  1367. 'manjian_info' => $all_info,
  1368. 'rule' => $discount_array[ 'rule' ],
  1369. 'sku_ids' => ''
  1370. ];
  1371. $calculate_data[ 'promotion' ][ 'manjian' ] = $manjian_list;
  1372. }
  1373. } else {
  1374. $goods_ids = array_unique(array_column($calculate_data[ 'goods_list' ], 'goods_id'));
  1375. $manjian_condition = array (
  1376. [ 'goods_id', 'in', $goods_ids ],
  1377. [ 'status', '=', 1 ]
  1378. );
  1379. $manjian_goods_list_result = $manjian_model->getManjianGoodsList($manjian_condition, 'manjian_id');
  1380. $manjian_goods_list = $manjian_goods_list_result[ 'data' ];
  1381. if (!empty($manjian_goods_list)) {
  1382. $discount_money = 0;
  1383. $manjian_goods_list = array_column($manjian_goods_list, 'manjian_id');
  1384. $manjian_goods_list = array_unique($manjian_goods_list); //去重
  1385. sort($manjian_goods_list);
  1386. $manjian_list_result = $manjian_model->getManjianList([ [ 'manjian_id', 'in', $manjian_goods_list ], [ 'status', '=', 1 ] ]);
  1387. $manjian_list = $manjian_list_result[ 'data' ];
  1388. foreach ($manjian_list as $k => $v) {
  1389. $manjian_goods_ids = explode(',', $v[ 'goods_ids' ]);
  1390. $item_goods_data = [
  1391. 'goods_money' => 0,
  1392. 'goods_num' => 0
  1393. ];
  1394. $item_goods_list = [];
  1395. $sku_ids = [];
  1396. foreach ($goods_list as $goods_k => $goods_item) {
  1397. if (in_array($goods_item[ 'goods_id' ], $manjian_goods_ids)) {
  1398. $item_goods_data[ 'goods_money' ] += $goods_item[ 'goods_money' ];
  1399. $item_goods_data[ 'goods_num' ] += $goods_item[ 'num' ];
  1400. $item_goods_list[] = $goods_item;
  1401. array_push($sku_ids, $goods_item[ 'sku_id' ]);
  1402. unset($goods_list[ $goods_k ]);
  1403. }
  1404. }
  1405. $discount_array = $this->getManjianDiscountMoney($v, $item_goods_data);
  1406. $temp_goods_list = $this->distributionGoodsDemiscount($item_goods_list, $item_goods_data[ 'goods_money' ], $discount_array[ 'real_discount_money' ], isset($discount_array[ 'rule' ][ 'free_shipping' ]), $sku_ids);
  1407. $goods_list = array_merge($goods_list, $temp_goods_list);
  1408. $manjian_list[ $k ][ 'discount_array' ] = $discount_array;
  1409. $discount_money += $discount_array[ 'real_discount_money' ];
  1410. if (!empty($discount_array[ 'rule' ])) {
  1411. array_push($calculate_data[ 'manjian_rule_list' ], [
  1412. 'manjian_info' => $v,
  1413. 'rule' => $discount_array[ 'rule' ],
  1414. 'sku_ids' => $sku_ids
  1415. ]);
  1416. }
  1417. }
  1418. $calculate_data[ 'promotion' ][ 'manjian' ] = $manjian_list;
  1419. $calculate_data[ 'goods_list' ] = $goods_list;
  1420. $calculate_data[ 'promotion_money' ] += $discount_money;
  1421. }
  1422. }
  1423. return $calculate_data;
  1424. }
  1425. /**
  1426. * 满减优惠金额
  1427. * @param $rule_list
  1428. * @param $goods_money
  1429. */
  1430. public function getManjianDiscountMoney($manjian_info, $data)
  1431. {
  1432. $goods_money = $data[ 'goods_money' ];
  1433. $value = $manjian_info[ 'type' ] == 0 ? $data[ 'goods_money' ] : $data[ 'goods_num' ];
  1434. //阶梯计算优惠
  1435. $rule_item = json_decode($manjian_info[ 'rule_json' ], true);
  1436. $discount_money = 0;
  1437. $money = 0;
  1438. $rule = []; // 符合条件的优惠规则
  1439. array_multisort(array_column($rule_item, 'limit'), SORT_ASC, $rule_item); //排序,根据num 排序
  1440. foreach ($rule_item as $k => $v) {
  1441. if ($value >= $v[ 'limit' ]) {
  1442. $rule = $v;
  1443. if (isset($v[ 'discount_money' ])) {
  1444. $discount_money = $v[ 'discount_money' ];
  1445. $money = $v[ 'limit' ];
  1446. }
  1447. }
  1448. }
  1449. $real_discount_money = $discount_money > $goods_money ? $goods_money : $discount_money;
  1450. return [ 'discount_money' => $discount_money, 'money' => $money, 'real_discount_money' => $real_discount_money, 'rule' => $rule ];
  1451. }
  1452. /**
  1453. * 处理商品满减
  1454. */
  1455. public function distributionGoodsDemiscount($goods_list, $goods_money, $discount_money, $is_free_shipping = false, $sku_ids = [])
  1456. {
  1457. $temp_discount_money = $discount_money;
  1458. $last_key = count($goods_list) - 1;
  1459. foreach ($goods_list as $k => $v) {
  1460. if ($last_key != $k) {
  1461. $item_discount_money = round($v[ 'goods_money' ] / $goods_money * $discount_money, 2);
  1462. } else {
  1463. $item_discount_money = $temp_discount_money;
  1464. }
  1465. $item_discount_money = $item_discount_money > $v[ 'real_goods_money' ] ? $v[ 'real_goods_money' ] : $item_discount_money;
  1466. $temp_discount_money -= $item_discount_money;
  1467. $goods_list[ $k ][ 'promotion_money' ] += $item_discount_money;
  1468. $goods_list[ $k ][ 'real_goods_money' ] -= $item_discount_money; //真实订单项金额
  1469. // 满减送包邮
  1470. if ($is_free_shipping) {
  1471. if (empty($sku_ids) || in_array($v[ 'sku_id' ], $sku_ids)) {
  1472. $goods_list[ $k ][ 'is_free_shipping' ] = 1;
  1473. }
  1474. }
  1475. }
  1476. return $goods_list;
  1477. }
  1478. /****************************************************************************** 满减 end *****************************************************************************/
  1479. /****************************************************************************** 订单优惠券 start *****************************************************************************/
  1480. /**
  1481. * 优惠券活动
  1482. * @param $shop_goods
  1483. * @param $coupon_info
  1484. * @return mixed
  1485. */
  1486. public function couponPromotion($shop_goods, $data)
  1487. {
  1488. $coupon_money = 0;
  1489. if (!empty($data[ 'coupon' ]) && $data[ 'coupon' ][ 'coupon_id' ] > 0) {
  1490. //查询优惠券信息,计算优惠券费用
  1491. $coupon_model = new Coupon();
  1492. $coupon_info_result = $coupon_model->getCouponInfo([ [ 'coupon_id', '=', $data[ 'coupon' ][ 'coupon_id' ] ], [ 'site_id', '=', $shop_goods[ 'site_id' ] ] ], 'member_id,at_least,money,state,goods_type,type,goods_ids,discount,discount_limit');
  1493. $coupon_info = $coupon_info_result[ 'data' ];
  1494. $is_coupon = false;
  1495. $coupon_goods_money = 0;
  1496. $goods_list = $shop_goods[ 'goods_list' ];
  1497. if ($coupon_info[ 'member_id' ] == $data[ 'member_id' ] && $coupon_info[ 'state' ] == 1) {
  1498. $coupon_goods_list = [];
  1499. if ($coupon_info[ 'goods_type' ] == 1) { //全场通用优惠券
  1500. if ($coupon_info[ 'at_least' ] <= $shop_goods[ 'goods_money' ]) {
  1501. $is_coupon = true;
  1502. } else {
  1503. $this->setError(1, '优惠券不可用!');
  1504. }
  1505. $coupon_goods_money = $shop_goods[ 'goods_money' ];
  1506. $coupon_goods_list = $goods_list;
  1507. $goods_list = [];
  1508. } else {
  1509. $item_goods_ids = explode(',', $coupon_info[ 'goods_ids' ]);
  1510. $temp_money = 0;
  1511. foreach ($goods_list as $goods_k => $goods_v) {
  1512. if (in_array($goods_v[ 'goods_id' ], $item_goods_ids)) {
  1513. $temp_money += $goods_v[ 'goods_money' ];
  1514. $coupon_goods_list[] = $goods_v;
  1515. unset($goods_list[ $goods_k ]);
  1516. }
  1517. }
  1518. if ($temp_money >= $coupon_info[ 'at_least' ]) {
  1519. $is_coupon = true;
  1520. }
  1521. $coupon_goods_money = $temp_money;
  1522. }
  1523. }
  1524. if ($is_coupon) {
  1525. $coupon_money = 0;
  1526. if ($coupon_info[ 'type' ] == 'reward') { //满减优惠券
  1527. $coupon_money = $coupon_info[ 'money' ] > $coupon_goods_money ? $coupon_goods_money : $coupon_info[ 'money' ];
  1528. } else if ($coupon_info[ 'type' ] == 'divideticket') { //瓜分优惠券
  1529. $coupon_money = $coupon_info[ 'money' ] > $coupon_goods_money ? $coupon_goods_money : $coupon_info[ 'money' ];
  1530. } else if ($coupon_info[ 'type' ] == 'discount') { //折扣优惠券
  1531. //计算折扣优惠金额
  1532. $coupon_money = $coupon_goods_money * ( 10 - $coupon_info[ 'discount' ] ) / 10;
  1533. $coupon_money = $coupon_money > $coupon_info[ 'discount_limit' ] && $coupon_info[ 'discount_limit' ] != 0 ? $coupon_info[ 'discount_limit' ] : $coupon_money;
  1534. $coupon_money = $coupon_money > $coupon_goods_money ? $coupon_goods_money : $coupon_money;
  1535. $coupon_money = round($coupon_money, 2);
  1536. }
  1537. $temp_goods_list = $this->distributionGoodsCouponMoney($coupon_goods_list, $coupon_goods_money, $coupon_money);
  1538. $goods_list = array_merge($goods_list, $temp_goods_list);
  1539. $shop_goods[ 'goods_list' ] = $goods_list;
  1540. } else {
  1541. $this->setError(1, '优惠券不可用!');
  1542. }
  1543. }
  1544. if ($coupon_money > 0) {
  1545. $shop_goods[ 'coupon_id' ] = $data[ 'coupon' ][ 'coupon_id' ];
  1546. if ($coupon_money > $shop_goods[ 'order_money' ]) {
  1547. $coupon_money = $shop_goods[ 'order_money' ];
  1548. }
  1549. $shop_goods[ 'order_money' ] -= $coupon_money;
  1550. $shop_goods[ 'coupon_money' ] = $coupon_money;
  1551. }
  1552. return $shop_goods;
  1553. }
  1554. /**
  1555. * 查询可用优惠券
  1556. * @param $data
  1557. */
  1558. public function getOrderCouponList($data)
  1559. {
  1560. $coupon_list = [];
  1561. //先查询全场通用的优惠券
  1562. $member_coupon_model = new Coupon();
  1563. $all_condition = array (
  1564. [ 'member_id', '=', $data[ 'member_id' ] ],
  1565. [ 'state', '=', 1 ],
  1566. [ 'site_id', '=', $data[ 'site_id' ] ],
  1567. [ 'goods_type', '=', 1 ],
  1568. [ 'at_least', '<=', $data[ 'shop_goods_list' ][ 'goods_money' ] ]
  1569. );
  1570. $all_coupon_list_result = $member_coupon_model->getCouponList($all_condition);
  1571. $all_coupon_list = $all_coupon_list_result[ 'data' ];
  1572. $coupon_list = array_merge($coupon_list, $all_coupon_list);
  1573. $shop_goods_list = $data[ 'shop_goods_list' ];
  1574. $goods_ids = array_column($shop_goods_list[ 'goods_list' ], 'goods_id');
  1575. $goods_list = $shop_goods_list[ 'goods_list' ];
  1576. $item_condition = array (
  1577. [ 'member_id', '=', $data[ 'member_id' ] ],
  1578. [ 'state', '=', 1 ],
  1579. [ 'site_id', '=', $data[ 'site_id' ] ],
  1580. [ 'goods_type', '=', 2 ],
  1581. );
  1582. $item_like_array = [];
  1583. foreach ($goods_ids as $k => $v) {
  1584. $item_like_array[] = '%,' . $v . ',%';
  1585. }
  1586. $item_condition[] = [ 'goods_ids', 'like', $item_like_array, 'OR' ];
  1587. $item_coupon_list_result = $member_coupon_model->getCouponList($item_condition);
  1588. $item_coupon_list = $item_coupon_list_result[ 'data' ];
  1589. if (!empty($item_coupon_list)) {
  1590. foreach ($item_coupon_list as $item_k => $item_v) {
  1591. $item_goods_ids = explode(',', $item_v[ 'goods_ids' ]);
  1592. $item_goods_money = 0;
  1593. foreach ($goods_list as $goods_k => $goods_v) {
  1594. if (in_array($goods_v[ 'goods_id' ], $item_goods_ids)) {
  1595. $item_goods_money += $goods_v[ 'goods_money' ];
  1596. }
  1597. }
  1598. if ($item_goods_money >= $item_v[ 'at_least' ]) {
  1599. $coupon_list[] = $item_v;
  1600. }
  1601. // $intersect_goods_ids = array_intersect($item_goods_ids, $goods_ids);
  1602. }
  1603. }
  1604. array_multisort(array_column($coupon_list, 'money'), SORT_DESC, $coupon_list);
  1605. return $coupon_list;
  1606. }
  1607. /**
  1608. * 查询商品可用次卡
  1609. * @param $data
  1610. */
  1611. public function memberGoodsCardPromotion($calculate_data, $data)
  1612. {
  1613. if (addon_is_exit('cardservice', $data[ 'site_id' ])) {
  1614. $member_card = new \addon\cardservice\model\MemberCard();
  1615. $common_card = [];
  1616. foreach ($calculate_data[ 'goods_list' ] as $k => $goods_item) {
  1617. $condition = [
  1618. [ 'mgci.member_id', '=', $data[ 'member_id' ] ],
  1619. [ 'mgci.sku_id', '=', $goods_item[ 'sku_id' ] ],
  1620. [ 'mgc.status', '=', 1 ],
  1621. [ '', 'exp', Db::raw("( (mgc.card_type = 'timercard') OR (mgc.card_type = 'oncecard' AND mgci.num > mgci.use_num) OR (mgc.card_type = 'commoncard' AND mgc.total_num > mgc.total_use_num) )") ]
  1622. ];
  1623. $card_ids = array_filter(array_map(function($item) {
  1624. if ($item[ 'total_use_num' ] >= $item[ 'total_num' ]) return $item[ 'card_id' ];
  1625. }, $common_card));
  1626. if (!empty($card_ids)) $condition[] = [ 'mgci.card_id', 'not in', $card_ids ];
  1627. // 查询可用的卡项
  1628. $card_list = $member_card->getCartItemList($condition, 'mgci.item_id,mgci.card_id,mgci.num,mgci.use_num,mgci.member_verify_id,mgc.end_time,mgc.total_num,mgc.total_use_num,mgc.card_type,mgc.goods_name', '', 'mgci', [
  1629. [ 'member_goods_card mgc', 'mgc.card_id = mgci.card_id', 'inner' ],
  1630. ])[ 'data' ];
  1631. if (!empty($card_list)) {
  1632. $card_item_id = isset($data[ 'member_goods_card' ]) && isset($data[ 'member_goods_card' ][ $goods_item[ 'sku_id' ] ]) ? $data[ 'member_goods_card' ][ $goods_item[ 'sku_id' ] ] : 0;
  1633. $card_list = array_column($card_list, null, 'item_id');
  1634. // 抵扣判断
  1635. if (isset($card_list[ $card_item_id ])) {
  1636. $card_item = $card_list[ $card_item_id ];
  1637. if ($card_item[ 'card_type' ] == 'commoncard') {
  1638. if (isset($common_card[ $card_item[ 'card_id' ] ])) {
  1639. $card_item[ 'num' ] = $common_card[ $card_item[ 'card_id' ] ][ 'total_num' ] - $common_card[ $card_item[ 'card_id' ] ][ 'total_use_num' ];
  1640. } else {
  1641. $card_item[ 'num' ] = $card_item[ 'total_num' ] - $card_item[ 'total_use_num' ];
  1642. }
  1643. } else if ($card_item[ 'card_type' ] == 'timecard') {
  1644. $card_item[ 'num' ] = $goods_item[ 'num' ];
  1645. } else {
  1646. $card_item[ 'num' ] -= $card_item[ 'use_num' ];
  1647. }
  1648. $num = $card_item[ 'num' ] > $goods_item[ 'num' ] ? $goods_item[ 'num' ] : $card_item[ 'num' ];
  1649. $promotion_money = round($goods_item[ 'price' ] * $num, 2);
  1650. $calculate_data[ 'goods_list' ][ $k ][ 'promotion_money' ] += $promotion_money;
  1651. $calculate_data[ 'goods_list' ][ $k ][ 'card_promotion_money' ] = $promotion_money;
  1652. $calculate_data[ 'goods_list' ][ $k ][ 'real_goods_money' ] = round($goods_item[ 'real_goods_money' ] - $promotion_money, 2);
  1653. $calculate_data[ 'goods_list' ][ $k ][ 'card_use_num' ] = $num;
  1654. // 针对通卡进行处理
  1655. if ($card_item[ 'card_type' ] == 'commoncard') {
  1656. if (isset($common_card[ $card_item[ 'card_id' ] ])) {
  1657. $common_card[ $card_item[ 'card_id' ] ][ 'total_use_num' ] += $num;
  1658. } else {
  1659. $common_card[ $card_item[ 'card_id' ] ] = [
  1660. 'card_id' => $card_item[ 'card_id' ],
  1661. 'total_num' => $card_item[ 'total_num' ],
  1662. 'total_use_num' => $card_item[ 'total_use_num' ] + $num
  1663. ];
  1664. }
  1665. }
  1666. $calculate_data[ 'promotion_money' ] += $promotion_money;
  1667. } else {
  1668. unset($data[ 'member_goods_card' ][ $goods_item[ 'sku_id' ] ]);
  1669. }
  1670. $calculate_data[ 'goods_list' ][ $k ][ 'member_card_list' ] = $card_list;
  1671. }
  1672. }
  1673. }
  1674. return $calculate_data;
  1675. }
  1676. /**
  1677. * 按比例摊派优惠券优惠
  1678. */
  1679. public function distributionGoodsCouponMoney($goods_list, $goods_money, &$coupon_money)
  1680. {
  1681. $temp_coupon_money = $coupon_money;
  1682. $last_key = count($goods_list) - 1;
  1683. foreach ($goods_list as $k => $v) {
  1684. if ($last_key != $k) {
  1685. $item_coupon_money = round($v[ 'real_goods_money' ] / $goods_money * $coupon_money, 2);
  1686. } else {
  1687. $item_coupon_money = $temp_coupon_money;
  1688. }
  1689. $item_coupon_money = $item_coupon_money > $v[ 'real_goods_money' ] ? $v[ 'real_goods_money' ] : $item_coupon_money;
  1690. $temp_coupon_money -= $item_coupon_money;
  1691. $goods_list[ $k ][ 'coupon_money' ] = $item_coupon_money;
  1692. $goods_list[ $k ][ 'real_goods_money' ] -= $item_coupon_money; //真实订单项金额
  1693. }
  1694. // 如果优惠券没有可抵扣金额
  1695. if ($temp_coupon_money == $coupon_money) $coupon_money = 0;
  1696. return $goods_list;
  1697. }
  1698. /****************************************************************************** 订单优惠券 end *****************************************************************************/
  1699. /**
  1700. * 满额包邮
  1701. * @param $shop_goods
  1702. */
  1703. public function freeShippingCalculate($shop_goods, $data)
  1704. {
  1705. if (addon_is_exit('freeshipping', $data[ 'site_id' ])) {
  1706. $free_shipping_model = new Freeshipping();
  1707. $district_id = $data[ 'member_address' ][ 'district_id' ] ?? 0;
  1708. $free_result = $free_shipping_model->calculate($shop_goods[ 'goods_money' ], $district_id, $data[ 'site_id' ]);
  1709. if ($free_result[ 'code' ] >= 0) {
  1710. $shop_goods[ 'promotion' ][ 'freeshipping' ] = $free_result[ 'data' ]; //优惠活动 满额包邮
  1711. $shop_goods[ 'is_free_delivery' ] = true;
  1712. }
  1713. }
  1714. return $shop_goods;
  1715. }
  1716. /**
  1717. * 会员等级免邮
  1718. */
  1719. public function memberLevelCalculate($shop_goods, $data)
  1720. {
  1721. $member_model = new Member();
  1722. $info = $member_model->getMemberInfo([ [ 'member_id', '=', $data[ 'member_id' ] ], [ 'site_id', '=', $data[ 'site_id' ] ] ], 'member_level');
  1723. if (!empty($info[ 'data' ])) {
  1724. $member_level_model = new MemberLevel();
  1725. $member_level_result = $member_level_model->getMemberLevelInfo([ [ 'level_id', '=', $info[ 'data' ][ 'member_level' ] ] ], '*');
  1726. $member_level = $member_level_result[ 'data' ];
  1727. $is_free_shipping = $member_level[ 'is_free_shipping' ] ?? 0;
  1728. if ($is_free_shipping > 0) {
  1729. $shop_goods[ 'promotion' ][ 'member_level' ] = $member_level; //优惠活动 满额包邮
  1730. $shop_goods[ 'is_free_delivery' ] = true;
  1731. }
  1732. }
  1733. return $shop_goods;
  1734. }
  1735. /**
  1736. * 获取订单最大可用积分
  1737. * @param $data
  1738. */
  1739. public function getMaxUsablePoint($shop_goods, $data)
  1740. {
  1741. $point = 0;
  1742. // 获取积分抵现配置
  1743. $config_model = new PointCashConfig();
  1744. $config = $config_model->getPointCashConfig($data[ 'site_id' ]);
  1745. $config = $config[ 'data' ][ 'value' ];
  1746. $shop_goods[ 'point_cash_config' ] = $config;
  1747. $order_money = $shop_goods[ 'delivery_money' ] > 0 ? $shop_goods[ 'order_money' ] - $shop_goods[ 'delivery_money' ] : $shop_goods[ 'order_money' ];
  1748. if ($config[ 'is_enable' ]) {
  1749. if ($config[ 'is_limit' ] == 1 && $order_money < $config[ 'limit' ]) {
  1750. $shop_goods[ 'max_usable_point' ] = $point;
  1751. return $shop_goods;
  1752. }
  1753. $deduction_money = $order_money;
  1754. if ($config[ 'is_limit_use' ] == 1) {
  1755. if ($config[ 'type' ] == 0) {
  1756. $deduction_money = $config[ 'max_use' ];
  1757. } else {
  1758. $ratio = $config[ 'max_use' ] / 100;
  1759. $deduction_money = round(( $order_money * $ratio ), 2);
  1760. }
  1761. if ($deduction_money > $order_money) {
  1762. $deduction_money = $order_money;
  1763. }
  1764. }
  1765. $max_point = round($deduction_money * $config[ 'cash_rate' ]);
  1766. $point = $max_point > $data[ 'member_account' ][ 'point' ] ? $data[ 'member_account' ][ 'point' ] : $max_point;
  1767. }
  1768. if ($data[ 'is_point' ] && $point > 0) {
  1769. $point_money = round(( $point * ( 1 / $config[ 'cash_rate' ] ) ), 2);
  1770. if ($point_money > $order_money) {
  1771. $point_money = $order_money;
  1772. }
  1773. $shop_goods[ 'goods_list' ] = $this->distributionGoodsPoint($shop_goods[ 'goods_list' ], $shop_goods[ 'goods_money' ], $point, $point_money);
  1774. $shop_goods[ 'order_money' ] -= $point_money;
  1775. $shop_goods[ 'point_money' ] = $point_money;
  1776. }
  1777. $shop_goods[ 'max_usable_point' ] = $point;
  1778. return $shop_goods;
  1779. }
  1780. /**
  1781. * 按比例摊派积分
  1782. * @param $goods_list
  1783. * @param $goods_money
  1784. * @param $point
  1785. */
  1786. public function distributionGoodsPoint($goods_list, $goods_money, $point, $point_money)
  1787. {
  1788. $temp_point = $point;
  1789. $temp_point_money = $point_money;
  1790. $last_key = count($goods_list) - 1;
  1791. foreach ($goods_list as $k => $v) {
  1792. if ($last_key != $k) {
  1793. $use_point = round($v[ 'goods_money' ] / $goods_money * $point);
  1794. $item_point_money = round($v[ 'goods_money' ] / $goods_money * $point_money, 2);
  1795. } else {
  1796. $use_point = $temp_point;
  1797. $item_point_money = $temp_point_money;
  1798. }
  1799. $temp_point -= $use_point;
  1800. $temp_point_money -= $item_point_money;
  1801. $goods_list[ $k ][ 'use_point' ] = $use_point;
  1802. $goods_list[ $k ][ 'point_money' ] = $item_point_money;
  1803. $real_goods_money = $v[ 'real_goods_money' ] - $item_point_money;
  1804. $real_goods_money = $real_goods_money < 0 ? 0 : $real_goods_money;
  1805. $goods_list[ $k ][ 'real_goods_money' ] = $real_goods_money; //真实订单项金额
  1806. }
  1807. return $goods_list;
  1808. }
  1809. }