OrderService.php 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. <?php
  2. namespace app\api\service;
  3. use app\common\model\ActivityProductModel;
  4. use app\common\model\AdminModel;
  5. use app\common\model\ConfigModel;
  6. use app\common\model\CreditCardConfigModel;
  7. use app\common\model\CustomerModel;
  8. use app\common\model\CustomerZueCoinModel;
  9. use app\common\model\OrderAnnualFeeModel;
  10. use app\common\model\OrderModel;
  11. use app\common\model\OrderPaymentModel;
  12. use app\common\model\OrderProceedsModel;
  13. use app\common\model\OrderProductModel;
  14. use app\common\model\PaymentChannelModel;
  15. use app\common\model\ProductModel;
  16. use app\common\model\StoreModel;
  17. use app\common\model\StoreProductModel;
  18. use think\facade\Db;
  19. class OrderService extends \app\BaseService
  20. {
  21. private $storeModel;
  22. private $orderModel;
  23. private $productModel;
  24. private $orderAnnualFeeModel;
  25. private $orderPaymentModel;
  26. private $orderProductModel;
  27. private $orderProceedsModel;
  28. private $activityProductModel;
  29. private $storeProductModel;
  30. private $configModel;
  31. private $adminModel;
  32. private $customerModel;
  33. private $paymentChannelModel;
  34. private $creditCardModel;
  35. private $zueCoinModel;
  36. public function __construct()
  37. {
  38. $this->storeModel = new StoreModel();
  39. $this->orderModel = new OrderModel();
  40. $this->productModel = new ProductModel();
  41. $this->configModel = new ConfigModel();
  42. $this->storeProductModel = new StoreProductModel();
  43. $this->orderAnnualFeeModel = new OrderAnnualFeeModel();
  44. $this->orderPaymentModel = new OrderPaymentModel();
  45. $this->orderProductModel = new OrderProductModel();
  46. $this->orderProceedsModel = new OrderProceedsModel();
  47. $this->activityProductModel = new ActivityProductModel();
  48. $this->adminModel = new AdminModel();
  49. $this->customerModel = new CustomerModel();
  50. $this->paymentChannelModel = new PaymentChannelModel();
  51. $this->creditCardModel = new CreditCardConfigModel();
  52. $this->zueCoinModel = new CustomerZueCoinModel();
  53. }
  54. /**
  55. * @param $params
  56. * @param array $store_products_params
  57. * @return \SResult
  58. * @throws \think\db\exception\DataNotFoundException
  59. * @throws \think\db\exception\DbException
  60. * @throws \think\db\exception\ModelNotFoundException
  61. */
  62. public function create($params, array $store_products_params) {
  63. // 客户
  64. $customer = $this->customerModel->findById($params['customer_id']);
  65. if (!$customer)
  66. return $this->fail(lang("The Customer does not exist"));
  67. // 门店
  68. $store = $this->storeModel->findById($params['store_id']);
  69. if (!$store)
  70. return $this->fail(lang("The store does not exist"));
  71. // 顾问 or 老师 ids
  72. $user_ids = [];
  73. // 门店商品ids
  74. $store_product_ids = [];
  75. for ($i = 0; $i < count($store_products_params); $i++) {
  76. $store_products_param = $store_products_params[$i];
  77. $ids = [];
  78. if(isset($store_products_param->adviser_1_id)) array_push($ids, $store_products_param->adviser_1_id);
  79. if(isset($store_products_param->adviser_2_id)) array_push($ids, $store_products_param->adviser_2_id);
  80. if(isset($store_products_param->teacher_1_id)) array_push($ids, $store_products_param->teacher_1_id);
  81. if(isset($store_products_param->teacher_2_id)) array_push($ids, $store_products_param->teacher_2_id);
  82. $user_ids = array_unique(array_merge($user_ids, $ids));
  83. array_push($store_product_ids, $store_products_param->store_product_id);
  84. }
  85. // Adviser|Teacher
  86. $users = $this->adminModel->findByIds($user_ids)->toArray();
  87. if(count($users) != count($user_ids))
  88. return $this->fail(lang("The Adviser|Teacher does not exist"));
  89. $fmt_users = array_reduce($users, function ($result, $item) {
  90. $result[$item['id']] = $item;
  91. return $result;
  92. }, []);
  93. // 门店商品
  94. $store_products = $this->storeProductModel->fetchRelationsByOrder($store_product_ids)->toArray();
  95. if(count($store_products) != count($store_product_ids))
  96. return $this->fail(lang("The Product does not exist"));
  97. // 商品信息
  98. $products = array_map(function ($p) {
  99. return $p['product'] ? $p['product'] : null;
  100. }, $store_products);
  101. if(in_array(null, $products))
  102. return $this->fail(lang("The Product does not exist"));
  103. $config = $this->configModel->findConfig();
  104. $activityProducts = $this->activityProductModel->fetchByProductIds(array_map(function ($data) {
  105. return $data['id'];
  106. }, $products))->toArray();
  107. $fmt_store_products = [];
  108. foreach ($store_products as &$item) {
  109. $aProducts = array_filter($activityProducts, function ($aProduct) use ($item) {
  110. return $aProduct['product_id'] == $item['product_id'];
  111. });
  112. $res = compare($item['product']['real_price'] ?? 0, $aProducts);
  113. $item['activity'] = $res['item'];
  114. $item['product']['origin_price'] = $item['product']['real_price'];
  115. $item['product']['real_price'] = fixed2Float($res['min_num'] > 0 ? $res['min_num'] : 0);
  116. $sales_tax_rate = $item['product']['sales_tax_rate'] > 0 ? $item['product']['sales_tax_rate'] : $config->sales_tax_rate;
  117. $sales_tax = fixed2Float($sales_tax_rate > 0 && $item['product']['real_price'] > 0 ? ($item['product']['real_price'] * ($sales_tax_rate / 100)) : 0);
  118. $item['product']['sales_tax_rate'] = $sales_tax_rate;
  119. $item['product']['sales_tax'] = $sales_tax;
  120. $fmt_store_products[$item['id']] = $item;
  121. }
  122. $order_products = [];
  123. //项目总额
  124. $rental_amount = 0;
  125. $product_amount = 0;
  126. // 总消费税
  127. $total_sales_tax = 0;
  128. $advisor_ids = [];
  129. $product_names = [];
  130. $total_annual_fee = 0;
  131. $order_no = $this->orderModel->genOrderNo($store->id, $store->abbr);
  132. for ($i = 0; $i < count($store_products_params); $i++) {
  133. $store_products_param = $store_products_params[$i];
  134. $store_product = $fmt_store_products[$store_products_param->store_product_id];
  135. if($store_product['now_stock'] < $store_products_param->quantity)
  136. return $this->fail(lang("inventory shortage"));
  137. array_push($advisor_ids, $store_products_param->adviser_1_id);
  138. if(isset($store_products_param->adviser_2_id)) {
  139. array_push($advisor_ids, $store_products_param->adviser_2_id);
  140. }
  141. for ($j = 0; $j < $store_products_param->quantity; $j++) {
  142. array_push($product_names, $store_product['product']['name']);
  143. array_push($order_products, [
  144. 'order_id' => 0,
  145. 'order_no' => $order_no,
  146. 'customer_id' => $customer->id,
  147. 'product_id' => $store_product['product']['id'],
  148. 'product_category_id' => $store_product['product']['category_id'],
  149. 'is_serve' => $store_product['product']['is_serve'],
  150. 'store_product_id' => $store_product['id'],
  151. 'product_name' => $store_product['product']['name'],
  152. 'adviser_1_id' => isset($store_products_param->adviser_1_id) ? $store_products_param->adviser_1_id : null,
  153. 'adviser_1_name' => isset($store_products_param->adviser_1_id) ? $fmt_users[$store_products_param->adviser_1_id]['nickname'] : null,
  154. 'adviser_2_id' => isset($store_products_param->adviser_2_id) ? $store_products_param->adviser_2_id : null,
  155. 'adviser_2_name' => isset($store_products_param->adviser_2_id) ? $fmt_users[$store_products_param->adviser_2_id]['nickname'] : null,
  156. 'teacher_1_id' => isset($store_products_param->teacher_1_id) ? $store_products_param->teacher_1_id : null,
  157. 'teacher_1_name' => isset($store_products_param->teacher_1_id) ? $fmt_users[$store_products_param->teacher_1_id]['nickname'] : null,
  158. 'teacher_2_id' => isset($store_products_param->teacher_2_id) ? $store_products_param->teacher_2_id : null,
  159. 'teacher_2_name' => isset($store_products_param->teacher_2_id) ? $fmt_users[$store_products_param->teacher_2_id]['nickname'] : null,
  160. 'is_upload_numerology' => $store_product['product']['is_upload_numerology'],
  161. 'is_upload' => 0,
  162. 'report' => null,
  163. 'is_gather_annuity' => $store_product['product']['is_gather_annuity'],
  164. 'annuity' => $store_product['product']['annuity'],
  165. 'real_price' => $store_product['product']['real_price'],
  166. 'service_charge' => 0,
  167. 'reduce_price' => $store_product['activity'] ? $store_product['product']['origin_price'] - $store_product['product']['real_price'] : 0,
  168. 'reduce_type' => $store_product['activity'] ? $store_product['activity']['type'] : 0,
  169. 'sales_tax_rate' => $store_product['product']['sales_tax_rate'],
  170. 'sales_tax' => $store_product['product']['sales_tax'],
  171. 'transaction_price' => fixed2Float($store_product['product']['real_price'] + $store_product['product']['sales_tax'] + $store_product['product']['annuity']),
  172. 'zue_coin' => 0,
  173. 'create_time' => time(),
  174. 'update_time' => time(),
  175. ]);
  176. $product_amount += $store_product['product']['real_price'];
  177. $total_sales_tax += $store_product['product']['sales_tax'];
  178. if($store_product['product']['is_gather_annuity'] == 1) {
  179. $total_annual_fee += $store_product['product']['annuity'];
  180. $rental_amount += ($store_product['product']['real_price'] + $store_product['product']['sales_tax'] + $store_product['product']['annuity']);
  181. } else {
  182. $rental_amount += ($store_product['product']['real_price'] + $store_product['product']['sales_tax']);
  183. }
  184. }
  185. }
  186. $order = $this->orderModel->create([
  187. 'no' => $order_no,
  188. 'customer_id' => $customer->id,
  189. 'customer_name' => "{$customer->name_en}|{$customer->name_zh}",
  190. 'obj_names' => join(',',array_unique($product_names)),
  191. 'rental_amount' => $rental_amount,
  192. 'receivable_amount' => $rental_amount,
  193. 'receive_amount' => 0,
  194. 'imposed_amount' => $rental_amount,
  195. 'product_amount' => $product_amount,
  196. 'total_sales_tax' => $total_sales_tax,
  197. 'service_charge_amount' => 0,
  198. 'total_annual_fee' => $total_annual_fee,
  199. 'type' => 2,
  200. 'store_id' => $store->id,
  201. 'advisor_ids' => join(',', array_unique($advisor_ids)),
  202. 'create_time' => time(),
  203. 'update_time' => time()
  204. ]);
  205. foreach ($order_products as &$order_product) $order_product['order_id'] = $order->id;
  206. Db::startTrans();
  207. try {
  208. Db::table('erp_order_product')->insertAll($order_products);
  209. Db::commit();
  210. } catch (\Exception $e) {
  211. Db::rollback();
  212. Db::table('erp_order')->delete($order->id);
  213. return $this->fail(lang($e->getMessage()));
  214. }
  215. return $this->ok($order);
  216. }
  217. /**
  218. * @param $params
  219. * @param $channels
  220. * @return \SResult
  221. * @throws \app\exception\BaseException
  222. * @throws \think\db\exception\DataNotFoundException
  223. * @throws \think\db\exception\DbException
  224. * @throws \think\db\exception\ModelNotFoundException
  225. */
  226. public function payment($params, $channels) {
  227. $order = $this->orderModel->findById($params);
  228. if(!$order)
  229. return $this->fail(lang("Order does not exist"));
  230. if($order->type == 1)
  231. return $this->fail('订单状态为历史订单!不支持付款');
  232. // 客户
  233. $customer = $this->customerModel->findById($order->customer_id);
  234. if (!$customer)
  235. return $this->fail(lang("The Customer does not exist"));
  236. $pay_channels = $this->paymentChannelModel->where('is_delete', 0)->select()->toArray();
  237. $fmt_pay_channels = array_reduce($pay_channels, function ($result, $item) {
  238. $result[$item['id']] = $item;
  239. return $result;
  240. },[]);
  241. $credit_card_configs = $this->creditCardModel->findAll()->toArray();
  242. $fmt_credit_card_configs = array_reduce($credit_card_configs, function ($result, $item) {
  243. $result[$item['id']] = $item;
  244. return $result;
  245. },[]);
  246. // 本次总计支付费用
  247. $total_fee = 0;
  248. // 本次信用卡支付手续费
  249. $service_charge = 0;
  250. // 本次御龙币
  251. $zue_coin = 0;
  252. $order_payments = [];
  253. $record_channel_names = [];
  254. for ($i = 0; $i < count($channels); $i++) {
  255. $channel = $channels[$i];
  256. $fmt_pay_channel = $fmt_pay_channels[$channel->channel_id];
  257. if (!$fmt_pay_channel)
  258. return $this->fail("支付渠道错误!");
  259. array_push($record_channel_names, '['.$fmt_pay_channel['name'].']');
  260. $item = [
  261. 'order_id' => $order->id,
  262. 'channel_id' => $channel->channel_id,
  263. 'channel_name' => $fmt_pay_channel['name'],
  264. 'create_time' => time(),
  265. 'update_time' => time(),
  266. ];
  267. if ($fmt_pay_channel['type'] == 1) { // 正常支付
  268. predicate(isset($channel->fee) && $channel->fee > 0, '支付费用未填写');
  269. $item['fee'] = $channel->fee;
  270. $total_fee += $channel->fee;
  271. if ($fmt_pay_channel['is_upload_code']) {
  272. predicate(isset($channel->code),'必须上传付款编号');
  273. $item['code'] = $channel->code;
  274. }
  275. array_push($order_payments, $item);
  276. } else if($fmt_pay_channel['type'] == 2) { // 御龙币支付
  277. predicate(isset($channel->fee) && $channel->fee > 0, '支付费用未填写');
  278. $item['fee'] = $channel->fee;
  279. // TODO: 御龙币需求未明确
  280. array_push($order_payments, $item);
  281. $zue_coin += $channel->fee;
  282. } else {
  283. for ($j = 0; $j < count($channel->credit_card); $j++) {
  284. $credit_card = $channel->credit_card[$j];
  285. $fmt_credit_card_config = $fmt_credit_card_configs[$credit_card->credit_card_id];
  286. if (!$fmt_credit_card_config)
  287. return $this->fail("信用卡支付渠道错误!");
  288. predicate(isset($credit_card->fee) && $credit_card->fee > 0, '支付费用未填写');
  289. $total_fee += $credit_card->fee;
  290. $el = [
  291. 'order_id' => $order->id,
  292. 'channel_id' => $channel->channel_id,
  293. 'channel_name' => $fmt_pay_channel['name'],
  294. 'fee' => $credit_card->fee,
  295. 'credit_card_id' => $credit_card->credit_card_id,
  296. 'credit_card_name' => $fmt_credit_card_config['bank'],
  297. 'create_time' => time(),
  298. 'update_time' => time(),
  299. ];
  300. if ($fmt_pay_channel['is_upload_code']) {
  301. predicate(isset($credit_card->code),'必须填写付款编号');
  302. $el['code'] = $credit_card->code;
  303. }
  304. if ($fmt_credit_card_config['is_stage'] == 1) {
  305. predicate(isset($credit_card->stage_num),'必须选择分期数');
  306. $el['stage_num'] = $credit_card->stage_num;
  307. $config = [
  308. '6' => $fmt_credit_card_config['stage_6'],
  309. '9' => $fmt_credit_card_config['stage_9'],
  310. '12' => $fmt_credit_card_config['stage_12'],
  311. '24' => $fmt_credit_card_config['stage_24'],
  312. '36' => $fmt_credit_card_config['stage_36'],
  313. ];
  314. $now_config = $config[$credit_card->stage_num];
  315. predicate($now_config[0] == 1,'该分期未启用!');
  316. if ($now_config[1] > 0) { // 收取手续费
  317. $el['service_charge_rate'] = $now_config[1];
  318. $now_service_charge = $el['fee'] * ($now_config[1] / 100);
  319. $el['service_charge'] = $now_service_charge;
  320. $service_charge += $now_service_charge;
  321. }
  322. }
  323. array_push($order_payments, $el);
  324. }
  325. }
  326. }
  327. // 信用卡手续费
  328. $total_service_charge_amount = ($order->service_charge_amount + $service_charge);
  329. // 总共需要收取这么多费用; (商品的价格 + 商品税费 + 年费 + 信用卡手续费) - 御龙币抵扣的费用
  330. $imposed_amount = fixed2Float($order->product_amount + $order->total_sales_tax + $order->total_annual_fee + $total_service_charge_amount);
  331. $order_use_zue_coin = $order->zue_coin;
  332. $order_use_zue_coin_amount = $order->zue_coin_amount;
  333. $change_zue_coin_record = null;
  334. $zue_coin_model = $this->zueCoinModel->findByCustomerId($customer->id);
  335. if(!$zue_coin_model)
  336. return $this->fail("当前客户御龙币账户余额: 0");
  337. if ($zue_coin > $zue_coin_model->zue_coin)
  338. return $this->fail("当前客户御龙币账户余额:{$zue_coin_model->zue_coin}");
  339. $zue_coin_config = $fmt_pay_channels['11'];
  340. if(!$zue_coin_config)
  341. return $this->fail("御龙币设置不存在!");
  342. $zue_coin_exchange_rate = $zue_coin_config['zue_coin_exchange_rate'] ?? 0; // 兑换比例
  343. $zue_coin_consume_rate = $zue_coin_config['zue_coin_consume_rate'] ?? 0; // 报销比例
  344. if($zue_coin > 0) {
  345. if($zue_coin_exchange_rate == 0 || $zue_coin_consume_rate == 0) {
  346. return $this->fail("该笔订单不支持御龙币支付");
  347. }
  348. // 1.计算出该订单能使用多少御龙币
  349. // 2.结合之前已使用的御龙币 算出还能使用多少御龙币
  350. // 3.判断当前御龙币是否符合兑换数额
  351. // 4.进行扣除并记录
  352. // 根据御龙币的设置 总共能报销这么多钱
  353. $max_consume_amount = fixed2Float($imposed_amount * ($zue_coin_consume_rate / 100));
  354. // 根据御龙币的设置 最大的报销的御龙币
  355. $max_consume_zue_coin = fixed2Float($max_consume_amount / $zue_coin_exchange_rate);
  356. if ($max_consume_zue_coin - ($order->zue_coin + $zue_coin) < 0) {
  357. return $this->fail("最多能使用御龙币: {$max_consume_zue_coin}, 当前已使用{$order->zue_coin}");
  358. }
  359. // 根据当前订单支付情况 得出现在最大的报销金额;
  360. $now_max_consume_amount = $order->imposed_amount < $max_consume_amount ? $order->imposed_amount : $max_consume_amount;
  361. // 当前最多还能使用多少御龙币
  362. $now_can_consume_zue_coin = fixed2Float($now_max_consume_amount / $zue_coin_exchange_rate);
  363. // 判断当前还能使用
  364. if ($now_can_consume_zue_coin - $zue_coin < 0)
  365. return $this->fail("当前剩余可使用的: {$now_can_consume_zue_coin}");
  366. // 总共使用了这么多御龙币
  367. $order_use_zue_coin += $zue_coin;
  368. // 总共兑换了这么多钱
  369. $order_use_zue_coin_amount = fixed2Float($order_use_zue_coin * $zue_coin_exchange_rate);
  370. $change_zue_coin_record = [
  371. 'zue_coin_id' => $zue_coin_model->id,
  372. 'origin' => $zue_coin_model->zue_coin,
  373. 'change' => $zue_coin,
  374. 'after' => $zue_coin_model->zue_coin - $zue_coin,
  375. 'reason' => 1,
  376. 'create_time' => time(),
  377. 'update_time' => time(),
  378. ];
  379. }
  380. // 总计费用 - 御龙币抵消费用;
  381. $imposed_amount -= $order_use_zue_coin_amount;
  382. // 总计实收金额
  383. $receive_amount = fixed2Float($order->receive_amount + $total_fee);
  384. if (round($receive_amount) > round($imposed_amount)) return $this->fail("实收金额大于待收金额! 当前已付款: {$order->receive_amount} / {$order->receivable_amount} (商品总价:{$order->product_amount} + 商品总消费税:{$order->total_sales_tax} + 第一年年费:{$order->total_annual_fee} + 信用卡总手续费:{$order->service_charge_amount})");
  385. $order_annual_fees = [];
  386. $update_store_products = [];
  387. $update_order_products = [];
  388. if (round($receive_amount) == round($imposed_amount)) { // 减库存
  389. $order_products = $this->orderProductModel->findByOrderId($order->id)->toArray();
  390. $store_products = $this->storeProductModel->findByIds(array_map(function ($r) {return $r['store_product_id'];}, $order_products))->toArray();
  391. $fmt_store_products = array_reduce($store_products, function ($result, $item) {
  392. $result[$item['id']] = $item;
  393. return $result;
  394. },[]);
  395. // 商品本身的价格 | 年费 | 消费税
  396. $total_ = $order->product_amount + $order->total_annual_fee + $order->total_sales_tax;
  397. // 信用卡手续费 每一块钱所占的比例
  398. $item_service_charge_rate = ($order->service_charge_amount + $service_charge) / $total_;
  399. // 每一个御龙币所占的比例
  400. $item_zue_coin_rate = $order_use_zue_coin / $total_;
  401. foreach ($order_products as $order_product) {
  402. predicate($fmt_store_products[$order_product['store_product_id']]['now_stock'] > 0, lang('inventory shortage'));
  403. $fmt_store_products[$order_product['store_product_id']]['now_stock'] -= 1;
  404. if (isset($update_store_products[$order_product['store_product_id']])) {
  405. $update_store_products[$order_product['store_product_id']]['reduce_num'] += 1;
  406. } else {
  407. $update_store_products[$order_product['store_product_id']] = ['id' => $order_product['store_product_id'], 'reduce_num' => 1];
  408. }
  409. if ($order_product['is_gather_annuity']) {
  410. array_push($order_annual_fees, [
  411. 'order_id' => $order->id,
  412. 'customer_id' => $customer->id,
  413. 'customer_name' => "{$customer->name_en}|{$customer->name_zh}",
  414. 'customer_mobile' => $customer->mobile,
  415. 'customer_create_username' => $customer->create_username,
  416. 'index' => 1,
  417. 'order_product_id' => $order_product['id'],
  418. 'order_product_name' => $order_product['product_name'],
  419. 'fee' => $order_product['annuity'],
  420. 'is_pay' => 1,
  421. 'start_time' => time(),
  422. 'end_time' => time() + (365 * 24 * 60 * 60),
  423. 'order_create_time' => strtotime($order->create_time),
  424. 'adviser_1_id' => $order_product['adviser_1_id'],
  425. 'store_id' => $order->store_id,
  426. 'create_time' => time(),
  427. 'update_time' => time()
  428. ]);
  429. }
  430. $now = $order_product['real_price'] + $order_product['annuity'] + $order_product['sales_tax'];
  431. $item_service_charge = fixed2Float($now * $item_service_charge_rate);
  432. $item_zue_coin = fixed2Float($now * $item_zue_coin_rate);
  433. $transaction_price = fixed2Float($now + $item_service_charge - ($item_zue_coin * $zue_coin_exchange_rate));
  434. array_push($update_order_products, [
  435. 'id' => $order_product['id'],
  436. 'service_charge' => $item_service_charge,
  437. 'zue_coin' => $item_zue_coin,
  438. 'transaction_price' => $transaction_price,
  439. 'is_pay' => 1
  440. ]);
  441. }
  442. }
  443. Db::startTrans();
  444. try {
  445. $update_order = [
  446. 'rental_amount' => $imposed_amount + $order_use_zue_coin_amount,
  447. 'receivable_amount' => $imposed_amount,
  448. 'receive_amount' => $receive_amount,
  449. 'imposed_amount' => $imposed_amount - $receive_amount,
  450. 'service_charge_amount' => $order->service_charge_amount + $service_charge,
  451. 'zue_coin' => $order_use_zue_coin,
  452. 'zue_coin_amount' => $order_use_zue_coin_amount,
  453. 'remarks' => $params['remarks']
  454. ];
  455. if (round($receive_amount) == round($imposed_amount)) { // 支付满了
  456. $update_order['type'] = 1;
  457. if(count($update_order_products) > 0) {
  458. foreach ($update_order_products as $item) {
  459. Db::table('erp_order_product')->where('id', $item['id'])->update($item);
  460. }
  461. }
  462. if(count($order_annual_fees) > 0) {
  463. Db::table('erp_order_annual_fee')->insertAll($order_annual_fees);
  464. }
  465. if(count($update_store_products) > 0) {
  466. foreach ($update_store_products as $update) {
  467. Db::table('erp_store_product')->where('id', $update['id'])->dec('now_stock',1)->update();
  468. Db::table('erp_store_product')->where('id', $update['id'])->inc('sale_stock',1)->update();
  469. }
  470. }
  471. }
  472. Db::table('erp_order_proceeds')->save([
  473. 'order_id' => $order->id,
  474. 'channels' => join(' ',$record_channel_names),
  475. 'fee' => $total_fee,
  476. 'admin_id' => $params['admin_id'],
  477. 'admin_name' => $params['admin_name'],
  478. 'create_time' => time(),
  479. 'update_time' => time(),
  480. ]);
  481. if ($zue_coin > 0 && $change_zue_coin_record != null) {
  482. Db::table('erp_zue_coin_record')->save($change_zue_coin_record);
  483. Db::table('erp_customer_zue_coin')->where('id', $change_zue_coin_record['zue_coin_id'])->dec('zue_coin', $zue_coin)->update();
  484. }
  485. if(count($order_payments) > 0) {
  486. Db::table('erp_order_payment')->insertAll(array_map(function ($data) {
  487. return [
  488. "order_id" => isset($data['order_id']) ? $data['order_id'] : null,
  489. "channel_id" => isset($data['channel_id']) ? $data['channel_id'] : null,
  490. "channel_name" => isset($data['channel_name']) ? $data['channel_name']: null,
  491. "fee" => isset($data['fee']) ? $data['fee'] : null,
  492. "credit_card_id" => isset($data['credit_card_id']) ? $data['credit_card_id'] : null,
  493. "credit_card_name" => isset($data['credit_card_name']) ? $data['credit_card_name'] : null,
  494. "create_time" => isset($data['create_time']) ? $data['create_time'] : null,
  495. "update_time" => isset($data['update_time']) ? $data['update_time'] : null,
  496. "code" => isset($data['code']) ? $data['code'] : null,
  497. "stage_num" => isset($data['stage_num']) ? $data['stage_num'] : null,
  498. "service_charge_rate" => isset($data['service_charge_rate']) ? $data['service_charge_rate'] : null,
  499. "service_charge" => isset($data['service_charge']) ? $data['service_charge'] : null
  500. ];
  501. }, $order_payments));
  502. }
  503. Db::table('erp_order')->where('id', $order->id)->update($update_order);
  504. Db::commit();
  505. } catch (\Exception $e) {
  506. Db::rollback();
  507. return $this->fail(lang($e->getMessage()));
  508. }
  509. return $this->ok(true);
  510. }
  511. /**
  512. * @param $params
  513. * @return array
  514. * @throws \think\db\exception\DbException
  515. */
  516. public function fetch($params) {
  517. $verify = AuthService::verify($params['admin_id'],$params['type'] == 1 ? 10003 : 10004);
  518. $res = $this->orderModel->search($params, $verify);
  519. $items = $res['data'];
  520. return [array_map(function ($item) {
  521. return [
  522. "id" => $item['id'],
  523. "no" => $item['no'],
  524. "customer_id" => $item['customer_id'],
  525. "customer_name" => $item['customer_name'],
  526. "obj_names" => $item['obj_names'],
  527. "rental_amount" => $item['rental_amount'],
  528. "receivable_amount" => $item['receivable_amount'],
  529. "receive_amount" => $item['receive_amount'],
  530. "imposed_amount" => $item['imposed_amount'],
  531. "product_amount" => $item['product_amount'],
  532. "total_sales_tax" => $item['total_sales_tax'],
  533. "service_charge_amount" => $item['service_charge_amount'],
  534. "total_annual_fee" => $item['total_annual_fee'],
  535. "zue_coin" => $item['zue_coin'],
  536. "zue_coin_amount" => $item['zue_coin_amount'],
  537. "type" => $item['type'],
  538. "store_id" => $item['store_id'],
  539. "advisor_ids" => $item['advisor_ids'],
  540. "remarks" => $item['remarks'],
  541. "create_time" => $item['create_time'],
  542. "advisers" => join('/',array_unique(array_reduce($item['products'], function ($result, $item) {
  543. array_push($result, $item['adviser_1_name']);
  544. if($item['adviser_2_id'] > 0)
  545. array_push($result, $item['adviser_2_name']);
  546. return $result;
  547. }, []))),
  548. "teachers" => join('/', array_unique(array_reduce($item['products'], function ($result, $item) {
  549. if($item['teacher_1_id'] > 0)
  550. array_push($result, $item['teacher_1_name']);
  551. if($item['teacher_2_id'] > 0)
  552. array_push($result, $item['teacher_2_name']);
  553. return $result;
  554. }, []))),
  555. "payments" => join(' ', array_unique(array_reduce($item['payments'], function ($result, $item) {
  556. array_push($result, '['.$item['channel_name'].']');
  557. return $result;
  558. }, []))),
  559. "stage_num" => array_reduce($item['payments'], function ($result, $item) {
  560. if($item['stage_num'] && $item['stage_num'] > $result) {
  561. $result = $item['stage_num'];
  562. }
  563. return $result;
  564. }, 0),
  565. 'is_need_upload' => $item['type'] == 1 && in_array(true, array_map(function ($product) {
  566. return $product['is_upload_numerology'] == 1 && $product['is_upload'] == 0;
  567. }, $item['products'])),
  568. ];
  569. }, $items), $res['total']];
  570. }
  571. /**
  572. * @param $params
  573. * @return array
  574. * @throws \think\db\exception\DbException
  575. */
  576. public function fetchByCustomerId($params) {
  577. $res = $this->orderModel->fetchByCustomerId($params['customer_id'], $params['page'] ?? 1, $params['size'] ?? 20);
  578. $items = $res['data'];
  579. return [array_map(function ($item) {
  580. return [
  581. "id" => $item['id'],
  582. "no" => $item['no'],
  583. "customer_id" => $item['customer_id'],
  584. "customer_name" => $item['customer_name'],
  585. "obj_names" => $item['obj_names'],
  586. "rental_amount" => $item['rental_amount'],
  587. "receivable_amount" => $item['receivable_amount'],
  588. "receive_amount" => $item['receive_amount'],
  589. "imposed_amount" => $item['imposed_amount'],
  590. "product_amount" => $item['product_amount'],
  591. "total_sales_tax" => $item['total_sales_tax'],
  592. "service_charge_amount" => $item['service_charge_amount'],
  593. "total_annual_fee" => $item['total_annual_fee'],
  594. "zue_coin" => $item['zue_coin'],
  595. "zue_coin_amount" => $item['zue_coin_amount'],
  596. "type" => $item['type'],
  597. "store_id" => $item['store_id'],
  598. "advisor_ids" => $item['advisor_ids'],
  599. "remarks" => $item['remarks'],
  600. "create_time" => $item['create_time'],
  601. "advisers" => join('/',array_unique(array_reduce($item['products'], function ($result, $item) {
  602. array_push($result, $item['adviser_1_name']);
  603. if($item['adviser_2_id'] > 0)
  604. array_push($result, $item['adviser_2_name']);
  605. return $result;
  606. }, []))),
  607. "teachers" => join('/', array_unique(array_reduce($item['products'], function ($result, $item) {
  608. if($item['teacher_1_id'] > 0)
  609. array_push($result, $item['teacher_1_name']);
  610. if($item['teacher_2_id'] > 0)
  611. array_push($result, $item['teacher_2_name']);
  612. return $result;
  613. }, []))),
  614. "stage_num" => array_reduce($item['payments'], function ($result, $item) {
  615. if($item['stage_num'] && $item['stage_num'] > $result) {
  616. $result = $item['stage_num'];
  617. }
  618. return $result;
  619. }, 0),
  620. 'is_need_upload' => $item['type'] == 1 && in_array(true, array_map(function ($product) {
  621. return $product['is_upload_numerology'] == 1 && $product['is_upload'] == 0;
  622. }, $item['products'])),
  623. ];
  624. }, $items), $res['total']];
  625. }
  626. public function fetchOrderProducts($order_id, $page = 1, $size = 10) {
  627. $res = $this->orderProductModel->fetchByOrderId($order_id, $page, $size);
  628. return [$res->items(),$res->total()];
  629. }
  630. public function upload_numerology($order_product_id, $report) {
  631. $order_product = $this->orderProductModel->findById($order_product_id);
  632. if (!$order_product) return $this->fail('订单商品不存在,无法上传命理报告!');
  633. if (!$order_product->is_pay) return $this->fail('订单未支付,无法上传商品');
  634. $order_product->is_upload = 1;
  635. $order_product->report = $report;
  636. $order_product->save();
  637. return $this->ok($order_product);
  638. }
  639. public function fetchWaitGatherAnnualFee($admin_id, $text = null, $start_time = null, $end_time = null, $page = 1, $size = 10) {
  640. $res = $this->orderAnnualFeeModel->fetchByAdviser($admin_id, $text, $start_time, $end_time, $page, $size);
  641. return [$res->items(),$res->total()];
  642. }
  643. public function paymentAnnualFee($annual_fee_id) {
  644. $annual_fee = $this->orderAnnualFeeModel->findById($annual_fee_id);
  645. if(!$annual_fee_id) {
  646. return $this->fail('年费记录不存在!');
  647. }
  648. if($annual_fee->is_pay == 1)
  649. return $this->fail('该条年费记录已经支付!');
  650. $annual_fee->is_pay = 1;
  651. $annual_fee->update_time = time();
  652. $annual_fee->save();
  653. return $this->ok($annual_fee);
  654. }
  655. public function fetchOrderByReturn($admin_id, $store_id, $no = null, $customer_name = null, $page = 1, $size = 10) {
  656. $verify = AuthService::verify($admin_id, 10005);
  657. $res = $this->orderModel->fetchOrderByReturn($admin_id, $store_id, $no, $customer_name, $page, $size, $verify);
  658. return [$res->items(),$res->total()];
  659. }
  660. /**
  661. * @param $admin_id
  662. * @param $order_id
  663. * @param array $order_product_ids
  664. * @return \SResult
  665. * @throws \think\db\exception\DataNotFoundException
  666. * @throws \think\db\exception\DbException
  667. * @throws \think\db\exception\ModelNotFoundException
  668. */
  669. public function returnOrderProduct($admin_id, $order_id, array $order_product_ids) {
  670. // $verify = AuthService::verify($admin_id, 10005);
  671. $order = $this->orderModel->findById($order_id);
  672. if (!$order) return $this->fail(lang("Order does not exist"));
  673. $return_order_products = $this->orderProductModel->findByIds($order_product_ids)->toArray();
  674. if (count($order_product_ids) != count($return_order_products)) return $this->fail(lang("The order item was incorrectly selected"));
  675. $all_order_products = $this->orderProductModel->findByOrderId($order->id)->toArray();
  676. Db::startTrans();
  677. try {
  678. if(count($return_order_products) == count($all_order_products)) {
  679. Db::table('erp_order')->where('id', $order->id)->update(['is_delete' => 1]);
  680. Db::table('erp_order_product')->where('order_id', $order->id)->update(['is_delete' => 1]);
  681. Db::table('erp_order')->where('id', $order->id)->update(['is_delete' => 1]);
  682. } else {
  683. foreach ($return_order_products as $return_order_product) {
  684. // $return_order_product['']
  685. }
  686. }
  687. Db::commit();
  688. } catch (\Exception $e) {
  689. Db::rollback();
  690. return $this->fail(lang($e->getMessage()));
  691. }
  692. return $this->ok(true);
  693. }
  694. public function findByOrderNo($admin_id, $order_no) {
  695. $order = $this->orderModel->findByOrderNo($admin_id, $order_no);
  696. if(!$order)
  697. return $this->fail(lang("Order does not exist"));
  698. return $this->ok($order);
  699. }
  700. public function exchange($admin_id, $order_id, $origin_order_product_ids, $append_product_ids) {
  701. return $this->ok(true);
  702. }
  703. }