OrderCreateTool.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  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 app\model\store\Store;
  12. use app\model\member\Member;
  13. use app\model\member\MemberAddress;
  14. use app\model\shop\Shop;
  15. use app\model\system\Cron;
  16. use think\facade\Cache;
  17. /**
  18. * 订单创建 可调用的工具类
  19. *
  20. * @author Administrator
  21. *
  22. */
  23. Trait OrderCreateTool
  24. {
  25. /**
  26. * 生成订单编号
  27. *
  28. * @param array $site_id
  29. */
  30. public function createOrderNo($site_id, $member_id = 0)
  31. {
  32. $time_str = date('YmdHi');
  33. $max_no = Cache::get($site_id . '_' . $member_id . '_' . $time_str);
  34. if (!isset($max_no) || empty($max_no)) {
  35. $max_no = 1;
  36. } else {
  37. $max_no = $max_no + 1;
  38. }
  39. $order_no = $time_str . $member_id . sprintf('%03d', $max_no);
  40. Cache::set($site_id . '_' . $member_id . '_' . $time_str, $max_no);
  41. return $order_no;
  42. }
  43. public function initStore($data)
  44. {
  45. $store_id = $data[ 'store_id' ] ?? 0;
  46. $store_model = new Store();
  47. $site_id = $data[ 'site_id' ];
  48. if ($store_id == 0) {
  49. // $is_allow_store = false;
  50. // //是否安装门店插件
  51. // //todo 只有存在门店插件,并且开启门店连锁模式,才可以所以传递store_id, 否则就只有门店配送和本地配送就可以接收store_id
  52. // if (addon_is_exit('store')) {
  53. // //查询门店运营插件
  54. // $store_config_model = new \addon\store\model\Config();
  55. // $store_config = $store_config_model->getStoreBusinessConfig($site_id)[ 'data' ][ 'value' ] ?? [];
  56. // if ($store_config[ 'store_business' ] == 'store') {
  57. // $is_allow_store = true;
  58. // }
  59. // }
  60. // if($is_allow_store){
  61. // $store_info = $store_model->getDefaultStore($site_id)[ 'data' ] ?? [];
  62. // $data[ 'store_info' ] = $store_info;
  63. // $data[ 'store_id' ] = $store_info[ 'store_id' ];
  64. // }
  65. } else {
  66. $cashier_type = $data[ 'cashier_type' ] ?? '';
  67. if ($cashier_type == 'cashier') {
  68. } else {
  69. $is_allow_store = false;
  70. //是否安装门店插件
  71. //todo 只有存在门店插件,并且开启门店连锁模式,才可以所以传递store_id, 否则就只有门店配送和本地配送就可以接收store_id
  72. if (addon_is_exit('store')) {
  73. //查询门店运营插件
  74. $store_config_model = new \addon\store\model\Config();
  75. $store_config = $store_config_model->getStoreBusinessConfig($site_id)[ 'data' ][ 'value' ] ?? [];
  76. if ($store_config[ 'store_business' ] == 'store') {
  77. $is_allow_store = true;
  78. }
  79. }
  80. if (!$is_allow_store) {
  81. $delivery_array = $data[ 'delivery' ] ?? [];
  82. $delivery_type = $delivery_array[ 'delivery_type' ] ?? 'express';
  83. if (!in_array($delivery_type, [ 'local', 'store' ])) {
  84. $store_id = 0;
  85. } else {
  86. $store_id = $data[ 'delivery' ][ 'store_id' ] ?? 0;
  87. }
  88. }
  89. }
  90. $store_info = $store_model->getStoreInfo([ [ 'site_id', '=', $site_id ], [ 'store_id', '=', $store_id ] ])[ 'data' ] ?? [];
  91. if (empty($store_info)) {
  92. $store_id = 0;
  93. }
  94. $data[ 'store_info' ] = $store_info;
  95. $data[ 'store_id' ] = $store_id;
  96. }
  97. return $data;
  98. }
  99. /**
  100. * 初始化站点信息
  101. * @param $data
  102. * @return mixed
  103. */
  104. public function initSiteData($data)
  105. {
  106. $site_id = $data[ 'site_id' ];
  107. $site_model = new Shop();
  108. $site_condition = array (
  109. [ 'site_id', '=', $site_id ]
  110. );
  111. $site_info = $site_model->getShopInfo($site_condition)[ 'data' ] ?? [];
  112. $data[ 'site_info' ] = $site_info;
  113. return $data;
  114. }
  115. /**
  116. * 初始化会员账户
  117. * @param $data
  118. * @return mixed
  119. */
  120. public function initMemberAccount($data)
  121. {
  122. $member_id = $data[ 'member_id' ] ?? 0;
  123. $site_id = $data[ 'site_id' ];
  124. if (empty($member_id))
  125. return $data;
  126. $member_model = new Member();
  127. $member_condition = array (
  128. [ 'member_id', '=', $member_id ],
  129. );
  130. $member_info = $member_model->getMemberInfo($member_condition)[ 'data' ] ?? [];
  131. if (empty($member_info))
  132. return $data;
  133. $data[ 'member_info' ] = $member_info;
  134. $data[ 'member_account' ] = $member_info;
  135. return $data;
  136. }
  137. /**
  138. * 初始化收货地址
  139. * @param unknown $data
  140. */
  141. public function initMemberAddress($data)
  142. {
  143. $member_address = new MemberAddress();
  144. $address = $member_address->getMemberAddressInfo([ [ 'member_id', '=', $data[ 'member_id' ] ], [ 'is_default', '=', 1 ] ]);
  145. $data[ 'member_address' ] = $address[ 'data' ];
  146. return $data;
  147. }
  148. /**
  149. * 计算商品的单价
  150. * @param $goods_info
  151. * @param $data
  152. */
  153. public function getGoodsPrice($goods_info, $data)
  154. {
  155. $store_id = $data[ 'store_id' ] ?? 0;
  156. //判断是否存在限时折扣
  157. //运营模式为平台, 选择门店或本地配送门店,门店价或门店商品统一价会收到折扣价..影响么
  158. //todo 计算商品的显示折扣价格 门店统一价该怎么处理和折扣价的关系
  159. if (addon_is_exit('cashier') && $store_id > 0) {
  160. $price = $goods_info[ 'price' ];//门店线上暂时没有折扣价格
  161. } else {
  162. $discount_price = $goods_info[ 'discount_price' ];
  163. $price = $discount_price;
  164. }
  165. //todo 计算当前会员的会员购买价
  166. $member_result = $this->getGoodsMemberPrice($goods_info, $data);
  167. if ($member_result[ 'code' ] >= 0) {
  168. $member_price = $member_result[ 'data' ];
  169. if ($member_price < $price) {
  170. $price = $member_price;
  171. }
  172. }
  173. return $this->success($price);
  174. }
  175. /**
  176. * 获取商品会员价格
  177. * @param $goods_info
  178. * @param $data
  179. */
  180. public function getGoodsMemberPrice($goods_info, $data)
  181. {
  182. $store_id = $data[ 'store_id' ] ?? 0;
  183. $sku_id = $goods_info[ 'sku_id' ];
  184. $site_id = $data[ 'site_id' ];
  185. $member_id = $data[ 'member_id' ];
  186. if ($member_id > 0) {
  187. $condition = [
  188. [ 'sku_id', '=', $sku_id ]
  189. ];
  190. $goods_sku_info = model('goods_sku')->getInfo($condition, '*');
  191. if (!empty($goods_sku_info)) {
  192. if (addon_is_exit("memberprice")) {
  193. if ($goods_sku_info[ 'is_consume_discount' ]) {
  194. $price = $goods_info[ 'price' ];
  195. $alias = 'm';
  196. $join = [
  197. [ 'member_level ml', 'ml.level_id = m.member_level', 'inner' ],
  198. ];
  199. $member_info = model("member")->getInfo([ [ 'member_id', '=', $member_id ] ], 'm.member_level,ml.consume_discount', $alias, $join);
  200. if (!empty($member_info)) {
  201. if ($goods_sku_info[ 'discount_config' ] == 1) {
  202. // 自定义优惠
  203. $goods_sku_info[ 'member_price' ] = json_decode($goods_sku_info[ 'member_price' ], true);
  204. $value = isset($goods_sku_info[ 'member_price' ][ $goods_sku_info[ 'discount_method' ] ][ $member_info[ 'member_level' ] ]) ? $goods_sku_info[ 'member_price' ][ $goods_sku_info[ 'discount_method' ] ][ $member_info[ 'member_level' ] ] : 0;
  205. switch ( $goods_sku_info[ 'discount_method' ] ) {
  206. case "discount":
  207. // 打折
  208. if ($value == 0) {
  209. $member_price = $price;
  210. } else
  211. $member_price = number_format($price * $value / 10, 2, '.', '');
  212. break;
  213. case "manjian":
  214. if ($value == 0) {
  215. $member_price = $price;
  216. } else
  217. // 满减
  218. $member_price = number_format($price - $value, 2, '.', '');
  219. break;
  220. case "fixed_price":
  221. if ($value == 0) {
  222. $member_price = $goods_sku_info[ 'price' ];
  223. } else
  224. // 指定价格
  225. $member_price = number_format($value, 2, '.', '');
  226. break;
  227. }
  228. } else {
  229. // 默认按会员享受折扣计算
  230. $member_price = number_format($price * $member_info[ 'consume_discount' ] / 100, 2, '.', '');
  231. }
  232. return $this->success($member_price);
  233. }
  234. }
  235. }
  236. }
  237. }
  238. return $this->error();
  239. }
  240. /**
  241. * 扣除商品库存
  242. * @param $params
  243. */
  244. public function skuDecStock($goods_info, $store_id = 0)
  245. {
  246. $goods_class = $goods_info[ 'goods_class' ] ?? 0;
  247. if (!empty($goods_class)) {
  248. if (in_array($goods_class, [ 1, 2, 3, 4, 5, 6 ])) {
  249. $order_stock = new OrderStock();
  250. $stock_result = $order_stock->decOrderSaleStock($goods_info[ 'sku_id' ], $goods_info[ 'num' ], $store_id);
  251. if ($stock_result[ 'code' ] < 0) {
  252. return $stock_result;
  253. }
  254. }
  255. }
  256. return $this->success();
  257. }
  258. /**
  259. * 次卡优惠计算
  260. * @param $goods_info
  261. */
  262. public function cardCalculate($goods_info)
  263. {
  264. $goods_money = $goods_info[ 'goods_money' ];
  265. //次卡抵扣优惠
  266. }
  267. /**
  268. * 补齐门店数据
  269. * @param $data
  270. */
  271. public function storeOrderData($shop_goods, $data)
  272. {
  273. $temp_data = [];
  274. $delivery_store_id = $shop_goods[ 'delivery' ][ 'store_id' ] ?? 0; //门店id
  275. if ($delivery_store_id > 0) {
  276. $store_model = new Store();
  277. $condition = array (
  278. [ 'store_id', '=', $delivery_store_id ],
  279. [ 'site_id', '=', $shop_goods[ 'site_id' ] ],
  280. [ 'status', '=', 1 ],
  281. [ 'is_pickup', '=', 1 ],
  282. );
  283. $store_info_result = $store_model->getStoreInfo($condition);
  284. $store_info = $store_info_result[ 'data' ] ?? [];
  285. if (empty($store_info)) {
  286. $this->setError(1, '当前门店不存在或未开启!');
  287. } else {
  288. $temp_data[ 'delivery_store_id' ] = $delivery_store_id;
  289. $delivery_store_name = $store_info_result[ 'data' ][ 'store_name' ];
  290. $temp_data[ 'delivery_store_name' ] = $delivery_store_name;
  291. $delivery_store_info = array (
  292. 'open_date' => $store_info[ 'open_date' ],
  293. 'full_address' => $store_info[ 'full_address' ] . $store_info[ 'address' ],
  294. 'longitude' => $store_info[ 'longitude' ],
  295. 'latitude' => $store_info[ 'latitude' ],
  296. 'telphone' => $store_info[ 'telphone' ],
  297. 'store_image' => $store_info[ 'store_image' ],
  298. 'time_type' => $store_info[ 'time_type' ],
  299. 'time_week' => $store_info[ 'time_week' ],
  300. 'start_time' => $store_info[ 'start_time' ],
  301. 'end_time' => $store_info[ 'end_time' ],
  302. );
  303. $temp_data[ 'delivery_store_info' ] = json_encode($delivery_store_info, JSON_UNESCAPED_UNICODE);
  304. $goods_list = $shop_goods[ 'goods_list' ];
  305. //核验门店库存 todo 新的库存方式
  306. // if (addon_is_exit('store', $data['site_id'])) {
  307. // foreach ($goods_list as $k => $v) {
  308. // //检测门店库存
  309. // $store_goods_sklu_model = new StoreGoodsSku();
  310. // $item_sku_params = array(
  311. // 'store_id' => $delivery_store_id,
  312. // 'goods_id' => $v['goods_id'],
  313. // 'sku_id' => $v['sku_id'],
  314. // 'site_id' => $data['site_id'],
  315. // 'num' => $v['num']
  316. // );
  317. // $result = $store_goods_sklu_model->checkStoreGoodsSkuStock($item_sku_params);
  318. // if ($result['code'] < 0) {
  319. // //todo 定义一个高优先级的提示窗口
  320. // //error 提示
  321. // $this->setError(1, $delivery_store_name.'(门店)'.'商品'.$v['sku_name'].$result['message'], 1);
  322. // }
  323. // }
  324. // }
  325. }
  326. } else {
  327. $this->setError(1, '配送门店不可为空!');
  328. }
  329. return array_merge($shop_goods, $temp_data);
  330. }
  331. /**
  332. * 设置错误,优先级
  333. * @param $error
  334. * @param string $priority 报错优先级 0 创建时提示 1 计算时提示
  335. */
  336. public function setError($error, $error_msg, $priority = '0')
  337. {
  338. $this->error = $error;
  339. $this->error_msg = $error_msg;
  340. if ($priority == 1) {
  341. $this->error_show = true;
  342. }
  343. }
  344. /**
  345. * 增加订单自动关闭事件
  346. * @param $order_id
  347. */
  348. public function addOrderCronClose($order_id, $site_id)
  349. {
  350. //计算订单自动关闭时间
  351. $config_model = new Config();
  352. $order_config_result = $config_model->getOrderEventTimeConfig($site_id);
  353. $order_config = $order_config_result[ 'data' ];
  354. $now_time = time();
  355. if ($order_config[ 'value' ][ 'auto_close' ] > 0) {
  356. $execute_time = $now_time + $order_config[ 'value' ][ 'auto_close' ] * 60; //自动关闭时间
  357. $cron_model = new Cron();
  358. $res = $cron_model->addCron(1, 0, '订单自动关闭', 'CronOrderClose', $execute_time, $order_id);
  359. }
  360. }
  361. }