OrderService.php 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  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 app\common\model\ZueCoinRecordModel;
  19. use app\exception\BaseException;
  20. use think\facade\Db;
  21. class OrderService extends \app\BaseService
  22. {
  23. private $storeModel;
  24. private $orderModel;
  25. private $productModel;
  26. private $orderAnnualFeeModel;
  27. private $orderPaymentModel;
  28. private $orderProductModel;
  29. private $orderProceedsModel;
  30. private $activityProductModel;
  31. private $storeProductModel;
  32. private $configModel;
  33. private $adminModel;
  34. private $customerModel;
  35. private $paymentChannelModel;
  36. private $creditCardModel;
  37. private $zueCoinModel;
  38. private $zueCoinRecordModel;
  39. public function __construct()
  40. {
  41. $this->storeModel = new StoreModel();
  42. $this->orderModel = new OrderModel();
  43. $this->productModel = new ProductModel();
  44. $this->configModel = new ConfigModel();
  45. $this->storeProductModel = new StoreProductModel();
  46. $this->orderAnnualFeeModel = new OrderAnnualFeeModel();
  47. $this->orderPaymentModel = new OrderPaymentModel();
  48. $this->orderProductModel = new OrderProductModel();
  49. $this->orderProceedsModel = new OrderProceedsModel();
  50. $this->activityProductModel = new ActivityProductModel();
  51. $this->adminModel = new AdminModel();
  52. $this->customerModel = new CustomerModel();
  53. $this->paymentChannelModel = new PaymentChannelModel();
  54. $this->creditCardModel = new CreditCardConfigModel();
  55. $this->zueCoinModel = new CustomerZueCoinModel();
  56. $this->zueCoinRecordModel = new ZueCoinRecordModel();
  57. }
  58. /**
  59. * @param $params
  60. * @param array $store_products_params
  61. * @return \SResult
  62. * @throws \think\db\exception\DataNotFoundException
  63. * @throws \think\db\exception\DbException
  64. * @throws \think\db\exception\ModelNotFoundException
  65. */
  66. public function create($params, array $store_products_params)
  67. {
  68. // 客户
  69. $customer = $this->customerModel->findById($params['customer_id']);
  70. if (!$customer)
  71. return $this->fail(lang("The Customer does not exist"));
  72. // 门店
  73. $store = $this->storeModel->findById($params['store_id']);
  74. if (!$store)
  75. return $this->fail(lang("The store does not exist"));
  76. // 顾问 or 老师 ids
  77. $user_ids = [];
  78. // 门店商品ids
  79. $store_product_ids = [];
  80. for ($i = 0; $i < count($store_products_params); $i++) {
  81. $store_products_param = $store_products_params[$i];
  82. $ids = [];
  83. if (isset($store_products_param->adviser_1_id)) array_push($ids, $store_products_param->adviser_1_id);
  84. if (isset($store_products_param->adviser_2_id)) array_push($ids, $store_products_param->adviser_2_id);
  85. if (isset($store_products_param->teacher_1_id)) array_push($ids, $store_products_param->teacher_1_id);
  86. if (isset($store_products_param->teacher_2_id)) array_push($ids, $store_products_param->teacher_2_id);
  87. $user_ids = array_unique(array_merge($user_ids, $ids));
  88. array_push($store_product_ids, $store_products_param->store_product_id);
  89. }
  90. // Adviser|Teacher
  91. $users = $this->adminModel->findByIds($user_ids)->toArray();
  92. if (count($users) != count($user_ids))
  93. return $this->fail(lang("The Adviser|Teacher does not exist"));
  94. $fmt_users = array_reduce($users, function ($result, $item) {
  95. $result[$item['id']] = $item;
  96. return $result;
  97. }, []);
  98. // 门店商品
  99. $store_products = $this->storeProductModel->fetchRelationsByOrder($store_product_ids)->toArray();
  100. if (count($store_products) != count($store_product_ids))
  101. return $this->fail(lang("The Product does not exist"));
  102. // 商品信息
  103. $products = array_map(function ($p) {
  104. return $p['product'] ? $p['product'] : null;
  105. }, $store_products);
  106. if (in_array(null, $products))
  107. return $this->fail(lang("The Product does not exist"));
  108. $config = $this->configModel->findConfig();
  109. $activityProducts = $this->activityProductModel->fetchByProductIds(array_map(function ($data) {
  110. return $data['id'];
  111. }, $products))->toArray();
  112. $fmt_store_products = [];
  113. foreach ($store_products as &$item) {
  114. $aProducts = array_filter($activityProducts, function ($aProduct) use ($item) {
  115. return $aProduct['product_id'] == $item['product_id'];
  116. });
  117. $res = compare($item['product']['real_price'] ?? 0, $aProducts);
  118. $item['activity'] = $res['item'];
  119. $item['product']['origin_price'] = $item['product']['real_price'];
  120. $item['product']['real_price'] = fixed2Float($res['min_num'] > 0 ? $res['min_num'] : 0);
  121. $sales_tax_rate = $item['product']['sales_tax_rate'] > 0 ? $item['product']['sales_tax_rate'] : $config->sales_tax_rate;
  122. $sales_tax = fixed2Float($sales_tax_rate > 0 && $item['product']['real_price'] > 0 ? ($item['product']['real_price'] * ($sales_tax_rate / 100)) : 0);
  123. $item['product']['sales_tax_rate'] = $sales_tax_rate;
  124. $item['product']['sales_tax'] = $sales_tax;
  125. $fmt_store_products[$item['id']] = $item;
  126. }
  127. $order_products = [];
  128. //项目总额
  129. $rental_amount = 0;
  130. $product_amount = 0;
  131. // 总消费税
  132. $total_sales_tax = 0;
  133. $advisor_ids = [];
  134. $product_names = [];
  135. $total_annual_fee = 0;
  136. $order_no = $this->orderModel->genOrderNo($store->id, $store->abbr);
  137. for ($i = 0; $i < count($store_products_params); $i++) {
  138. $store_products_param = $store_products_params[$i];
  139. $store_product = $fmt_store_products[$store_products_param->store_product_id];
  140. if ($store_product['now_stock'] < $store_products_param->quantity)
  141. return $this->fail(lang("inventory shortage"));
  142. array_push($advisor_ids, $store_products_param->adviser_1_id);
  143. if (isset($store_products_param->adviser_2_id)) {
  144. array_push($advisor_ids, $store_products_param->adviser_2_id);
  145. }
  146. for ($j = 0; $j < $store_products_param->quantity; $j++) {
  147. array_push($product_names, $store_product['product']['name']);
  148. array_push($order_products, [
  149. 'order_id' => 0,
  150. 'order_no' => $order_no,
  151. 'customer_id' => $customer->id,
  152. 'product_id' => $store_product['product']['id'],
  153. 'product_category_id' => $store_product['product']['category_id'],
  154. 'is_serve' => $store_product['product']['is_serve'],
  155. 'store_product_id' => $store_product['id'],
  156. 'product_name' => $store_product['product']['name'],
  157. 'adviser_1_id' => isset($store_products_param->adviser_1_id) ? $store_products_param->adviser_1_id : null,
  158. 'adviser_1_name' => isset($store_products_param->adviser_1_id) ? $fmt_users[$store_products_param->adviser_1_id]['nickname'] : null,
  159. 'adviser_2_id' => isset($store_products_param->adviser_2_id) ? $store_products_param->adviser_2_id : null,
  160. 'adviser_2_name' => isset($store_products_param->adviser_2_id) ? $fmt_users[$store_products_param->adviser_2_id]['nickname'] : null,
  161. 'teacher_1_id' => isset($store_products_param->teacher_1_id) ? $store_products_param->teacher_1_id : null,
  162. 'teacher_1_name' => isset($store_products_param->teacher_1_id) ? $fmt_users[$store_products_param->teacher_1_id]['nickname'] : null,
  163. 'teacher_2_id' => isset($store_products_param->teacher_2_id) ? $store_products_param->teacher_2_id : null,
  164. 'teacher_2_name' => isset($store_products_param->teacher_2_id) ? $fmt_users[$store_products_param->teacher_2_id]['nickname'] : null,
  165. 'is_upload_numerology' => $store_product['product']['is_upload_numerology'],
  166. 'is_upload' => 0,
  167. 'report' => null,
  168. 'is_gather_annuity' => $store_product['product']['is_gather_annuity'],
  169. 'annuity' => $store_product['product']['annuity'],
  170. 'real_price' => $store_product['product']['real_price'],
  171. 'service_charge' => 0,
  172. 'reduce_price' => $store_product['activity'] ? $store_product['product']['origin_price'] - $store_product['product']['real_price'] : 0,
  173. 'reduce_type' => $store_product['activity'] ? $store_product['activity']['type'] : 0,
  174. 'sales_tax_rate' => $store_product['product']['sales_tax_rate'],
  175. 'sales_tax' => $store_product['product']['sales_tax'],
  176. 'transaction_price' => fixed2Float($store_product['product']['real_price'] + $store_product['product']['sales_tax'] + $store_product['product']['annuity']),
  177. 'zue_coin' => 0,
  178. 'create_time' => time(),
  179. 'update_time' => time(),
  180. ]);
  181. $product_amount += $store_product['product']['real_price'];
  182. $total_sales_tax += $store_product['product']['sales_tax'];
  183. if ($store_product['product']['is_gather_annuity'] == 1) {
  184. $total_annual_fee += $store_product['product']['annuity'];
  185. $rental_amount += ($store_product['product']['real_price'] + $store_product['product']['sales_tax'] + $store_product['product']['annuity']);
  186. } else {
  187. $rental_amount += ($store_product['product']['real_price'] + $store_product['product']['sales_tax']);
  188. }
  189. }
  190. }
  191. $order = $this->orderModel->create([
  192. 'no' => $order_no,
  193. 'customer_id' => $customer->id,
  194. 'customer_name' => "{$customer->name_en}|{$customer->name_zh}",
  195. 'obj_names' => join(',', array_unique($product_names)),
  196. 'rental_amount' => $rental_amount,
  197. 'receivable_amount' => $rental_amount,
  198. 'receive_amount' => 0,
  199. 'imposed_amount' => $rental_amount,
  200. 'product_amount' => $product_amount,
  201. 'total_sales_tax' => $total_sales_tax,
  202. 'service_charge_amount' => 0,
  203. 'total_annual_fee' => $total_annual_fee,
  204. 'type' => 2,
  205. 'store_id' => $store->id,
  206. 'advisor_ids' => join(',', array_unique($advisor_ids)),
  207. 'create_time' => time(),
  208. 'update_time' => time()
  209. ]);
  210. foreach ($order_products as &$order_product) $order_product['order_id'] = $order->id;
  211. Db::startTrans();
  212. try {
  213. Db::table('erp_order_product')->insertAll($order_products);
  214. Db::commit();
  215. } catch (\Exception $e) {
  216. Db::rollback();
  217. Db::table('erp_order')->delete($order->id);
  218. return $this->fail(lang($e->getMessage()));
  219. }
  220. return $this->ok($order);
  221. }
  222. /**
  223. * @param $params
  224. * @param $channels
  225. * @return \SResult
  226. * @throws \app\exception\BaseException
  227. * @throws \think\db\exception\DataNotFoundException
  228. * @throws \think\db\exception\DbException
  229. * @throws \think\db\exception\ModelNotFoundException
  230. */
  231. public function payment($params, $channels)
  232. {
  233. $order = $this->orderModel->findById($params['order_id']);
  234. if (!$order)
  235. return $this->fail(lang("Order does not exist"));
  236. if ($order->type == 1)
  237. return $this->fail('订单状态为历史订单!不支持付款');
  238. // 客户
  239. $customer = $this->customerModel->findById($order->customer_id);
  240. if (!$customer)
  241. return $this->fail(lang("The Customer does not exist"));
  242. $pay_channels = $this->paymentChannelModel->where('is_delete', 0)->select()->toArray();
  243. $fmt_pay_channels = array_reduce($pay_channels, function ($result, $item) {
  244. $result[$item['id']] = $item;
  245. return $result;
  246. }, []);
  247. $credit_card_configs = $this->creditCardModel->findAll()->toArray();
  248. $fmt_credit_card_configs = array_reduce($credit_card_configs, function ($result, $item) {
  249. $result[$item['id']] = $item;
  250. return $result;
  251. }, []);
  252. // 本次总计支付费用
  253. $total_fee = 0;
  254. // 本次信用卡支付手续费
  255. $service_charge = 0;
  256. // 本次御龙币
  257. $zue_coin = 0;
  258. $order_payments = [];
  259. $record_channel_names = [];
  260. for ($i = 0; $i < count($channels); $i++) {
  261. $channel = $channels[$i];
  262. $fmt_pay_channel = $fmt_pay_channels[$channel->channel_id];
  263. if (!$fmt_pay_channel)
  264. return $this->fail("支付渠道错误!");
  265. array_push($record_channel_names, '[' . $fmt_pay_channel['name'] . ']');
  266. $item = [
  267. 'order_id' => $order->id,
  268. 'channel_id' => $channel->channel_id,
  269. 'channel_name' => $fmt_pay_channel['name'],
  270. 'create_time' => time(),
  271. 'update_time' => time(),
  272. ];
  273. if ($fmt_pay_channel['type'] == 1) { // 正常支付
  274. predicate(isset($channel->fee) && $channel->fee > 0, '支付费用未填写');
  275. $item['fee'] = $channel->fee;
  276. $total_fee += $channel->fee;
  277. if ($fmt_pay_channel['is_upload_code']) {
  278. predicate(isset($channel->code), '必须上传付款编号');
  279. $item['code'] = $channel->code;
  280. }
  281. array_push($order_payments, $item);
  282. } else if ($fmt_pay_channel['type'] == 2) { // 御龙币支付
  283. predicate(isset($channel->fee) && $channel->fee > 0, '支付费用未填写');
  284. $item['fee'] = $channel->fee;
  285. // TODO: 御龙币需求未明确
  286. array_push($order_payments, $item);
  287. $zue_coin += $channel->fee;
  288. } else {
  289. for ($j = 0; $j < count($channel->credit_card); $j++) {
  290. $credit_card = $channel->credit_card[$j];
  291. $fmt_credit_card_config = $fmt_credit_card_configs[$credit_card->credit_card_id];
  292. if (!$fmt_credit_card_config)
  293. return $this->fail("信用卡支付渠道错误!");
  294. predicate(isset($credit_card->fee) && $credit_card->fee > 0, '支付费用未填写');
  295. $total_fee += $credit_card->fee;
  296. $el = [
  297. 'order_id' => $order->id,
  298. 'channel_id' => $channel->channel_id,
  299. 'channel_name' => $fmt_pay_channel['name'],
  300. 'fee' => $credit_card->fee,
  301. 'credit_card_id' => $credit_card->credit_card_id,
  302. 'credit_card_name' => $fmt_credit_card_config['bank'],
  303. 'create_time' => time(),
  304. 'update_time' => time(),
  305. ];
  306. if ($fmt_pay_channel['is_upload_code']) {
  307. predicate(isset($credit_card->code), '必须填写付款编号');
  308. $el['code'] = $credit_card->code;
  309. }
  310. if ($fmt_credit_card_config['is_stage'] == 1) {
  311. predicate(isset($credit_card->stage_num), '必须选择分期数');
  312. $el['stage_num'] = $credit_card->stage_num;
  313. $config = [
  314. '6' => $fmt_credit_card_config['stage_6'],
  315. '9' => $fmt_credit_card_config['stage_9'],
  316. '12' => $fmt_credit_card_config['stage_12'],
  317. '24' => $fmt_credit_card_config['stage_24'],
  318. '36' => $fmt_credit_card_config['stage_36'],
  319. ];
  320. $now_config = $config[$credit_card->stage_num];
  321. predicate($now_config[0] == 1, '该分期未启用!');
  322. if ($now_config[1] > 0) { // 收取手续费
  323. $el['service_charge_rate'] = $now_config[1];
  324. $now_service_charge = $el['fee'] * ($now_config[1] / 100);
  325. $el['service_charge'] = $now_service_charge;
  326. $service_charge += $now_service_charge;
  327. }
  328. }
  329. array_push($order_payments, $el);
  330. }
  331. }
  332. }
  333. // 信用卡手续费
  334. $total_service_charge_amount = ($order->service_charge_amount + $service_charge);
  335. // 总共需要收取这么多费用; (商品的价格 + 商品税费 + 年费 + 信用卡手续费) - 御龙币抵扣的费用
  336. $imposed_amount = fixed2Float($order->product_amount + $order->total_sales_tax + $order->total_annual_fee + $total_service_charge_amount);
  337. $order_use_zue_coin = $order->zue_coin;
  338. $order_use_zue_coin_amount = $order->zue_coin_amount;
  339. $change_zue_coin_record = null;
  340. $zue_coin_model = $this->zueCoinModel->findByCustomerId($customer->id);
  341. $zue_coin_exchange_rate = 0;
  342. if ($zue_coin > 0) {
  343. if (!$zue_coin_model)
  344. return $this->fail("当前客户御龙币账户余额: 0");
  345. if ($zue_coin > $zue_coin_model->zue_coin)
  346. return $this->fail("当前客户御龙币账户余额:{$zue_coin_model->zue_coin}");
  347. $zue_coin_config = $fmt_pay_channels['11'];
  348. if (!$zue_coin_config)
  349. return $this->fail("御龙币设置不存在!");
  350. $zue_coin_exchange_rate = $zue_coin_config['zue_coin_exchange_rate'] ?? 0; // 兑换比例
  351. $zue_coin_consume_rate = $zue_coin_config['zue_coin_consume_rate'] ?? 0; // 报销比例
  352. if ($zue_coin_exchange_rate == 0 || $zue_coin_consume_rate == 0) {
  353. return $this->fail("该笔订单不支持御龙币支付");
  354. }
  355. // 1.计算出该订单能使用多少御龙币
  356. // 2.结合之前已使用的御龙币 算出还能使用多少御龙币
  357. // 3.判断当前御龙币是否符合兑换数额
  358. // 4.进行扣除并记录
  359. // 根据御龙币的设置 总共能报销这么多钱
  360. $max_consume_amount = fixed2Float($imposed_amount * ($zue_coin_consume_rate / 100));
  361. // 根据御龙币的设置 最大的报销的御龙币
  362. $max_consume_zue_coin = fixed2Float($max_consume_amount / $zue_coin_exchange_rate);
  363. if ($max_consume_zue_coin - ($order->zue_coin + $zue_coin) < 0) {
  364. return $this->fail("最多能使用御龙币: {$max_consume_zue_coin}, 当前已使用{$order->zue_coin}");
  365. }
  366. // 根据当前订单支付情况 得出现在最大的报销金额;
  367. $now_max_consume_amount = $order->imposed_amount < $max_consume_amount ? $order->imposed_amount : $max_consume_amount;
  368. // 当前最多还能使用多少御龙币
  369. $now_can_consume_zue_coin = fixed2Float($now_max_consume_amount / $zue_coin_exchange_rate);
  370. // 判断当前还能使用
  371. if ($now_can_consume_zue_coin - $zue_coin < 0)
  372. return $this->fail("当前剩余可使用的: {$now_can_consume_zue_coin}");
  373. // 总共使用了这么多御龙币
  374. $order_use_zue_coin += $zue_coin;
  375. // 总共兑换了这么多钱
  376. $order_use_zue_coin_amount = fixed2Float($order_use_zue_coin * $zue_coin_exchange_rate);
  377. $change_zue_coin_record = [
  378. 'zue_coin_id' => $zue_coin_model->id,
  379. 'order_id' => $order->id,
  380. 'origin' => $zue_coin_model->zue_coin,
  381. 'change' => -$zue_coin,
  382. 'after' => $zue_coin_model->zue_coin - $zue_coin,
  383. 'reason' => 1,
  384. 'create_time' => time(),
  385. 'update_time' => time(),
  386. ];
  387. }
  388. // 总计费用 - 御龙币抵消费用;
  389. $imposed_amount -= $order_use_zue_coin_amount;
  390. // 总计实收金额
  391. $receive_amount = fixed2Float($order->receive_amount + $total_fee);
  392. 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})");
  393. $order_annual_fees = [];
  394. $update_store_products = [];
  395. $update_order_products = [];
  396. if (round($receive_amount) == round($imposed_amount)) { // 减库存
  397. $order_products = $this->orderProductModel->findByOrderId($order->id)->toArray();
  398. $store_products = $this->storeProductModel->findByIds(array_map(function ($r) {
  399. return $r['store_product_id'];
  400. }, $order_products))->toArray();
  401. $fmt_store_products = array_reduce($store_products, function ($result, $item) {
  402. $result[$item['id']] = $item;
  403. return $result;
  404. }, []);
  405. // 商品本身的价格 | 年费 | 消费税
  406. $total_ = $order->product_amount + $order->total_annual_fee + $order->total_sales_tax;
  407. // 信用卡手续费 每一块钱所占的比例
  408. $item_service_charge_rate = ($order->service_charge_amount + $service_charge) / $total_;
  409. // 每一个御龙币所占的比例
  410. $item_zue_coin_rate = $order_use_zue_coin / $total_;
  411. foreach ($order_products as $order_product) {
  412. predicate($fmt_store_products[$order_product['store_product_id']]['now_stock'] > 0, lang('inventory shortage'));
  413. $fmt_store_products[$order_product['store_product_id']]['now_stock'] -= 1;
  414. if (isset($update_store_products[$order_product['store_product_id']])) {
  415. $update_store_products[$order_product['store_product_id']]['reduce_num'] += 1;
  416. } else {
  417. $update_store_products[$order_product['store_product_id']] = ['id' => $order_product['store_product_id'], 'reduce_num' => 1];
  418. }
  419. if ($order_product['is_gather_annuity'] && $order_product['annuity'] > 0) {
  420. $adviser_ids = [];
  421. if ($order_product['adviser_1_id']) {
  422. array_push($adviser_ids, $order_product['adviser_1_id']);
  423. }
  424. if ($order_product['adviser_2_id']) {
  425. array_push($adviser_ids, $order_product['adviser_2_id']);
  426. }
  427. array_push($order_annual_fees, [
  428. 'order_id' => $order->id,
  429. 'customer_id' => $customer->id,
  430. 'customer_name' => "{$customer->name_en}|{$customer->name_zh}",
  431. 'customer_mobile' => $customer->mobile,
  432. 'customer_create_username' => $customer->create_username,
  433. 'index' => 1,
  434. 'order_product_id' => $order_product['id'],
  435. 'order_product_name' => $order_product['product_name'],
  436. 'fee' => $order_product['annuity'],
  437. 'is_pay' => 1,
  438. 'start_time' => time(),
  439. 'end_time' => time() + (365 * 24 * 60 * 60),
  440. 'order_create_time' => strtotime($order->create_time),
  441. 'adviser_ids' => join(',', $adviser_ids),
  442. 'store_id' => $order->store_id,
  443. 'create_time' => time(),
  444. 'update_time' => time()
  445. ]);
  446. }
  447. $now = $order_product['real_price'] + $order_product['annuity'] + $order_product['sales_tax'];
  448. $item_service_charge = fixed2Float($now * $item_service_charge_rate);
  449. $item_zue_coin = fixed2Float($now * $item_zue_coin_rate);
  450. $item_zue_coin_amount = fixed2Float($item_zue_coin * $zue_coin_exchange_rate);
  451. $transaction_price = fixed2Float($now + $item_service_charge - $item_zue_coin_amount);
  452. array_push($update_order_products, [
  453. 'id' => $order_product['id'],
  454. 'service_charge' => $item_service_charge,
  455. 'zue_coin' => $item_zue_coin,
  456. 'zue_coin_amount' => $item_zue_coin_amount,
  457. 'transaction_price' => $transaction_price,
  458. 'is_pay' => 1
  459. ]);
  460. }
  461. }
  462. Db::startTrans();
  463. try {
  464. $update_order = [
  465. 'rental_amount' => $imposed_amount + $order_use_zue_coin_amount,
  466. 'receivable_amount' => $imposed_amount,
  467. 'receive_amount' => $receive_amount,
  468. 'imposed_amount' => $imposed_amount - $receive_amount,
  469. 'service_charge_amount' => $order->service_charge_amount + $service_charge,
  470. 'zue_coin' => $order_use_zue_coin,
  471. 'zue_coin_amount' => $order_use_zue_coin_amount,
  472. 'remarks' => $params['remarks'] ?? null
  473. ];
  474. if (round($receive_amount) == round($imposed_amount)) { // 支付满了
  475. $update_order['type'] = 1;
  476. if (count($update_order_products) > 0) {
  477. foreach ($update_order_products as $item) {
  478. Db::table('erp_order_product')->where('id', $item['id'])->update($item);
  479. }
  480. }
  481. if (count($order_annual_fees) > 0) {
  482. Db::table('erp_order_annual_fee')->insertAll($order_annual_fees);
  483. }
  484. if (count($update_store_products) > 0) {
  485. foreach ($update_store_products as $update) {
  486. Db::table('erp_store_product')->where('id', $update['id'])->dec('now_stock', 1)->update();
  487. Db::table('erp_store_product')->where('id', $update['id'])->inc('sale_stock', 1)->update();
  488. }
  489. }
  490. }
  491. Db::table('erp_order_proceeds')->save([
  492. 'order_id' => $order->id,
  493. 'channels' => join(' ', $record_channel_names),
  494. 'fee' => $total_fee,
  495. 'admin_id' => $params['admin_id'],
  496. 'admin_name' => $params['admin_name'],
  497. 'create_time' => time(),
  498. 'update_time' => time(),
  499. ]);
  500. if ($zue_coin > 0 && $change_zue_coin_record != null) {
  501. Db::table('erp_zue_coin_record')->save($change_zue_coin_record);
  502. Db::table('erp_customer_zue_coin')->where('id', $change_zue_coin_record['zue_coin_id'])->dec('zue_coin', $zue_coin)->update();
  503. }
  504. if (count($order_payments) > 0) {
  505. Db::table('erp_order_payment')->insertAll(array_map(function ($data) {
  506. return [
  507. "order_id" => isset($data['order_id']) ? $data['order_id'] : null,
  508. "channel_id" => isset($data['channel_id']) ? $data['channel_id'] : null,
  509. "channel_name" => isset($data['channel_name']) ? $data['channel_name'] : null,
  510. "fee" => isset($data['fee']) ? $data['fee'] : null,
  511. "credit_card_id" => isset($data['credit_card_id']) ? $data['credit_card_id'] : null,
  512. "credit_card_name" => isset($data['credit_card_name']) ? $data['credit_card_name'] : null,
  513. "create_time" => isset($data['create_time']) ? $data['create_time'] : null,
  514. "update_time" => isset($data['update_time']) ? $data['update_time'] : null,
  515. "code" => isset($data['code']) ? $data['code'] : null,
  516. "stage_num" => isset($data['stage_num']) ? $data['stage_num'] : null,
  517. "service_charge_rate" => isset($data['service_charge_rate']) ? $data['service_charge_rate'] : null,
  518. "service_charge" => isset($data['service_charge']) ? $data['service_charge'] : null
  519. ];
  520. }, $order_payments));
  521. }
  522. Db::table('erp_order')->where('id', $order->id)->update($update_order);
  523. Db::commit();
  524. } catch (\Exception $e) {
  525. Db::rollback();
  526. return $this->fail(lang($e->getMessage()));
  527. }
  528. return $this->ok(true);
  529. }
  530. /**
  531. * @param $params
  532. * @return array
  533. * @throws \think\db\exception\DbException
  534. */
  535. public function fetch($params)
  536. {
  537. $verify = AuthService::verify($params['admin_id'], $params['type'] == 1 ? 10003 : 10004);
  538. $res = $this->orderModel->search($params, $verify);
  539. $items = $res['data'];
  540. return [array_map(function ($item) {
  541. return [
  542. "id" => $item['id'],
  543. "no" => $item['no'],
  544. "customer_id" => $item['customer_id'],
  545. "customer_name" => $item['customer_name'],
  546. "obj_names" => $item['obj_names'],
  547. "rental_amount" => $item['rental_amount'],
  548. "receivable_amount" => $item['receivable_amount'],
  549. "receive_amount" => $item['receive_amount'],
  550. "imposed_amount" => $item['imposed_amount'],
  551. "product_amount" => $item['product_amount'],
  552. "total_sales_tax" => $item['total_sales_tax'],
  553. "service_charge_amount" => $item['service_charge_amount'],
  554. "total_annual_fee" => $item['total_annual_fee'],
  555. "zue_coin" => $item['zue_coin'],
  556. "zue_coin_amount" => $item['zue_coin_amount'],
  557. "type" => $item['type'],
  558. "store_id" => $item['store_id'],
  559. "advisor_ids" => $item['advisor_ids'],
  560. "remarks" => $item['remarks'],
  561. "create_time" => $item['create_time'],
  562. "advisers" => join('/', array_unique(array_reduce($item['products'], function ($result, $item) {
  563. array_push($result, $item['adviser_1_name']);
  564. if ($item['adviser_2_id'] > 0)
  565. array_push($result, $item['adviser_2_name']);
  566. return $result;
  567. }, []))),
  568. "teachers" => join('/', array_unique(array_reduce($item['products'], function ($result, $item) {
  569. if ($item['teacher_1_id'] > 0)
  570. array_push($result, $item['teacher_1_name']);
  571. if ($item['teacher_2_id'] > 0)
  572. array_push($result, $item['teacher_2_name']);
  573. return $result;
  574. }, []))),
  575. "payments" => join(' ', array_unique(array_reduce($item['payments'], function ($result, $item) {
  576. array_push($result, '[' . $item['channel_name'] . ']');
  577. return $result;
  578. }, []))),
  579. "stage_num" => array_reduce($item['payments'], function ($result, $item) {
  580. if ($item['stage_num'] && $item['stage_num'] > $result) {
  581. $result = $item['stage_num'];
  582. }
  583. return $result;
  584. }, 0),
  585. 'is_need_upload' => $item['type'] == 1 && in_array(true, array_map(function ($product) {
  586. return $product['is_upload_numerology'] == 1 && $product['is_upload'] == 0;
  587. }, $item['products'])),
  588. ];
  589. }, $items), $res['total']];
  590. }
  591. /**
  592. * @param $params
  593. * @return array
  594. * @throws \think\db\exception\DbException
  595. */
  596. public function fetchByCustomerId($params)
  597. {
  598. $res = $this->orderModel->fetchByCustomerId($params['customer_id'], $params['page'] ?? 1, $params['size'] ?? 20);
  599. $items = $res['data'];
  600. return [array_map(function ($item) {
  601. return [
  602. "id" => $item['id'],
  603. "no" => $item['no'],
  604. "customer_id" => $item['customer_id'],
  605. "customer_name" => $item['customer_name'],
  606. "obj_names" => $item['obj_names'],
  607. "rental_amount" => $item['rental_amount'],
  608. "receivable_amount" => $item['receivable_amount'],
  609. "receive_amount" => $item['receive_amount'],
  610. "imposed_amount" => $item['imposed_amount'],
  611. "product_amount" => $item['product_amount'],
  612. "total_sales_tax" => $item['total_sales_tax'],
  613. "service_charge_amount" => $item['service_charge_amount'],
  614. "total_annual_fee" => $item['total_annual_fee'],
  615. "zue_coin" => $item['zue_coin'],
  616. "zue_coin_amount" => $item['zue_coin_amount'],
  617. "type" => $item['type'],
  618. "store_id" => $item['store_id'],
  619. "advisor_ids" => $item['advisor_ids'],
  620. "remarks" => $item['remarks'],
  621. "create_time" => $item['create_time'],
  622. "advisers" => join('/', array_unique(array_reduce($item['products'], function ($result, $item) {
  623. array_push($result, $item['adviser_1_name']);
  624. if ($item['adviser_2_id'] > 0)
  625. array_push($result, $item['adviser_2_name']);
  626. return $result;
  627. }, []))),
  628. "teachers" => join('/', array_unique(array_reduce($item['products'], function ($result, $item) {
  629. if ($item['teacher_1_id'] > 0)
  630. array_push($result, $item['teacher_1_name']);
  631. if ($item['teacher_2_id'] > 0)
  632. array_push($result, $item['teacher_2_name']);
  633. return $result;
  634. }, []))),
  635. "stage_num" => array_reduce($item['payments'], function ($result, $item) {
  636. if ($item['stage_num'] && $item['stage_num'] > $result) {
  637. $result = $item['stage_num'];
  638. }
  639. return $result;
  640. }, 0),
  641. 'is_need_upload' => $item['type'] == 1 && in_array(true, array_map(function ($product) {
  642. return $product['is_upload_numerology'] == 1 && $product['is_upload'] == 0;
  643. }, $item['products'])),
  644. ];
  645. }, $items), $res['total']];
  646. }
  647. public function fetchOrderProducts($order_id, $page = 1, $size = 10)
  648. {
  649. $res = $this->orderProductModel->fetchByOrderId($order_id, $page, $size);
  650. return [$res->items(), $res->total()];
  651. }
  652. public function upload_numerology($order_product_id, $report)
  653. {
  654. $order_product = $this->orderProductModel->findById($order_product_id);
  655. if (!$order_product) return $this->fail('订单商品不存在,无法上传命理报告!');
  656. if (!$order_product->is_pay) return $this->fail('订单未支付,无法上传商品');
  657. $order_product->is_upload = 1;
  658. $order_product->report = $report;
  659. $order_product->save();
  660. return $this->ok($order_product);
  661. }
  662. public function fetchWaitGatherAnnualFee($admin_id, $text = null, $start_time = null, $end_time = null, $page = 1, $size = 10)
  663. {
  664. $res = $this->orderAnnualFeeModel->fetchByAdviser($admin_id, $text, $start_time, $end_time, $page, $size);
  665. return [$res[0]->items(), $res[0]->total(), $res[1]];
  666. }
  667. public function paymentAnnualFee($annual_fee_id)
  668. {
  669. $annual_fee = $this->orderAnnualFeeModel->findById($annual_fee_id);
  670. if (!$annual_fee_id) {
  671. return $this->fail('年费记录不存在!');
  672. }
  673. if ($annual_fee->is_pay == 1)
  674. return $this->fail('该条年费记录已经支付!');
  675. $annual_fee->is_pay = 1;
  676. $annual_fee->update_time = time();
  677. $annual_fee->save();
  678. return $this->ok($annual_fee);
  679. }
  680. public function fetchOrderByReturn($admin_id, $store_id, $no = null, $customer_name = null, $page = 1, $size = 10)
  681. {
  682. $verify = AuthService::verify($admin_id, 10005);
  683. $res = $this->orderModel->fetchOrderByReturn($admin_id, $store_id, $no, $customer_name, $page, $size, $verify)->toArray();
  684. $items = $res['data'];
  685. return [array_map(function ($item) {
  686. return [
  687. "id" => $item['id'],
  688. "no" => $item['no'],
  689. "customer_id" => $item['customer_id'],
  690. "customer_name" => $item['customer_name'],
  691. "obj_names" => $item['obj_names'],
  692. "rental_amount" => $item['rental_amount'],
  693. "receivable_amount" => $item['receivable_amount'],
  694. "receive_amount" => $item['receive_amount'],
  695. "imposed_amount" => $item['imposed_amount'],
  696. "product_amount" => $item['product_amount'],
  697. "total_sales_tax" => $item['total_sales_tax'],
  698. "service_charge_amount" => $item['service_charge_amount'],
  699. "total_annual_fee" => $item['total_annual_fee'],
  700. "zue_coin" => $item['zue_coin'],
  701. "zue_coin_amount" => $item['zue_coin_amount'],
  702. "type" => $item['type'],
  703. "store_id" => $item['store_id'],
  704. "advisor_ids" => $item['advisor_ids'],
  705. "remarks" => $item['remarks'],
  706. "create_time" => $item['create_time'],
  707. "advisers" => join('/', array_unique(array_reduce($item['products'], function ($result, $item) {
  708. array_push($result, $item['adviser_1_name']);
  709. if ($item['adviser_2_id'] > 0)
  710. array_push($result, $item['adviser_2_name']);
  711. return $result;
  712. }, []))),
  713. "teachers" => join('/', array_unique(array_reduce($item['products'], function ($result, $item) {
  714. if ($item['teacher_1_id'] > 0)
  715. array_push($result, $item['teacher_1_name']);
  716. if ($item['teacher_2_id'] > 0)
  717. array_push($result, $item['teacher_2_name']);
  718. return $result;
  719. }, [])))
  720. ];
  721. }, $items), $res['total']];
  722. }
  723. public function findByOrderNo($admin_id, $order_no)
  724. {
  725. $order = $this->orderModel->findByOrderNo($admin_id, $order_no);
  726. if (!$order)
  727. return $this->fail(lang("Order does not exist"));
  728. return $this->ok($order);
  729. }
  730. /**
  731. * @param $admin_id
  732. * @param $order_id
  733. * @param array $order_product_ids
  734. * @return \SResult
  735. * @throws \think\db\exception\DataNotFoundException
  736. * @throws \think\db\exception\DbException
  737. * @throws \think\db\exception\ModelNotFoundException
  738. */
  739. public function returnOrderProduct($admin_id, $order_id, array $order_product_ids)
  740. {
  741. // $verify = AuthService::verify($admin_id, 10005);
  742. $order = $this->orderModel->findById($order_id);
  743. if (!$order) return $this->fail(lang("Order does not exist"));
  744. if ($order->type == 2) return $this->fail(lang("The status of the order does not support return or exchange"));
  745. $return_order_products = $this->orderProductModel->findByIds($order_product_ids)->toArray();
  746. if (count($order_product_ids) != count($return_order_products)) return $this->fail(lang("The order item was incorrectly selected"));
  747. $all_order_products = $this->orderProductModel->findByOrderId($order->id)->toArray();
  748. $merge_order_products = array_reduce($all_order_products,
  749. function ($result, $item) use ($order_product_ids) {
  750. if (!in_array($item['id'], $order_product_ids))
  751. array_push($result, $item);
  752. return $result;
  753. }, []);
  754. $obj_names = array_map(function ($data) {
  755. return $data['product_name'];
  756. }, $merge_order_products);
  757. $advisor_ids = array_reduce($merge_order_products, function ($result, $item) {
  758. if ($item['adviser_1_id'])
  759. array_push($result, $item['adviser_1_id']);
  760. if ($item['adviser_2_id'])
  761. array_push($result, $item['adviser_2_id']);
  762. return $result;
  763. }, []);
  764. $zue_coin_config = $this->paymentChannelModel->findById(11);
  765. if (!$zue_coin_config)
  766. return $this->fail("御龙币设置不存在!");
  767. $zue_coin_exchange_rate = $zue_coin_config['zue_coin_exchange_rate'] ?? 0; // 兑换比例
  768. //商品本金
  769. $total_product_amount = $order->product_amount;
  770. // 整体税费
  771. $total_sales_tax = $order->total_sales_tax;
  772. // 总体信用卡服务费
  773. $total_service_amount = $order->service_charge_amount;
  774. // 总体年费
  775. $total_annual_fee = $order->total_annual_fee;
  776. // 总体御龙币
  777. $total_zue_coin = $order->zue_coin;
  778. // 御龙币兑换的金额
  779. $total_zue_coin_amount = $order->zue_coin_amount;
  780. // 御龙币当时的兑换比例
  781. $zue_coin_exchange_rate = $order->zue_coin_amount > 0 && $order->zue_coin > 0 ? fixed2Float($order->zue_coin_amount / $order->zue_coin) : $zue_coin_exchange_rate;
  782. // 总计退还多少钱
  783. $total_return_amount = 0;
  784. // 商品库存
  785. $return_now_stocks = [];
  786. foreach ($return_order_products as $return_order_product) {
  787. // 减少御龙币
  788. $total_zue_coin -= $return_order_product['zue_coin'];
  789. $total_zue_coin_amount -= ($return_order_product['zue_coin'] * $zue_coin_exchange_rate);
  790. // 减少年费
  791. $total_annual_fee -= $return_order_product['annuity'];
  792. // 减少信用卡服务费
  793. $total_service_amount -= $return_order_product['service_charge'];
  794. // 减少税费
  795. $total_sales_tax -= $return_order_product['sales_tax'];
  796. // 减少本金
  797. $total_product_amount -= $return_order_product['real_price'];
  798. $total_return_amount -= $return_order_product['transaction_price'];
  799. if (isset($return_now_stocks[$return_order_product['store_product_id']])) {
  800. $return_now_stocks[$return_order_product['store_product_id']] += 1;
  801. } else {
  802. $return_now_stocks[$return_order_product['store_product_id']] = 1;
  803. }
  804. }
  805. $total_order_rental_amount = fixed2Float($total_product_amount + $total_sales_tax + $total_service_amount + $total_annual_fee);
  806. $total_receivable_amount = fixed2Float($total_product_amount + $total_sales_tax + $total_service_amount + $total_annual_fee - ($total_zue_coin * $zue_coin_exchange_rate));
  807. $total_receive_amount = $total_receivable_amount;
  808. $annual_fees = $this->orderAnnualFeeModel->fetchByOrderProductId($order_product_ids);
  809. Db::startTrans();
  810. try {
  811. // 退还御龙币
  812. $return_zue_coin = $order->zue_coin - $total_zue_coin;
  813. if ($return_zue_coin > 0) {
  814. $customer_zue_coin = $this->zueCoinModel->findByCustomerId($order->customer_id);
  815. if (!$customer_zue_coin) {
  816. throw new BaseException('御龙币账户记录不存在', 1012);
  817. }
  818. Db::table('erp_customer_zue_coin')->where('id', '=', $customer_zue_coin->id)->inc('zue_coin', $return_zue_coin)->update();
  819. Db::table('erp_zue_coin_record')->save([
  820. 'zue_coin_id' => $customer_zue_coin->id,
  821. 'order_id' => $order->id,
  822. 'origin' => $customer_zue_coin->zue_coin,
  823. 'change' => $return_zue_coin,
  824. 'after' => $customer_zue_coin->zue_coin + $return_zue_coin,
  825. 'reason' => 3,
  826. 'create_time' => time(),
  827. 'update_time' => time(),
  828. ]);
  829. }
  830. // 退还年费
  831. if (count($annual_fees) > 0)
  832. Db::table('erp_order_annual_fee')->where('id', 'in', array_map(function ($data) {
  833. return $data['id'];
  834. }, $annual_fees))->update(['is_delete' => 1, 'delete_time' => time()]);
  835. // 更新订单
  836. if (count($return_order_products) == count($all_order_products)) {
  837. Db::table('erp_order')->where('id', $order->id)->update(['is_delete' => 1]);
  838. } else {
  839. Db::table('erp_order')->where('id', $order->id)->update([
  840. 'rental_amount' => $total_order_rental_amount,
  841. 'receivable_amount' => $total_receivable_amount,
  842. 'receive_amount' => $total_receive_amount,
  843. 'product_amount' => $total_product_amount,
  844. 'total_sales_tax' => $total_sales_tax,
  845. 'service_charge_amount' => $total_service_amount,
  846. 'total_annual_fee' => $total_annual_fee,
  847. 'zue_coin' => $total_zue_coin,
  848. 'zue_coin_amount' => $total_zue_coin_amount,
  849. 'obj_names' => join(',', array_unique($obj_names)),
  850. 'advisor_ids' => join(',', array_unique($advisor_ids)),
  851. ]);
  852. }
  853. // 插入退款记录
  854. Db::table('erp_order_payment')->save([
  855. 'order_id' => $order->id,
  856. 'channel_id' => 0,
  857. 'channel_name' => "Exchange a purchase",
  858. 'fee' => $total_return_amount,
  859. 'create_time' => time(),
  860. 'update_time' => time(),
  861. ]);
  862. // 退还商品库存
  863. $return_stock_keys = array_keys($return_now_stocks);
  864. foreach ($return_stock_keys as $key) {
  865. Db::table("erp_store_product")
  866. ->where('id', $key)
  867. ->inc('now_stock', $return_now_stocks[$key])
  868. ->dec('sale_stock', $return_now_stocks[$key])
  869. ->update();
  870. }
  871. // 删除订单商品
  872. Db::table('erp_order_product')->where('id', 'in', $order_product_ids)->update(['is_delete' => 1, 'delete_time' => time()]);
  873. Db::commit();
  874. } catch (\Exception $e) {
  875. Db::rollback();
  876. return $this->fail(lang($e->getMessage()));
  877. }
  878. return $this->ok(true);
  879. }
  880. /**
  881. * @param $admin_id
  882. * @param $admin_name
  883. * @param $order_id
  884. * @param $origin_order_product_ids
  885. * @param $append_store_product_ids
  886. * @return \SResult
  887. * @throws \think\db\exception\DataNotFoundException
  888. * @throws \think\db\exception\DbException
  889. * @throws \think\db\exception\ModelNotFoundException
  890. */
  891. public function exchange($admin_id, $admin_name, $order_id, $origin_order_product_ids, $append_store_product_ids)
  892. {
  893. // $verify = AuthService::verify($admin_id, 10005);
  894. $order = $this->orderModel->findById($order_id);
  895. if (!$order) return $this->fail(lang("Order does not exist"));
  896. if ($order->type == 2) return $this->fail(lang("The status of the order does not support return or exchange"));
  897. $return_order_products = $this->orderProductModel->findByIds($origin_order_product_ids)->toArray();
  898. if (count($origin_order_product_ids) != count($return_order_products)) return $this->fail(lang("The order item was incorrectly selected"));
  899. $all_order_products = $this->orderProductModel->findByOrderId($order->id)->toArray();
  900. $merge_order_products = array_reduce($all_order_products,
  901. function ($result, $item) use ($origin_order_product_ids) {
  902. if (!in_array($item['id'], $origin_order_product_ids))
  903. array_push($result, $item);
  904. return $result;
  905. }, []);
  906. $obj_names = array_map(function ($data) {
  907. return $data['product_name'];
  908. }, $merge_order_products);
  909. $advisor_ids = array_reduce($merge_order_products, function ($result, $item) {
  910. if ($item['adviser_1_id'])
  911. array_push($result, $item['adviser_1_id']);
  912. if ($item['adviser_2_id'])
  913. array_push($result, $item['adviser_2_id']);
  914. return $result;
  915. }, []);
  916. $zue_coin_config = $this->paymentChannelModel->findById(11);
  917. if (!$zue_coin_config)
  918. return $this->fail("御龙币设置不存在!");
  919. $zue_coin_exchange_rate = $zue_coin_config['zue_coin_exchange_rate'] ?? 0; // 兑换比例
  920. //商品本金
  921. $total_product_amount = $order->product_amount;
  922. // 整体税费
  923. $total_sales_tax = $order->total_sales_tax;
  924. // 总体信用卡服务费
  925. $total_service_amount = $order->service_charge_amount;
  926. // 总体年费
  927. $total_annual_fee = $order->total_annual_fee;
  928. // 总体御龙币
  929. $total_zue_coin = $order->zue_coin;
  930. // 御龙币兑换的金额
  931. $total_zue_coin_amount = $order->zue_coin_amount;
  932. // 御龙币当时的兑换比例
  933. $zue_coin_exchange_rate = $order->zue_coin_amount > 0 && $order->zue_coin > 0 ? fixed2Float($order->zue_coin_amount / $order->zue_coin) : $zue_coin_exchange_rate;
  934. // 差价
  935. $diff_amount = 0;
  936. // 商品库存
  937. $return_now_stocks = [];
  938. // 减操作
  939. foreach ($return_order_products as $return_order_product) {
  940. // 减少御龙币
  941. $total_zue_coin -= $return_order_product['zue_coin'];
  942. $total_zue_coin_amount -= ($return_order_product['zue_coin'] * $zue_coin_exchange_rate);
  943. // 减少年费
  944. $total_annual_fee -= $return_order_product['annuity'];
  945. // 减少信用卡服务费
  946. $total_service_amount -= $return_order_product['service_charge'];
  947. // 减少税费
  948. $total_sales_tax -= $return_order_product['sales_tax'];
  949. // 减少本金
  950. $total_product_amount -= $return_order_product['real_price'];
  951. $diff_amount -= $return_order_product['transaction_price'];
  952. if (isset($return_now_stocks[$return_order_product['store_product_id']])) {
  953. $return_now_stocks[$return_order_product['store_product_id']] += 1;
  954. } else {
  955. $return_now_stocks[$return_order_product['store_product_id']] = 1;
  956. }
  957. }
  958. /////////////// 加操作
  959. // 客户
  960. $customer = $this->customerModel->findById($order->customer_id);
  961. if (!$customer)
  962. return $this->fail(lang("The Customer does not exist"));
  963. // 门店商品
  964. $store_products = $this->storeProductModel->fetchRelationsByOrder($append_store_product_ids)->toArray();
  965. $store_products = array_reduce($store_products, function ($result, $item) {
  966. $result[$item['id']] = $item;
  967. return $result;
  968. }, []);
  969. $store_products = array_map(function ($id) use ($store_products) {
  970. return $store_products[$id];
  971. }, $append_store_product_ids);
  972. if (count($store_products) != count($append_store_product_ids))
  973. return $this->fail(lang("The Product does not exist"));
  974. // 商品信息
  975. $products = array_map(function ($p) {
  976. return $p['product'] ? $p['product'] : null;
  977. }, $store_products);
  978. if (in_array(null, $products))
  979. return $this->fail(lang("The Product does not exist"));
  980. $config = $this->configModel->findConfig();
  981. $activityProducts = $this->activityProductModel->fetchByProductIds(array_map(function ($data) {
  982. return $data['id'];
  983. }, $products))->toArray();
  984. $fmt_store_products = [];
  985. foreach ($store_products as &$item) {
  986. $aProducts = array_filter($activityProducts, function ($aProduct) use ($item) {
  987. return $aProduct['product_id'] == $item['product_id'];
  988. });
  989. $res = compare($item['product']['real_price'] ?? 0, $aProducts);
  990. $item['activity'] = $res['item'];
  991. $item['product']['origin_price'] = $item['product']['real_price'];
  992. $item['product']['real_price'] = fixed2Float($res['min_num'] > 0 ? $res['min_num'] : 0);
  993. $sales_tax_rate = $item['product']['sales_tax_rate'] > 0 ? $item['product']['sales_tax_rate'] : $config->sales_tax_rate;
  994. $sales_tax = fixed2Float($sales_tax_rate > 0 && $item['product']['real_price'] > 0 ? ($item['product']['real_price'] * ($sales_tax_rate / 100)) : 0);
  995. $item['product']['sales_tax_rate'] = $sales_tax_rate;
  996. $item['product']['sales_tax'] = $sales_tax;
  997. $fmt_store_products[$item['id']] = $item;
  998. }
  999. $order_products = [];
  1000. $order_annual_fees = [];
  1001. for ($j = 0; $j < count($store_products); $j++) {
  1002. $store_product = $store_products[$j];
  1003. array_push($obj_names, $store_product['product']['name']);
  1004. array_push($advisor_ids, $admin_id);
  1005. array_push($order_products, [
  1006. 'order_id' => $order->id,
  1007. 'order_no' => $order->no,
  1008. 'customer_id' => $order->customer_id,
  1009. 'product_id' => $store_product['product']['id'],
  1010. 'product_category_id' => $store_product['product']['category_id'],
  1011. 'is_serve' => $store_product['product']['is_serve'],
  1012. 'store_product_id' => $store_product['id'],
  1013. 'product_name' => $store_product['product']['name'],
  1014. 'adviser_1_id' => $admin_id,
  1015. 'adviser_1_name' => $admin_name,
  1016. 'adviser_2_id' => null,
  1017. 'adviser_2_name' => null,
  1018. 'teacher_1_id' => null,
  1019. 'teacher_1_name' => null,
  1020. 'teacher_2_id' => null,
  1021. 'teacher_2_name' => null,
  1022. 'is_upload_numerology' => $store_product['product']['is_upload_numerology'],
  1023. 'is_upload' => 0,
  1024. 'report' => null,
  1025. 'is_gather_annuity' => $store_product['product']['is_gather_annuity'],
  1026. 'annuity' => $store_product['product']['annuity'],
  1027. 'real_price' => $store_product['product']['real_price'],
  1028. 'service_charge' => 0,
  1029. 'reduce_price' => $store_product['activity'] ? $store_product['product']['origin_price'] - $store_product['product']['real_price'] : 0,
  1030. 'reduce_type' => $store_product['activity'] ? $store_product['activity']['type'] : 0,
  1031. 'sales_tax_rate' => $store_product['product']['sales_tax_rate'],
  1032. 'sales_tax' => $store_product['product']['sales_tax'],
  1033. 'transaction_price' => fixed2Float($store_product['product']['real_price'] + $store_product['product']['sales_tax'] + $store_product['product']['annuity']),
  1034. 'zue_coin' => 0,
  1035. 'is_pay' => 0,
  1036. 'create_time' => time(),
  1037. 'update_time' => time(),
  1038. ]);
  1039. array_push($order_annual_fees, $store_product['product']['is_gather_annuity'] && $store_product['product']['annuity'] > 0 ? [
  1040. 'order_id' => $order->id,
  1041. 'customer_id' => $order->customer_id,
  1042. 'customer_name' => $order->customer_name,
  1043. 'customer_mobile' => $customer->mobile,
  1044. 'customer_create_username' => $customer->create_username,
  1045. 'index' => 1,
  1046. 'order_product_id' => -1,
  1047. 'order_product_name' => $store_product['product']['name'],
  1048. 'fee' => $store_product['product']['annuity'],
  1049. 'is_pay' => 0,
  1050. 'start_time' => time(),
  1051. 'end_time' => time() + (365 * 24 * 60 * 60),
  1052. 'order_create_time' => strtotime($order->create_time),
  1053. 'adviser_ids' => $admin_id,
  1054. 'store_id' => $order->store_id,
  1055. 'create_time' => time(),
  1056. 'update_time' => time()
  1057. ] : null);
  1058. $total_product_amount += $store_product['product']['real_price'];
  1059. $total_sales_tax += $store_product['product']['sales_tax'];
  1060. if ($store_product['product']['is_gather_annuity'] == 1)
  1061. $total_annual_fee += $store_product['product']['annuity'];
  1062. $diff_amount += fixed2Float($store_product['product']['real_price'] + $store_product['product']['sales_tax'] + $store_product['product']['annuity']);
  1063. }
  1064. $total_order_rental_amount = fixed2Float($total_product_amount + $total_sales_tax + $total_service_amount + $total_annual_fee);
  1065. $total_receivable_amount = fixed2Float($total_product_amount + $total_sales_tax + $total_service_amount + $total_annual_fee - ($total_zue_coin * $zue_coin_exchange_rate));
  1066. $total_receive_amount = $total_receivable_amount;
  1067. $annual_fees = $this->orderAnnualFeeModel->fetchByOrderProductId($origin_order_product_ids);
  1068. $return_zue_coin = $order->zue_coin - $total_zue_coin;
  1069. Db::startTrans();
  1070. try {
  1071. // 退还御龙币
  1072. if ($return_zue_coin > 0) {
  1073. $customer_zue_coin = $this->zueCoinModel->findByCustomerId($order->customer_id);
  1074. if (!$customer_zue_coin) {
  1075. throw new BaseException('御龙币账户记录不存在', 1012);
  1076. }
  1077. Db::table('erp_customer_zue_coin')->where('id', '=', $customer_zue_coin->id)->inc('zue_coin', $return_zue_coin)->update();
  1078. Db::table('erp_zue_coin_record')->save([
  1079. 'zue_coin_id' => $customer_zue_coin->id,
  1080. 'order_id' => $order->id,
  1081. 'origin' => $customer_zue_coin->zue_coin,
  1082. 'change' => $return_zue_coin,
  1083. 'after' => $customer_zue_coin->zue_coin + $return_zue_coin,
  1084. 'reason' => 3,
  1085. 'create_time' => time(),
  1086. 'update_time' => time(),
  1087. ]);
  1088. }
  1089. // 退还年费
  1090. if (count($annual_fees) > 0)
  1091. Db::table('erp_order_annual_fee')->where('id', 'in', array_map(function ($data) {
  1092. return $data['id'];
  1093. }, $annual_fees))->update(['is_delete' => 1, 'delete_time' => time()]);
  1094. // 退还商品库存
  1095. $return_stock_keys = array_keys($return_now_stocks);
  1096. foreach ($return_stock_keys as $key) {
  1097. Db::table("erp_store_product")
  1098. ->where('id', $key)
  1099. ->inc('now_stock', $return_now_stocks[$key])
  1100. ->dec('sale_stock', $return_now_stocks[$key])
  1101. ->update();
  1102. }
  1103. // 删除订单商品
  1104. Db::table('erp_order_product')->where('id', 'in', $origin_order_product_ids)->update(['is_delete' => 1, 'delete_time' => time()]);
  1105. $imposed_amount = fixed2Float($total_receivable_amount - $order->receive_amount); // 应收金额 - 实收金额
  1106. if($imposed_amount == 0) {// 应收金额 == 代收金额;
  1107. // 新增商品
  1108. for ($i = 0; $i < count($order_products); $i++) {
  1109. $order_product = $order_products[$i];
  1110. $order_product['is_pay'] = 1;
  1111. $order_annual_fee = $order_annual_fees[$i];
  1112. $last_id = Db::table('erp_order_product')->insert($order_product, true);
  1113. if($order_annual_fee != null) {
  1114. $order_annual_fee['order_product_id'] = $last_id;
  1115. $order_annual_fee['is_pay'] = 1;
  1116. Db::table('erp_order_annual_fee')->save($order_annual_fee);
  1117. }
  1118. Db::table("erp_store_product")
  1119. ->where('id', $order_product['store_product_id'])
  1120. ->dec('now_stock', 1)
  1121. ->inc('sale_stock', 1)
  1122. ->update();
  1123. }
  1124. // 更新订单
  1125. Db::table('erp_order')->where('id', $order->id)->update([
  1126. 'rental_amount' => $total_order_rental_amount,
  1127. 'receivable_amount' => $total_receivable_amount,
  1128. 'receive_amount' => $total_receive_amount,
  1129. 'product_amount' => $total_product_amount,
  1130. 'total_sales_tax' => $total_sales_tax,
  1131. 'service_charge_amount' => $total_service_amount,
  1132. 'total_annual_fee' => $total_annual_fee,
  1133. 'zue_coin' => $total_zue_coin,
  1134. 'zue_coin_amount' => $total_zue_coin_amount,
  1135. 'obj_names' => join(',', array_unique($obj_names)),
  1136. 'advisor_ids' => join(',', array_unique($advisor_ids)),
  1137. ]);
  1138. } else { // 补差价
  1139. // 更新订单
  1140. Db::table('erp_order')->where('id', $order->id)->update([
  1141. 'rental_amount' => $total_order_rental_amount,
  1142. 'receivable_amount' => $total_receivable_amount,
  1143. "imposed_amount" => $imposed_amount,
  1144. 'product_amount' => $total_product_amount,
  1145. 'total_sales_tax' => $total_sales_tax,
  1146. 'service_charge_amount' => $total_service_amount,
  1147. 'total_annual_fee' => $total_annual_fee,
  1148. 'zue_coin' => $total_zue_coin,
  1149. 'zue_coin_amount' => $total_zue_coin_amount,
  1150. 'type' => 2,
  1151. 'obj_names' => join(',', array_unique($obj_names)),
  1152. 'advisor_ids' => join(',', array_unique($advisor_ids)),
  1153. ]);
  1154. // 新增商品
  1155. Db::table('erp_order_product')->insertAll($order_products);
  1156. }
  1157. Db::commit();
  1158. } catch (\Exception $e) {
  1159. Db::rollback();
  1160. return $this->fail(lang($e->getMessage()));
  1161. }
  1162. return $this->ok($diff_amount);
  1163. }
  1164. public function findOrderByOrderId($order_id)
  1165. {
  1166. return $this->orderModel->findById($order_id);
  1167. }
  1168. public function fetchOrderPayments($order_id)
  1169. {
  1170. return $this->orderPaymentModel->findByOrderId($order_id);
  1171. }
  1172. public function paymentDone($admin_id, $order_id, $remarks = null) {
  1173. $order = $this->orderModel->findById($order_id);
  1174. if (!$order)
  1175. return $this->fail(lang("Order does not exist"));
  1176. if ($order->type == 1)
  1177. return $this->fail('订单状态为历史订单!不支持付款');
  1178. // 客户
  1179. $customer = $this->customerModel->findById($order->customer_id);
  1180. if (!$customer)
  1181. return $this->fail(lang("The Customer does not exist"));
  1182. $no_pay_order_products = $this->orderProductModel->findByOrderId($order->id,0)->toArray();
  1183. Db::startTrans();
  1184. try {
  1185. $update_order = [
  1186. 'imposed_amount' => 0,
  1187. 'receive_amount' => $order->receivable_amount,
  1188. 'type' => 1,
  1189. 'remarks' => $remarks
  1190. ];
  1191. $order_annual_fees = [];
  1192. for ($i = 0; $i < count($no_pay_order_products); $i++) {
  1193. $order_product = $no_pay_order_products[$i];
  1194. Db::table('erp_order_product')->where('id',$order_product['id'])->update([
  1195. 'is_pay' => 1
  1196. ]);
  1197. if($order_product['is_gather_annuity'] && $order_product['annuity'] > 0) {
  1198. array_push($order_annual_fees, [
  1199. 'order_id' => $order->id,
  1200. 'customer_id' => $order->customer_id,
  1201. 'customer_name' => $order->customer_name,
  1202. 'customer_mobile' => $customer->mobile,
  1203. 'customer_create_username' => $customer->create_username,
  1204. 'index' => 1,
  1205. 'order_product_id' => $order_product['id'],
  1206. 'order_product_name' => $order_product['product_name'],
  1207. 'fee' => $order_product['annuity'] ,
  1208. 'is_pay' => 1,
  1209. 'start_time' => time(),
  1210. 'end_time' => time() + (365 * 24 * 60 * 60),
  1211. 'order_create_time' => strtotime($order->create_time),
  1212. 'adviser_ids' => $admin_id,
  1213. 'store_id' => $order->store_id,
  1214. 'create_time' => time(),
  1215. 'update_time' => time()
  1216. ]);
  1217. }
  1218. Db::table("erp_store_product")
  1219. ->where('id', $order_product['store_product_id'])
  1220. ->dec('now_stock', 1)
  1221. ->inc('sale_stock', 1)
  1222. ->update();
  1223. }
  1224. Db::table('erp_order_annual_fee')->insertAll($order_annual_fees);
  1225. // 更新订单
  1226. Db::table('erp_order')->where('id', $order->id)->update($update_order);
  1227. // 插入退款记录
  1228. Db::table('erp_order_payment')->save([
  1229. 'order_id' => $order->id,
  1230. 'channel_id' => 0,
  1231. 'channel_name' => "Exchange a purchase",
  1232. 'fee' => $order->imposed_amount,
  1233. 'create_time' => time(),
  1234. 'update_time' => time(),
  1235. ]);
  1236. Db::table('erp_order')->where('id', $order->id)->update($update_order);
  1237. Db::commit();
  1238. } catch (\Exception $e) {
  1239. Db::rollback();
  1240. return $this->fail(lang($e->getMessage()));
  1241. }
  1242. return $this->ok(true);
  1243. }
  1244. }