OrderClass.php 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351
  1. <?php
  2. namespace bizHd\order\classes;
  3. use biz\goods\classes\GoodsClass;
  4. use biz\goods\models\Goods;
  5. use biz\shop\classes\ShopCapitalClass;
  6. use biz\shop\classes\ShopClass;
  7. use biz\shop\classes\ShopExtClass;
  8. use biz\stat\classes\StatOrderCountClass;
  9. use biz\stock\classes\GoodsStockRecordClass;
  10. use bizGhs\product\classes\ProductClass;
  11. use bizGhs\stock\classes\StockRecordClass;
  12. use bizHd\custom\classes\CustomClass;
  13. use bizHd\custom\classes\HdClass;
  14. use bizHd\distribution\classes\DistributionCommissionClass;
  15. use bizHd\hb\classes\HbClass;
  16. use bizHd\item\classes\ItemClass;
  17. use bizHd\merchant\classes\SjClass;
  18. use bizHd\groupBuy\classes\GroupBuyClass;
  19. use bizHd\refund\classes\HdRefundClass;
  20. use bizHd\shop\classes\MainClass;
  21. use bizHd\shop\classes\ShopMoneyChangeClass;
  22. use bizHd\user\classes\UserClass;
  23. use bizHd\work\classes\WorkClass;
  24. use common\components\dict;
  25. use common\components\imgUtil;
  26. use common\components\miniUtil;
  27. use common\components\noticeUtil;
  28. use common\components\orderSn;
  29. use common\components\printUtil;
  30. use common\components\stringUtil;
  31. use common\components\util;
  32. use Yii;
  33. use bizHd\base\classes\BaseClass;
  34. use common\components\lakala\Lakala;
  35. class OrderClass extends BaseClass
  36. {
  37. public static $baseFile = '\bizHd\order\models\Order';
  38. //已取消
  39. const ORDER_STATUS_CANCEL = 5;
  40. //完成
  41. const ORDER_STATUS_COMPLETE = 4;
  42. //配送中
  43. const ORDER_STATUS_SENDING = 3;
  44. //待配送
  45. const ORDER_STATUS_UN_SEND = 2;
  46. //待付款
  47. const ORDER_STATUS_UN_PAY = 1;
  48. //订单总流程数
  49. const ORDER_TOTAL_FLOW = 4;
  50. //未确认配送方式
  51. const SEND_TYPE_UNKNOWN = 0;
  52. //自取
  53. const SEND_TYPE_NO = 1;
  54. //自己送
  55. const SEND_TYPE_MYSELF = 2;
  56. //快递送
  57. const SEND_TYPE_THIRD = 3;
  58. //正常订单
  59. const REFUND_NO = 0;
  60. //已退款订单
  61. const REFUND_YES = 1;
  62. //送达时间段
  63. public static $reachPeriod = [0 => '上午', 1 => '下午', 2 => '晚上'];
  64. //优惠金额
  65. public static $randDiscount = [
  66. 50 => [1, 3],
  67. 100 => [5, 9],
  68. 300 => [10, 15],
  69. 500 => [16, 18],
  70. 1000 => [18, 30],
  71. 20000 => [90, 100],
  72. ];
  73. /**
  74. * 是否必须走跨天售后(挂账已结清/超额、或可售后时限已过)
  75. * @return array{shAddPay:int,shAddPayReason:int} shAddPay=1 表示跨天售后;reason:0欠款已结清/超额,1可售后时限已过
  76. */
  77. public static function ifShPay($order, $main, $refundAmount = 0)
  78. {
  79. $shAddPay = 0;
  80. $shAddPayReason = 0;
  81. $payStatus = $order['payStatus'] ?? 0;
  82. if ($payStatus == 1) {
  83. if ($order['payWay'] == 3) {
  84. if ($order['remainDebtPrice'] <= 0) {
  85. // 挂账已结清:走跨天售后(写 nextRefundNum/nextDayTkPrice)
  86. $shAddPay = 1;
  87. } else {
  88. if ($refundAmount > 0 && $refundAmount > $order['remainDebtPrice']) {
  89. // 售后金额大于剩余欠款:走跨天售后
  90. $shAddPay = 1;
  91. }
  92. }
  93. }
  94. $cRet = OrderClass::couldRefund($order, $main);
  95. $could = $cRet['could'];
  96. if (!$could) {
  97. // 可售后时限已过:走跨天售后
  98. $shAddPay = 1;
  99. $shAddPayReason = 1;
  100. }
  101. }
  102. return ['shAddPay' => $shAddPay, 'shAddPayReason' => $shAddPayReason];
  103. }
  104. //订单是否过了可以售后的时间 ssh 20250730
  105. // $could false 过了售后时间,不能售后,true可以
  106. public static function couldRefund($order, $main)
  107. {
  108. $refundLimit = $main->refundLimit ?? 0;
  109. $payTime = $order['payTime'];
  110. $currentPayTime = strtotime($payTime);
  111. $addDateTime = $refundLimit * 86400;
  112. $couldRefundTime = $currentPayTime + $addDateTime;
  113. $now = time();
  114. $could = $couldRefundTime > $now;
  115. return ['could' => $could];
  116. }
  117. public static function valid($order, $mainId)
  118. {
  119. if (!isset($order->mainId) || $order->mainId != $mainId) {
  120. Yii::info(json_encode($order));
  121. Yii::info('mainId: ' . $mainId);
  122. util::fail('无法访问的订单');
  123. }
  124. return true;
  125. }
  126. //添加订单 ssh 2019.12.5
  127. public static function addOrder($data)
  128. {
  129. $data['orderSn'] = $data['orderSn'] ?? orderSn::getOrderSn();
  130. $data['payStatus'] = $data['payStatus'] ?? 0;
  131. $shopId = $data['shopId'] ?? 0;
  132. //累计订单增加
  133. $shop = ShopClass::getLockById($shopId);
  134. if (empty($shop)) {
  135. util::fail('没有找到门店信息54');
  136. }
  137. $mainId = $shop->mainId ?? 0;
  138. $main = MainClass::getLockById($mainId);
  139. if (empty($main)) {
  140. util::fail('没有找到main信息');
  141. }
  142. $main->unPayOrder += 1;
  143. $main->totalOrder += 1;
  144. $main->save();
  145. $address = $data['address'] ?? '';
  146. $floor = $data['floor'] ?? '';
  147. if (empty($data['fullAddress'])) {
  148. $data['fullAddress'] = $address . $floor;
  149. }
  150. $sendType = intval($data['sendType'] ?? 0);
  151. if ($sendType == 1) {
  152. //到店自取,客户自己下单,不会有到店自取时间,但是如果是花店后台接单,会填到店自取时间,重要!!!!!!!!阿东那边已经出问题了!!!
  153. if (empty($data['reachDate'])) {
  154. $data['reachDate'] = date("Y-m-d");
  155. }
  156. if (empty($data['reachPeriod'])) {
  157. $data['reachPeriod'] = date("H:i", time() + 3600);
  158. }
  159. } elseif (in_array($sendType, [3, 4], true)) {
  160. // 物流(3)/快递(4):时效由客服确认,不强制配送时间;日期缺省为当天
  161. $data['reachDate'] = !empty($data['reachDate']) ? $data['reachDate'] : date("Y-m-d");
  162. $data['reachPeriod'] = $data['reachPeriod'] ?? '';
  163. } else {
  164. //商家配送/跑腿等必须要有配送时间,日期默认当天
  165. $data['reachDate'] = !empty($data['reachDate']) ? $data['reachDate'] : date("Y-m-d");
  166. if (empty($data['reachPeriod'])) {
  167. util::fail('请选择配送时间');
  168. }
  169. }
  170. // 无时段时仅按日期生成 reachTime(物流/快递常见)
  171. $data['reachTime'] = !empty($data['reachPeriod'])
  172. ? strtotime($data['reachDate'] . ' ' . $data['reachPeriod'])
  173. : strtotime($data['reachDate'] . ' 00:00:00');
  174. $book = $data['book'] ?? 0;
  175. // skipShopMeetCut:前端已写入满减后金额时跳过,避免二次门店满减
  176. // 拼团单不叠加门店满减(团购价已是优惠价)
  177. $skipShopMeetCut = !empty($data['skipShopMeetCut']) || intval($data['groupBuyId'] ?? 0) > 0;
  178. $seckillGoodsPrice = self::capSeckillExcludePrice($data['seckillGoodsPrice'] ?? 0, $data['actPrice'] ?? 0);
  179. $seckillGoodsNum = isset($data['seckillGoodsNum']) && is_numeric($data['seckillGoodsNum'] ?? 0) ? $data['seckillGoodsNum'] : 0;
  180. unset($data['skipShopMeetCut'], $data['skipMemberDiscount']); //$data['seckillGoodsPrice'], $data['seckillGoodsNum']
  181. if ($book == 0 && !$skipShopMeetCut) {
  182. $actPrice = $data['actPrice'];
  183. $meetNum = $shop->meetNum ?? 0;
  184. $meetAmount = $shop->meetAmount ?? 0;
  185. $cutOption = $shop->cutAmount ?? 0;
  186. $cutStyle = $shop->cutStyle ?? 0;
  187. // 满减金额门槛和折扣额按剔除秒杀后的应付算,避免秒杀价凑满减或被打折
  188. $discountablePrice = bcsub($actPrice, $seckillGoodsPrice, 2);
  189. // 满减件数门槛不含秒杀份数,最低消费数量仍用订单 bigNum
  190. $meetBigNum = isset($data['bigNum']) ? bcsub($data['bigNum'], $seckillGoodsNum, 2) : 0;
  191. if (bccomp($meetBigNum, '0', 2) < 0) {
  192. $meetBigNum = 0;
  193. }
  194. if ($cutStyle == 0) {
  195. $cutAmount = $cutOption;
  196. } else {
  197. $miniOption = bcsub(1, $cutOption, 2);
  198. $cutAmount = bcmul($discountablePrice, $miniOption, 2);
  199. }
  200. if ($cutAmount > 0 && $meetNum >= 0 && $meetAmount > 0) {
  201. if (bccomp($meetBigNum, $meetNum, 2) >= 0 && bccomp($discountablePrice, $meetAmount, 2) >= 0) {
  202. if (bccomp($cutAmount, $discountablePrice, 2) < 0) {
  203. $actPrice = bcsub($actPrice, $cutAmount, 2);
  204. $data['orderReachDiscountPrice'] = $cutAmount;
  205. $data['actPrice'] = $actPrice;
  206. $data['realPrice'] = $actPrice;
  207. $data['mainPay'] = $actPrice;
  208. // 满减后应付一并回写,避免混合单按未减的 orderPrice 拉起支付
  209. $data['orderPrice'] = $actPrice;
  210. } else {
  211. noticeUtil::push('订单金额不足满减金额,customId:' . $data['customId'], '15280215347');
  212. }
  213. }
  214. }
  215. }
  216. //将花店每月的总订单数作为编号
  217. $riseNum = StatOrderCountClass::addOrder($shop, $main);
  218. $data['sendNum'] = date("j") . $riseNum;
  219. $data['totalFlow'] = OrderClass::ORDER_TOTAL_FLOW;
  220. $salt = stringUtil::charsShuffleLowerCase(10);
  221. $data['salt'] = $salt;
  222. return self::add($data, true);
  223. }
  224. /**
  225. * 将会员折/满减要剔除的秒杀金额限制在应付范围内。
  226. * 红包把应付压到低于秒杀额时,不能用完整秒杀额去减,否则会抬高应付。
  227. *
  228. * @param mixed $seckillPrice 秒杀商品行合计
  229. * @param mixed $payablePrice 当前应付(含运费包装、已减红包)
  230. * @return string 不超过应付的秒杀剔除额
  231. */
  232. public static function capSeckillExcludePrice($seckillPrice, $payablePrice)
  233. {
  234. $seckillPrice = is_numeric($seckillPrice) ? $seckillPrice : 0;
  235. $payablePrice = is_numeric($payablePrice) ? $payablePrice : 0;
  236. if (bccomp($seckillPrice, '0', 2) <= 0 || bccomp($payablePrice, '0', 2) <= 0) {
  237. return '0.00';
  238. }
  239. if (bccomp($seckillPrice, $payablePrice, 2) > 0) {
  240. return bcadd($payablePrice, '0', 2);
  241. }
  242. return bcadd($seckillPrice, '0', 2);
  243. }
  244. public static function getByOrderSn($orderSn)
  245. {
  246. return self::getByCondition(['orderSn' => $orderSn]);
  247. }
  248. //评价 ssh 2019.12.16
  249. public static function comment($data)
  250. {
  251. $id = $data['id'];
  252. unset($data['id']);
  253. return self::updateById($id, $data);
  254. }
  255. public static function getFullInfo($id)
  256. {
  257. $order = self::getById($id);
  258. if (empty($order)) {
  259. return [];
  260. }
  261. $sn = $order['orderSn'] ?? '';
  262. $order['goodsInfoList'] = OrderGoodsClass::getListBySn($sn);
  263. $order['itemInfoList'] = OrderItemClass::getListBySn($sn);
  264. $workList = WorkClass::getAllByCondition(['orderId' => $id], null, '*');
  265. if (!empty($workList)) {
  266. foreach ($workList as $key => $work) {
  267. $shortCover = $work['cover'] ?? '';
  268. $workList[$key]['shortCover'] = $shortCover;
  269. $workList[$key]['smallCover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_130,w_130";
  270. }
  271. }
  272. $order['workList'] = $workList;
  273. $debtPrice = $order['debtPrice'] ?? 0;
  274. $remainDebtPrice = $order['remainDebtPrice'] ?? 0;
  275. $orderId = $order['id'] ?? 0;
  276. $osList = [];
  277. if ($debtPrice > $remainDebtPrice) {
  278. $osList = OrderSettleClass::getAllByCondition(['orderId' => $orderId, 'status' => 1], null, '*', null, true);
  279. }
  280. //结账记录关系
  281. $order['orderSettleList'] = $osList;
  282. $order['today'] = date("Y-m-d");
  283. $order['tomorrow'] = date("Y-m-d", strtotime("+1 day"));
  284. // 拼团订单附带团状态,供商城订单详情展示
  285. $groupBuyId = intval($order['groupBuyId'] ?? 0);
  286. $order['groupBuyStatus'] = 0;
  287. if ($groupBuyId > 0) {
  288. $groupBuy = GroupBuyClass::getById($groupBuyId);
  289. $order['groupBuyStatus'] = intval($groupBuy['status'] ?? 0);
  290. }
  291. return $order;
  292. }
  293. //订单
  294. public static function getOrderById($id)
  295. {
  296. $order = self::getById($id);
  297. if (empty($order)) {
  298. return [];
  299. }
  300. $sn = $order['orderSn'] ?? '';
  301. $order['goodsInfoList'] = OrderGoodsClass::getListBySn($sn);
  302. return $order;
  303. }
  304. //根据订单查询 ssh 2020.1.4
  305. public static function getOrderBySn($orderSn)
  306. {
  307. $order = self::getByCondition(['orderSn' => $orderSn]);
  308. if (empty($order)) {
  309. return [];
  310. }
  311. $id = $order['id'];
  312. $order['goodsInfoList'] = OrderGoodsClass::getGoodsListById($id);
  313. return $order;
  314. }
  315. //返回随机优惠金额 ssh 2019.9.12
  316. public static function getRandDiscount($amount)
  317. {
  318. if ($amount <= 0) {
  319. return 0;
  320. }
  321. $randDiscount = self::$randDiscount;
  322. krsort($randDiscount);
  323. $rand = 0;
  324. foreach ($randDiscount as $currentAmount => $val) {
  325. if ($amount >= $currentAmount) {
  326. $rand = rand($val[0], $val[1]);
  327. break;
  328. }
  329. }
  330. return $rand / 10;
  331. }
  332. //第三方支付后回调处理流程 ssh 2021.4.30
  333. public static function thirdPay($payWay, $orderSn, $totalFee, $attach, $transactionId)
  334. {
  335. $order = self::getByCondition(['orderSn' => $orderSn], true);
  336. if (empty($order)) {
  337. noticeUtil::push('散客下单,付款成功,支付回调,单号:' . $orderSn . ' 金额:' . $totalFee . ' 回调id:' . $transactionId . ' 附件:' . $attach . ',没有找到订单', '15280215347');
  338. $msg = "没有找到零售订单 orderSn:{$orderSn}";
  339. Yii::info($msg);
  340. util::fail($msg);
  341. }
  342. if ($order->mainPay != $totalFee) {
  343. noticeUtil::push("散客下单,付款成功,支付回调错误,零售订单金额与回调通知金额不一致 orderSn:{$orderSn} {$order->mainPay} {$totalFee} 附件:{$attach}", '15280215347');
  344. $msg = "零售订单金额与回调通知金额不一致 orderSn:{$orderSn} {$order->mainPay} {$totalFee}";
  345. Yii::info($msg);
  346. util::fail($msg);
  347. }
  348. $id = $order->id;
  349. $order = self::getLockById($id);
  350. $date = date("Y-m-d H:i:s");
  351. $order->payTime = $date;
  352. $order->thirdNo = $transactionId;
  353. $order->onlinePay = dict::getDict('onlinePay', 'yes');
  354. $order->save();
  355. $params = [];
  356. self::payAfter($order, $payWay, $params);
  357. }
  358. //订单完成 ssh 2021.4.20
  359. public static function payAfter($order, $payWay, $params = [])
  360. {
  361. if (empty($order)) {
  362. util::fail('没有找到订单');
  363. }
  364. if (!isset($order->status)) {
  365. util::fail('没有找到订单的状态');
  366. }
  367. $orderSn = $order->orderSn ?? '';
  368. if ($order->status == self::ORDER_STATUS_CANCEL) {
  369. $shopId = $order->shopId;
  370. $shop = ShopClass::getById($shopId, true);
  371. if (empty($shop)) {
  372. noticeUtil::push('注意,零售订单:' . $orderSn . ',付款成功但订单已取消,没有找到门店,关键词 cancel_get_money', '15280215347');
  373. util::stop("SUCCESS");
  374. }
  375. Yii::$app->params['errorReport'] = 1;
  376. try {
  377. //恢复取消的订单
  378. self::recoverOrderToPay($order);
  379. noticeUtil::push('注意,零售订单:' . $orderSn . ',付款成功,取消的订单,已恢复 SUCCESS', '15280215347');
  380. } catch (\Exception $exception) {
  381. $ret = HdRefundClass::onlyRefundAmount($shop, $order);
  382. if ($ret['status'] == 0) {
  383. $errMsg = $exception->getMessage();
  384. noticeUtil::push('注意,零售订单:' . $orderSn . ',付款成功但订单取消。订单没有恢复成功,原因' . $errMsg . ',也没有退款成功。请手动处理。关键词 cancel_get_money', '15280215347');
  385. }
  386. util::stop("SUCCESS");
  387. }
  388. }
  389. if ($order->payStatus == 1) {
  390. noticeUtil::push('注意,零售订单:' . $orderSn . ',已经付过款了。已经重新返回 success', '15280215347');
  391. echo "SUCCESS";
  392. exit();
  393. }
  394. $orderId = $order->id ?? 0;
  395. $customId = $order->customId ?? 0;
  396. $order->status = self::ORDER_STATUS_UN_SEND; // 付款后,订单状态设置为:已付款(待配送)
  397. $order->payWay = $payWay;
  398. $order->payStatus = 1;
  399. if (!empty($params['historyDate'])) {
  400. $order->payTime = $params['historyDate'] . ' ' . date("H:i:s");
  401. } else {
  402. $order->payTime = date("Y-m-d H:i:s");
  403. }
  404. $order->stockChange = 1;
  405. $order->save();
  406. $myCustom = CustomClass::getLockById($customId);
  407. if (!empty($myCustom)) {
  408. $customName = $myCustom->name ?? $order->customName ?? '';
  409. $orderSnText = $order->orderSn ?? '';
  410. $shopAdminId = $order->shopAdminId ?? 0;
  411. $shopAdminName = $order->shopAdminName ?? '';
  412. $eventPrefix = $customName;
  413. if ($eventPrefix === '' && $orderSnText !== '') {
  414. $eventPrefix = '客户';
  415. }
  416. $myCustom->recentExpend = date("Y-m-d H:i:s");
  417. $myCustom->visitTime = date("Y-m-d H:i:s");
  418. if ($payWay == dict::getDict('payWay', 'balancePay')) {
  419. $myCustom->recordGrowthAndIntegral = false;
  420. }
  421. $myCustom->buyAmount = bcadd($myCustom->buyAmount, $order->realPrice, 2);
  422. $myCustom->eventRemark = trim($eventPrefix . '下单' . $orderSnText);
  423. $myCustom->relateId = $orderId;
  424. $myCustom->relateType = 1; //关联的表或类别:0.无关联 1.零售订单
  425. $myCustom->staffId = $shopAdminId;
  426. $myCustom->staffName = $shopAdminName;
  427. $myCustom->mainId = $order->mainId;
  428. $myCustom->save();
  429. $hd = HdClass::getLockById($myCustom->hdId);
  430. if (!empty($hd)) {
  431. $hd->expendAmount = bcadd($hd->expendAmount, $order->realPrice, 2);
  432. $hd->save();
  433. }
  434. }
  435. $realPrice = $order->realPrice ?? 0;
  436. $shopId = $order->shopId;
  437. $shop = ShopClass::getLockById($shopId);
  438. if (empty($shop)) {
  439. util::fail('没有找到门店,编号5115');
  440. }
  441. $mainId = $shop->mainId ?? 0;
  442. $main = MainClass::getLockById($mainId);
  443. if (empty($main)) {
  444. util::fail('没有main信息,编号3096');
  445. }
  446. $main->unSendOrder += 1;
  447. $main->unPayOrder -= 1;
  448. $currentTotalIncome = bcadd($main->totalIncome, $realPrice, 2);
  449. $main->totalIncome = $currentTotalIncome;
  450. $main->save();
  451. $capitalType = dict::getDict('capitalType', 'xhOrder', 'id');
  452. $shopAdminId = $order->shopAdminId ?? 0;
  453. $shopAdminName = $order->shopAdminName ?? '';
  454. $sjId = $order->sjId;
  455. $fromType = $order->fromType ?? 1;
  456. $event = !empty($shopAdminId) ? '员工开单' : '客户下单';
  457. $capital = [
  458. 'capitalType' => $capitalType,
  459. 'relateId' => $orderId,
  460. 'io' => 1,
  461. 'totalIncome' => $currentTotalIncome,
  462. 'payWay' => $payWay,
  463. 'event' => $event,
  464. 'sjId' => $sjId,
  465. 'shopId' => $shopId,
  466. 'shopAdminId' => $shopAdminId,
  467. 'shopAdminName' => $shopAdminName,
  468. 'amount' => $realPrice,
  469. 'fromType' => $fromType,
  470. 'mainId' => $mainId,
  471. ];
  472. ShopCapitalClass::addCapital($capital);
  473. //每天和每月收入增加
  474. //StatIncomeClass::updateOrInsert($main, $shop, $realPrice);
  475. //今日订单+1
  476. //StatOrderClass::updateOrInsert($main, $shop);
  477. //销售收入增加
  478. //StatSaleClass::replace($main, $shop, $realPrice);
  479. //各渠道收入金额统计
  480. //StatKdClass::replace($shop, $realPrice, $payWay);
  481. //当天同个人同地址的订单汇总
  482. $sameDate = date("Y_m_d");
  483. $sameAddress = $order->showAddress ?? '';
  484. $addressMd5 = md5($sameAddress);
  485. $sameKey = $customId . '_' . $addressMd5 . '_' . $sameDate . '_retail';
  486. $sameString = Yii::$app->redis->executeCommand('GET', [$sameKey]);
  487. if (!empty($sameString)) {
  488. $newString = $sameString . ',' . $orderId;
  489. $newIdsArray = explode(',', $newString);
  490. if (count($newIdsArray) <= 90) {
  491. Yii::$app->redis->executeCommand('SETEX', [$sameKey, 186400, $newString]);
  492. foreach ($newIdsArray as $currentOrderId) {
  493. OrderClass::updateById($currentOrderId, ['sameTimeIds' => $newString]);
  494. }
  495. //noticeUtil::push($sameKey . '' . $sameAddress . " 花掌柜当天汇总ids:" . $newString, '15280215347');
  496. }
  497. } else {
  498. Yii::$app->redis->executeCommand('SETEX', [$sameKey, 186400, $orderId]);
  499. $order->sameTimeIds = $orderId;
  500. $order->save();
  501. //noticeUtil::push($sameKey . '' . $sameAddress . " 花掌柜当天汇总ids:" . $orderId, '15280215347');
  502. }
  503. //客户在线支付下单增加商家可提现余额
  504. if (isset($order->onlinePay) && $order->onlinePay == dict::getDict('onlinePay', 'yes')) {
  505. $amount = $order->mainPay;
  506. ShopClass::customKdAddBalance($main, $shop, $amount, $order, $capitalType);
  507. }
  508. //客户使用余额付款
  509. if ($payWay == dict::getDict('payWay', 'balancePay')) {
  510. CustomClass::payToChangeBalance($order);
  511. }
  512. //有欠款时
  513. if ($payWay == dict::getDict('payWay', 'debtPay')) {
  514. if (isset($order->remainDebtPrice) && $order->remainDebtPrice > 0) {
  515. CustomClass::skCgDebtAmountAdd($myCustom, $order);
  516. }
  517. }
  518. //全部现金付款余额增加
  519. if ($payWay == dict::getDict('payWay', 'cash')) {
  520. $moneyBalance = bcadd($main->money, $order->mainPay, 2);
  521. $main->money = $moneyBalance;
  522. $main->save();
  523. $moneyEvent = "客户现金下单" . floatval($order->mainPay) . "元(单号 {$order->orderSn})";
  524. $moneyRemark = '';
  525. $change = [
  526. 'relateId' => $orderId,
  527. 'amount' => $order->mainPay,
  528. 'balance' => $moneyBalance,
  529. 'io' => 1,
  530. 'mainId' => $mainId,
  531. 'capitalType' => $capitalType,
  532. 'ptStyle' => dict::getDict('ptStyle', 'hd'),
  533. 'event' => $moneyEvent,
  534. 'remark' => $moneyRemark,
  535. ];
  536. ShopMoneyChangeClass::addData($change);
  537. } else {
  538. //部分现金付款
  539. $orderCash = $order->cash ?? 0;
  540. $orderCash = floatval($orderCash);
  541. if ($orderCash > 0) {
  542. $moneyBalance = bcadd($main->money, $orderCash, 2);
  543. $main->money = $moneyBalance;
  544. $main->save();
  545. $moneyEvent = "客户部分现金付款{$orderCash}元(单号 {$order->orderSn})";
  546. $moneyRemark = '';
  547. $change = [
  548. 'relateId' => $orderId,
  549. 'amount' => $orderCash,
  550. 'balance' => $moneyBalance,
  551. 'io' => 1,
  552. 'mainId' => $mainId,
  553. 'capitalType' => $capitalType,
  554. 'ptStyle' => dict::getDict('ptStyle', 'hd'),
  555. 'event' => $moneyEvent,
  556. 'remark' => $moneyRemark,
  557. ];
  558. ShopMoneyChangeClass::addData($change);
  559. }
  560. }
  561. // 拼团订单:支付成功后计入成团人数并判定是否满团
  562. if (intval($order->groupBuyId ?? 0) > 0) {
  563. GroupBuyClass::onOrderPaid($order);
  564. }
  565. // 零售单支付成功后计分销提成(无分销关系等场景内部抛错,不阻断付款)
  566. DistributionCommissionClass::tryCalcDistributionAfterPay((int)$orderId);
  567. // 商城订单支付成功:标记 xhPsMethod 未达门槛附加费当日决策(与 NoticeController / 余额支付同源)
  568. if ((int)($order->fromType ?? 0) === (int)dict::getDict('fromType', 'mall')) {
  569. PsMethodClass::markUnMeetFeePaidFromOrder($order);
  570. }
  571. }
  572. //转化出送到时间 ssh 2020.3.15
  573. public static function getReachTime($order)
  574. {
  575. $reachTime = '';
  576. if (isset($order['reachDate']) && !empty($order['reachDate'])) {
  577. $prev = date("n-j", strtotime($order['reachDate']));
  578. $periodData = self::$reachPeriod;
  579. $periodKey = $order['reachPeriod'];
  580. $period = isset($periodData[$periodKey]) ? $periodData[$periodKey] : '上午';
  581. $reachTime = $prev . ' ' . $period;
  582. }
  583. return $reachTime;
  584. }
  585. //支付成功获取unionId ssh 2020.5.12
  586. public static function payToUpdateUnionId($merchant, $merchantExtend, $orderSn, $user)
  587. {
  588. $mcId = $merchantExtend['wxPayMerchantId'];
  589. $miniOpenId = isset($user['miniOpenId']) ? $user['miniOpenId'] : '';
  590. $unionId = isset($user['unionId']) ? $user['unionId'] : '';
  591. $userId = $user['id'];
  592. if (empty($unionId)) {
  593. $unionId = miniUtil::getPaidUnionId($merchant, $miniOpenId, $mcId, (string)$orderSn, 0);
  594. if (!empty($unionId)) {
  595. $findUser = UserClass::getByUnionId($unionId);
  596. if (empty($findUser)) {
  597. UserClass::updateByCondition(['id' => $userId], ['unionId' => $unionId]);
  598. } else {
  599. UserClass::mergeUser($findUser, $user);
  600. }
  601. }
  602. }
  603. }
  604. //订单取消 ssh 20220516
  605. public static function setExpire($order, $force = false, $staff = null)
  606. {
  607. $now = time();
  608. if ($order->deadline > $now && $force == false) {
  609. return false;
  610. }
  611. if ($order->status != 1) {
  612. return false;
  613. }
  614. // 红包退回
  615. HbClass::hbBack($order);
  616. $order->status = 5;
  617. $order->cancelTime = date("Y-m-d H:i:s");
  618. $order->save();
  619. $orderSn = $order->orderSn ?? '';
  620. $relateName = $staff->name ?? '系统';
  621. $itemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  622. if (!empty($itemList)) {
  623. foreach ($itemList as $item) {
  624. $ptItemId = $item->ptItemId ?? 0;
  625. $sjId = $item->sjId ?? 0;
  626. $shopId = $item->shopId ?? 0;
  627. $mainId = $item->mainId ?? 0;
  628. $ratio = $item->ratio ?? 20;
  629. $unitType = $item->unitType ?? 0;
  630. if ($unitType == 0) {
  631. $bigNum = $item->num;
  632. $smallNum = 0;
  633. } else {
  634. $bigNum = 0;
  635. $smallNum = $item->num;
  636. }
  637. $itemId = $item->itemId ?? 0;
  638. $stockInfo = ProductClass::addStock($itemId, $bigNum, $smallNum);
  639. ProductClass::tryRecoverLimitBuyWhenStockRollbackFromZero($itemId, $stockInfo['oldStock']);
  640. $recordData = [];
  641. $recordData['sjId'] = $sjId;
  642. $recordData['shopId'] = $shopId;
  643. $recordData['mainId'] = $mainId;
  644. $recordData['itemId'] = $ptItemId;
  645. $recordData['itemNum'] = ProductClass::mergeItemNum($bigNum, $smallNum, $ratio);
  646. $recordData['oldStock'] = $stockInfo['oldStock'];
  647. $recordData['newStock'] = $stockInfo['newStock'];
  648. $recordData['productId'] = $itemId;
  649. $recordData['orderSn'] = $orderSn;
  650. $recordData['relateName'] = $relateName;
  651. StockRecordClass::addSellStockOrderCancelRecord($recordData);
  652. }
  653. }
  654. $goodsList = OrderGoodsClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  655. if (!empty($goodsList)) {
  656. foreach ($goodsList as $goods) {
  657. $goodsId = $goods->goodsId ?? 0;
  658. $num = $goods->num ?? 0;
  659. $mainId = $goods->mainId ?? 0;
  660. $orderSn = $goods->orderSn ?? '';
  661. $shopId = $goods->shopId ?? 0;
  662. $sjId = $goods->sjId ?? 0;
  663. $params = ['reduceSale' => 1];
  664. $respond = \bizHd\goods\classes\GoodsClass::addStock($goodsId, $mainId, $num, $params);
  665. $oldStock = $respond['oldStock'] ?? 0;
  666. $newStock = $respond['newStock'] ?? 0;
  667. $data = [];
  668. $data['sjId'] = $sjId;
  669. $data['shopId'] = $shopId;
  670. $data['mainId'] = $mainId;
  671. $data['orderSn'] = $orderSn;
  672. $data['goodsId'] = $goodsId;
  673. $data['goodsNum'] = $num;
  674. $data['oldStock'] = $oldStock;
  675. $data['newStock'] = $newStock;
  676. $data['relateName'] = $relateName;
  677. GoodsStockRecordClass::cancelOrder($data);
  678. }
  679. }
  680. $shopId = $order->shopId ?? 0;
  681. $shop = ShopClass::getById($shopId, true);
  682. if (!empty($shop)) {
  683. $merchantPrivateKeyPath = Yii::getAlias("@vendor/lakala") . '/production/api_private_key.pem';
  684. $lklCertificatePath = Yii::getAlias("@vendor/lakala") . '/production/lkl-apigw-v1.cer';
  685. $params = [
  686. 'appid' => 'OP00002119',
  687. 'serial_no' => '018b08cfddbd',
  688. 'merchant_no' => $shop->lklSjNo,
  689. 'term_no' => $shop->lklScanTermNo,
  690. 'merchantPrivateKeyPath' => $merchantPrivateKeyPath,
  691. 'lklCertificatePath' => $lklCertificatePath,
  692. ];
  693. $laResource = new Lakala($params);
  694. $closeParams = [
  695. 'orderSn' => $orderSn,
  696. ];
  697. $response = $laResource->close($closeParams);
  698. if (isset($response['code']) == false || $response['code'] != 'BBS00000') {
  699. //noticeUtil::push('零售订单:' . $orderSn . ',关单没有成功。', '15280215347');
  700. } else {
  701. //noticeUtil::push('零售订单:' . $orderSn . ',关单成功。', '15280215347');
  702. }
  703. }
  704. //清理限购缓存
  705. $customId = $order->customId ?? 0;
  706. if (!empty($customId) && !empty($itemList)) {
  707. foreach ($itemList as $item) {
  708. $productId = $item['itemId'];
  709. $num = floor($item['num']);
  710. if (!empty($productId) && $num > 0) {
  711. \bizHd\product\classes\ProductClass::baseClearLimitBuy($productId, $customId, $num);
  712. }
  713. }
  714. }
  715. // 拼团订单超时未支付:成员失效;无人支付则取消团
  716. if (intval($order->groupBuyId ?? 0) > 0) {
  717. GroupBuyClass::onOrderExpired($order);
  718. }
  719. }
  720. // 恢复订单 -- 即:把订单的状态从取消状态变成待付款状态
  721. public static function recoverOrderToPay($order)
  722. {
  723. $now = time();
  724. $order->status = 1;
  725. $order->deadline = $now + 86400;
  726. $order->save();
  727. // 重新占用库存(与取消订单时的库存回滚相反)
  728. $itemList = OrderItemClass::getAllByCondition(['orderSn' => $order->orderSn], null, '*', null, true);
  729. if (!empty($itemList)) {
  730. foreach ($itemList as $item) {
  731. $ptItemId = $item->ptItemId ?? 0;
  732. $sjId = $item->sjId ?? 0;
  733. $shopId = $item->shopId ?? 0;
  734. $mainId = $item->mainId ?? 0;
  735. $ratio = $item->ratio ?? 20;
  736. $unitType = $item->unitType ?? 0;
  737. if ($unitType == 0) {
  738. $bigNum = $item->num;
  739. $smallNum = 0;
  740. } else {
  741. $bigNum = 0;
  742. $smallNum = $item->num;
  743. }
  744. $itemId = $item->itemId ?? 0;
  745. // 重新扣减库存(占用库存)
  746. $stockInfo = ProductClass::decreaseStock($itemId, $bigNum, $smallNum, true);
  747. $recordData = [];
  748. $recordData['sjId'] = $sjId;
  749. $recordData['shopId'] = $shopId;
  750. $recordData['mainId'] = $mainId;
  751. $recordData['itemId'] = $ptItemId;
  752. $recordData['itemNum'] = ProductClass::mergeItemNum($bigNum, $smallNum, $ratio);
  753. $recordData['oldStock'] = $stockInfo['oldStock'];
  754. $recordData['newStock'] = $stockInfo['newStock'];
  755. $recordData['productId'] = $itemId;
  756. $recordData['orderSn'] = $order->orderSn;
  757. $recordData['relateName'] = $order->customName ?? '';
  758. StockRecordClass::hdKdAddRecord($recordData);
  759. }
  760. }
  761. return true;
  762. }
  763. // 扣库存
  764. protected static function decGoodsStock($orderGoods)
  765. {
  766. foreach ($orderGoods as $goods) {
  767. GoodsClass::counters([
  768. 'stock' => -$goods['num']
  769. ], [
  770. 'and',
  771. ['id' => $goods['goodsId']],
  772. ['<>', 'stock', Goods::FULL_STOCK]
  773. ]);
  774. }
  775. }
  776. //云打印 ssh 20210709
  777. public static function onlinePrint($order, $must = false, $port = 'front')
  778. {
  779. if (empty($order)) {
  780. return false;
  781. }
  782. if (!$must) {
  783. if ($order->needPrint != dict::getDict('needPrint', 'need')) {
  784. return false;
  785. }
  786. if ($order->payStatus != 1) {
  787. return false;
  788. }
  789. }
  790. $shopId = $order->shopId ?? 0;
  791. $shop = ShopClass::getById($shopId, true);
  792. $sjId = $shop->sjId ?? 0;
  793. // 复杂分支/关键逻辑:云打印字号与批发端一致,读取门店 fontSize 配置(0 加粗,1 放大)
  794. $fontSizeType = $shop->fontSize ?? 0;
  795. $sj = SjClass::getById($sjId, true);
  796. $sjName = $sj->name ?? '';
  797. $shopName = $shop->shopName ?? '';
  798. $currentName = $shopName == '首店' ? $sjName : $sjName . ' ' . $shopName;
  799. $ext = ShopExtClass::getByCondition(['shopId' => $shopId]);
  800. $printSn = $ext['printSn'] ?? '';
  801. if ($port == 'make') {
  802. $printSn = $ext['makePrintSn'] ?? '';
  803. if ($order->fromType == 4) {
  804. $printSn = $ext['mtPrintSn'] ?? '';
  805. }
  806. $workList = WorkClass::getAllByCondition(['orderId' => $order->id], null, '*', null, true);
  807. $hasSh = 0;
  808. if (!empty($workList)) {
  809. foreach ($workList as $work) {
  810. $sh = $work->sh ?? 0;
  811. if ($sh == 1) {
  812. $hasSh = 1;
  813. }
  814. }
  815. }
  816. if ($hasSh == 1) {
  817. $printSn = $ext['printSn'] ?? '';
  818. }
  819. }
  820. if (empty($printSn)) {
  821. return false;
  822. }
  823. $order->printNum += 1;
  824. $order->save();
  825. $customId = $order->customId ?? 0;
  826. $custom = CustomClass::getById($customId);
  827. $debtAmount = $custom['debtAmount'] ?? 0;
  828. $respond = self::getPrintData($order, $debtAmount);
  829. $fromType = $order->fromType ?? dict::getDict('fromType', 'shop');
  830. $fromTypeMap = dict::getDict('fromTypeMap');
  831. $fromTypeName = $fromTypeMap[$fromType] ?? '门店';
  832. //客服下的单则显示客服号和客户名称
  833. if ($fromType == dict::getDict('fromType', 'friend')) {
  834. $staffName = $order->shopAdminName ?? '';
  835. $bookName = $order->bookName ?? '';
  836. $fromTypeName = $staffName . ' ' . $bookName;
  837. }
  838. $content = '';
  839. //$content .= "<CB>【零售】</CB><BR>";
  840. if ($fromType == dict::getDict('fromType', 'mt')) {
  841. $content .= '<B>美团 ' . $order->thirdSn . '</B><BR>';
  842. if (isset($order->goodsNum) && $order->goodsNum > 1) {
  843. $content .= '<B>美团 ' . $order->thirdSn . ' (' . $order->goodsNum . '份)</B><BR>';
  844. }
  845. $content .= '--------------------------------<BR>';
  846. $content .= date("Y-m-d", strtotime($order->addTime)) . '<BR>';
  847. } else {
  848. $content .= '<CB>' . $currentName . '</CB><BR>';
  849. $content .= '<CB>销售单</CB><BR><BR>';
  850. $content .= '<CB>' . $fromTypeName . ' ' . $respond['sendNum'] . '</CB><BR>';
  851. $content .= '--------------------------------<BR>';
  852. }
  853. $readPeriod = $order->reachPeriod ?? 0;
  854. if ($order->sendType == 1) {
  855. if (!empty($order->reachDate) && $order->reachDate != '0000-00-00') {
  856. $currentReachDate = date("m-d", strtotime($order->reachDate));
  857. $content .= '<B>' . $currentReachDate . ' ' . $readPeriod . '前</B><BR>';
  858. $content .= '<B>到店自取</B><BR><BR>';
  859. } else {
  860. $content .= '<B>到店自取</B><BR><BR>';
  861. }
  862. } else {
  863. if ($order->sendType == 0) {
  864. $content .= '<B>送货上门</B><BR><BR>';
  865. } else if ($order->sendType == 2) {
  866. $content .= '<B>请跑腿送</B><BR><BR>';
  867. } else if ($order->sendType == 3) {
  868. $content .= '<B>物流到付</B><BR><BR>';
  869. } else if ($order->sendType == 4) {
  870. $content .= '<B>快递到付</B><BR><BR>';
  871. } else {
  872. $content .= '';
  873. }
  874. if (!empty($order->reachDate) && $order->reachDate != '0000-00-00') {
  875. $currentReachDate = date("m-d", strtotime($order->reachDate));
  876. $content .= '<B>' . $currentReachDate . ' ' . $readPeriod . '前</B><BR><BR>';
  877. }
  878. }
  879. $defaultCustomId = $shop->defaultCustomId ?? 0;
  880. $fastOrder = $defaultCustomId == $customId ? 1 : 0;
  881. //快捷开单不需要显示这些东西
  882. if ($fastOrder == 0) {
  883. if (!empty($order->receiveUserName)) {
  884. $content .= '收花人:<BR>';
  885. $content .= '<B>' . $order->receiveUserName . '</B><BR>';
  886. }
  887. if (!empty($order->receiveMobile)) {
  888. $content .= '<B>' . $order->receiveMobile . '</B><BR><BR>';
  889. }
  890. if (!empty($order->fullAddress)) {
  891. $content .= '<B>' . $order->fullAddress . '(' . $order->showAddress . ')' . '</B><BR><BR>';
  892. }
  893. if (!empty($order->cardInfo)) {
  894. $content .= '<B>贺卡内容:' . $order->cardInfo . '</B><BR><BR>';
  895. }
  896. if ($order->anonymity == 1) {
  897. $content .= '<B>匿名派送!!</B><BR><BR>';
  898. } else {
  899. if (!empty($order->bookMobile)) {
  900. $bookName = $order->bookName ?? '';
  901. $bookMobile = $order->bookMobile;
  902. $content .= '订花人:<BR>';
  903. if (!empty($bookName)) {
  904. $content .= '<B>' . $bookName . '</B><BR>';
  905. }
  906. $content .= '<B>' . $bookMobile . '</B><BR>';
  907. }
  908. }
  909. }
  910. if (!empty($respond['remark'])) {
  911. $content .= '<BR>';
  912. $content .= '备注:<BR>';
  913. $content .= '<B>' . $respond['remark'] . '</B><BR>';
  914. }
  915. $content .= '<BR>';
  916. $content .= '商品 数量/单价 金额 <BR>';
  917. $content .= '--------------------------------<BR>';
  918. if (!empty($respond['product'])) {
  919. foreach ($respond['product'] as $current) {
  920. $content = self::printGroup($current, $content, $fontSizeType);
  921. }
  922. }
  923. if (!empty($respond['refund'])) {
  924. $content .= '<B>已退款:</B><BR>';
  925. foreach ($respond['refund'] as $current) {
  926. //58mm的机器,一行打印16个汉字,32个字母
  927. $name = $current['name'] ?? '';
  928. $content .= $name . '<BR>';
  929. $name = str_repeat(' ', 10);
  930. $productNum = $current['num'] ?? '';
  931. $blankNum = bcsub(12, strlen($productNum));
  932. if ($blankNum > 0) {
  933. $productNum = $productNum . str_repeat(' ', $blankNum);
  934. }
  935. $productPrice = $current['price'] ?? '';
  936. $blankNum = bcsub(7, strlen($productPrice));
  937. if ($blankNum > 0) {
  938. $productPrice = $productPrice . str_repeat(' ', $blankNum);
  939. }
  940. $content .= $name . " " . $productNum . ' ' . $productPrice . '<BR>';
  941. }
  942. $content .= '--------------------------------<BR>';
  943. }
  944. if (isset($order->goodsPrice) && $order->goodsPrice > 0) {
  945. $content .= '商品合计:' . floatval($order->goodsPrice) . '<BR>';
  946. }
  947. if (isset($respond['sendCost']) && $respond['sendCost'] > 0 && $order->sendType == 2) {
  948. $content .= '运费:' . floatval($respond['sendCost']) . '<BR>';
  949. }
  950. if (isset($order->serviceFee) && $order->serviceFee > 0) {
  951. $content .= '手续费:' . floatval($order->serviceFee) . '<BR>';
  952. }
  953. if (isset($order->labourCost) && $order->labourCost > 0) {
  954. $content .= '包装费:' . floatval($order->labourCost) . '<BR>';
  955. }
  956. if (isset($order->prePrice) && $order->prePrice > 0) {
  957. $content .= '总计:' . floatval($order->prePrice) . '<BR>';
  958. }
  959. if (!empty($respond['discountAmount']) && $respond['discountAmount'] > 0) {
  960. $content .= '优惠扣除:-' . floatval($respond['discountAmount']) . '<BR>';
  961. }
  962. $content .= '<B>金额:' . floatval($respond['orderPrice']) . '</B><BR>';
  963. if (isset($respond['refundPrice']) && $respond['refundPrice'] > 0) {
  964. $content .= '退款金额:' . floatval($respond['refundPrice']) . '<BR>';
  965. }
  966. if (isset($respond['debt']) && $respond['debt'] == 1) {
  967. $content .= '实付金额:0<BR>';
  968. } else {
  969. $content .= '实付金额:' . floatval($respond['realPrice']) . '<BR>';
  970. }
  971. if (isset($order->remainDebtPrice) && $order->remainDebtPrice > 0) {
  972. $content .= '<B>待付尾款:' . floatval($order->remainDebtPrice) . '</B><BR>';
  973. }
  974. $content .= '--------------------------------<BR>';
  975. $balance = $custom['balance'] ?? 0;
  976. $balance = floatval($balance);
  977. if ($balance > 0) {
  978. $content .= '当前账户余额:' . $balance . '元<BR>';
  979. }
  980. $content .= '订单日期:' . $order->addTime . '<BR>';
  981. $content .= '订单编号:' . $respond['orderSn'] . '<BR>';
  982. $content .= '门店名称:' . $currentName . '<BR>';
  983. $content .= "<BR>";
  984. //noticeUtil::push($content, '15280215347');
  985. $p = new printUtil($printSn);
  986. $orderSn = $order->orderSn ?? '';
  987. $workList = WorkClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  988. if (!empty($workList)) {
  989. $content .= "<BR>";
  990. $content .= '--------------------------------<BR>';
  991. foreach ($workList as $work) {
  992. $goodsSn = $work->goodsSn ?? '';
  993. $sn = $work->sn ?? '';
  994. $content .= '<B>制作号:' . $sn . '<B>';
  995. // 1-523 有-特殊符号,使用飞鹅自带的函数处理
  996. $content .= $p->bar_code($goodsSn);
  997. $content .= "<BR>";
  998. }
  999. }
  1000. $p->printMsg($content);
  1001. }
  1002. //打印数据 ssh 20210702
  1003. public static function getPrintData($order, $debtAmount)
  1004. {
  1005. $orderSn = $order->orderSn ?? '';
  1006. $printProduct = [];
  1007. $orderItemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*');
  1008. if (!empty($orderItemList)) {
  1009. foreach ($orderItemList as $itemKey => $itemVal) {
  1010. $unitName = $itemVal['unitName'] ?? '扎';
  1011. $unitPrice = $itemVal['unitPrice'] ? floatval($itemVal['unitPrice']) : 0;
  1012. $itemNum = $itemVal['num'] ?? 0;
  1013. $printProduct[] = [
  1014. 'name' => $itemVal['name'] ?? '',
  1015. // 第二行小字:数量 * 单价 = 金额,排版与批发端一致
  1016. 'num' => floatval($itemNum) . $unitName . ' * ' . $unitPrice . '元',
  1017. 'price' => floatval($itemVal['price']),
  1018. 'unitPrice' => $unitPrice,
  1019. 'itemNum' => $itemNum,
  1020. 'refundNum' => $itemVal['refundNum'] ?? 0,
  1021. 'unitName' => $unitName,
  1022. 'remark' => $itemVal['remark'] ?? '',
  1023. 'ratioType' => $itemVal['ratioType'] ?? null,
  1024. 'ratio' => $itemVal['ratio'] ?? '',
  1025. ];
  1026. }
  1027. }
  1028. $orderGoodsList = OrderGoodsClass::getAllByCondition(['orderSn' => $orderSn], null, '*');
  1029. if (!empty($orderGoodsList)) {
  1030. foreach ($orderGoodsList as $itemKey => $itemVal) {
  1031. $unitName = $itemVal['unitName'] ?? '份';
  1032. $unitPrice = $itemVal['unitPrice'] ? floatval($itemVal['unitPrice']) : 0;
  1033. $itemNum = $itemVal['num'] ?? 0;
  1034. $name = $itemVal['name'] ?? '';
  1035. $sn = $itemVal['sn'] ?? '';
  1036. if (!empty($sn)) {
  1037. $name = '#' . $sn . ' ' . $name;
  1038. }
  1039. $printProduct[] = [
  1040. 'name' => $name,
  1041. 'num' => floatval($itemNum) . $unitName . ' * ' . $unitPrice . '元',
  1042. 'price' => floatval($itemVal['price']),
  1043. 'unitPrice' => $unitPrice,
  1044. 'itemNum' => $itemNum,
  1045. 'refundNum' => 0,
  1046. 'unitName' => $unitName,
  1047. 'remark' => '',
  1048. 'ratioType' => null,
  1049. 'ratio' => '',
  1050. ];
  1051. }
  1052. }
  1053. $sendNum = $order['sendNum'] ?? '';
  1054. //退款记录
  1055. $refundList = [];
  1056. $printData = [
  1057. 'address' => '',
  1058. 'sendCost' => $order->sendCost ?? '0.00',
  1059. 'prePrice' => $order->prePrice ?? '0.00',
  1060. 'orderPrice' => $order->orderPrice ?? '0',
  1061. 'discountAmount' => $order->discountAmount ?? '0.00',
  1062. 'realPrice' => $order->realPrice ?? '0.00',
  1063. 'refundPrice' => $order->refundPrice ?? '0.00',
  1064. 'debt' => $order->debt ?? 0,
  1065. 'orderSn' => $order->orderSn ?? '',
  1066. 'date' => $order->addTime ?? '',
  1067. 'remark' => $order->remark ?? '',
  1068. 'custom' => [
  1069. 'customName' => $order->customName ?? '',
  1070. 'customMobile' => $order->customMobile ?? '',
  1071. 'fullAddress' => $order->fullAddress ?? '',
  1072. ],
  1073. 'product' => $printProduct,
  1074. 'refund' => $refundList,
  1075. 'sendNum' => $sendNum,
  1076. 'debtAmount' => $debtAmount,
  1077. ];
  1078. return $printData;
  1079. }
  1080. /**
  1081. * 职责:组装零售云打印单条商品行,排版与批发端 printGroup 一致
  1082. * 入参:$current 商品行数据, $content 已拼接内容, $fontSizeType 字号类型(0 加粗,1 放大)
  1083. * 返回:拼接后的打印内容
  1084. * 关键边界:第一行「数量+单位+名称」大字,第二行「数量*单价=金额」小字
  1085. */
  1086. public static function printGroup($current, $content, $fontSizeType = 0)
  1087. {
  1088. //58mm的机器,一行打印16个汉字,32个字母
  1089. $productPrice = $current['price'] ?? '';
  1090. $unitPrice = $current['unitPrice'] ?? '';
  1091. $name = $current['name'] ?? '';
  1092. if (floatval($unitPrice) == 0.01) {
  1093. $name = $name . '(送)';
  1094. }
  1095. $productNum = $current['num'] ?? '';
  1096. $itemNum = $current['itemNum'] ?? 0;
  1097. $refundNum = $current['refundNum'] ?? 0;
  1098. $unitName = $current['unitName'] ?? '扎';
  1099. $remark = $current['remark'] ?? '';
  1100. $ratioType = $current['ratioType'] === null ? -1 : intval($current['ratioType']);
  1101. $ratio = $current['ratio'] ?? '';
  1102. $lastNum = bcsub($itemNum, $refundNum);
  1103. // 第一行:数量在前,名称在后(与批发端一致)
  1104. if (!empty($remark)) {
  1105. $show = $lastNum . $unitName . ' ' . $name . "【" . $remark . "】";
  1106. } else {
  1107. $show = $lastNum . $unitName . ' ' . $name;
  1108. }
  1109. if ($fontSizeType == 1) {
  1110. $content .= '<L>' . $show . '</L><BR>';
  1111. } else {
  1112. $content .= '<B>' . $show . '</B><BR>';
  1113. }
  1114. if ($refundNum > 0) {
  1115. $content .= '(买' . $itemNum . $unitName . ' 退' . $refundNum . $unitName . ')<BR>';
  1116. }
  1117. // 第二行:小字体的数量和价格明细
  1118. if (floatval($unitPrice) == 0.01) {
  1119. $content .= $productNum . ' = ' . $productPrice . '元 赠送价<BR>';
  1120. } else {
  1121. $content .= $productNum . ' = ' . $productPrice . '元 ' . ($ratioType == 0 ? $ratio . '支装' : ($ratioType == 1 ? '若干支装' : '')) . '<BR>';
  1122. }
  1123. $content .= '--------------------------------<BR>';
  1124. return $content;
  1125. }
  1126. //扫码收款的,减少库存 ssh 20250822
  1127. public static function reduceMyStock($data, $shop, $custom)
  1128. {
  1129. $mainId = $shop->mainId;
  1130. $customId = $custom->id;
  1131. $orderId = $data['orderId'] ?? '';
  1132. $sjId = $shop->sjId;
  1133. $hdId = $custom->hdId;
  1134. $shopId = $shop->id;
  1135. $order = self::getById($orderId, true);
  1136. if (empty($order)) {
  1137. util::fail('没有找到订单');
  1138. }
  1139. if ($order->mainId != $shop->mainId) {
  1140. util::fail('并不是你的订单');
  1141. }
  1142. if ($order->repeat == 0) {
  1143. util::fail('已经扣过了');
  1144. }
  1145. if ($order->tkPrice > 0) {
  1146. util::fail('已经发生退款,无法操作');
  1147. }
  1148. if ($order->customId != $customId) {
  1149. util::fail('订单对应客户有问题,无法扣库存,编号:' . $customId . ' ' . $order->customId);
  1150. }
  1151. $orderSn = $order->orderSn ?? '';
  1152. $product = $data['product'] ?? [];
  1153. if (empty($product)) {
  1154. util::fail('请选择商品呢');
  1155. }
  1156. $orderItemList = OrderItemClass::getAllbyCondition(['orderSn' => $orderSn], null, '*', null, true);
  1157. if (!empty($orderItemList)) {
  1158. foreach ($orderItemList as $orderItem) {
  1159. $orderItem->unitPrice = 0;
  1160. $orderItem->save();
  1161. }
  1162. }
  1163. $actPrice = $order->actPrice ?? 0;
  1164. if ($actPrice <= 0) {
  1165. util::fail('订单金额为0');
  1166. }
  1167. $ids = array_column($product, 'productId');
  1168. $productInfo = ItemClass::getByIds($ids, null, 'id');
  1169. $goodsPrice = 0;
  1170. foreach ($product as $key => $val) {
  1171. $property = $val['property'] ?? 0;
  1172. if ($property != 1) {
  1173. util::fail('暂时只支持花材');
  1174. }
  1175. $unitPrice = $val['unitPrice'] ?? 0;
  1176. $unitType = $val['unitType'] ?? 0;
  1177. $currentId = $val['productId'] ?? 0;
  1178. $num = $val['num'] ?? 0;
  1179. $currentInfo = $productInfo[$currentId] ?? [];
  1180. if (empty($currentInfo)) {
  1181. util::fail('存在无效花材,编号:' . $currentId);
  1182. }
  1183. $name = $currentInfo['name'] ?? '';
  1184. $cover = $currentInfo['cover'] ?? '';
  1185. $ratio = $currentInfo['ratio'] ?? 20;
  1186. $itemMainId = $currentInfo['mainId'] ?? 0;
  1187. if ($itemMainId != $mainId) {
  1188. util::fail('不是您的花材,请勿使用,编号:' . $mainId . ' ' . $itemMainId);
  1189. }
  1190. if ($unitType == 0) {
  1191. $unitName = $currentInfo['bigUnit'] ?? '';
  1192. $unitId = $currentInfo['bigUnitId'] ?? 0;
  1193. $totalNum = $num;
  1194. } else {
  1195. $unitName = $currentInfo['smallUnit'] ?? '';
  1196. $unitId = $currentInfo['smallUnitId'] ?? 0;
  1197. $totalNum = bcdiv($num, $ratio, 2);
  1198. }
  1199. $ptItemId = $currentInfo['itemId'] ?? 0;
  1200. $classId = $currentInfo['classId'] ?? 0;
  1201. $belongCost = $currentInfo['belongCost'] ?? 0;
  1202. $currentPrice = bcmul($unitPrice, $num, 2);
  1203. $goodsPrice = bcadd($goodsPrice, $currentPrice, 2);
  1204. $currentItemData = [
  1205. 'name' => $name,
  1206. 'cover' => $cover,
  1207. 'ratio' => $ratio,
  1208. 'unitType' => $unitType,
  1209. 'unitName' => $unitName,
  1210. 'unitId' => $unitId,
  1211. 'unitPrice' => $unitPrice,
  1212. 'num' => $num,
  1213. 'orderSn' => $orderSn,
  1214. 'itemId' => $currentId,
  1215. 'ptItemId' => $ptItemId,
  1216. 'totalNum' => $totalNum,
  1217. 'totalPrice' => 0,
  1218. 'customId' => $customId,
  1219. 'hdId' => $hdId,
  1220. 'sjId' => $sjId,
  1221. 'shopId' => $shopId,
  1222. 'mainId' => $mainId,
  1223. 'classId' => $classId,
  1224. 'price' => $currentPrice,
  1225. 'belongCost' => $belongCost,
  1226. ];
  1227. //库存变化在这里
  1228. OrderItemClass::addData($currentItemData, $custom);
  1229. }
  1230. $labourCost = 0;
  1231. $discountType = 0;
  1232. $discountAmount = 0;
  1233. if ($goodsPrice > $actPrice) {
  1234. $prePrice = $goodsPrice;
  1235. $discountAmount = bcsub($goodsPrice, $actPrice, 2);
  1236. if ($discountAmount > 0) {
  1237. $discountType = 3;
  1238. }
  1239. } else {
  1240. $prePrice = $actPrice;
  1241. $labourCost = bcsub($actPrice, $goodsPrice, 2);
  1242. }
  1243. $order->goodsPrice = $goodsPrice;
  1244. $order->prePrice = $prePrice;
  1245. $order->labourCost = $labourCost;
  1246. $order->discountAmount = $discountAmount;
  1247. $order->discountType = $discountType;
  1248. $order->repeat = 0;
  1249. $order->save();
  1250. return $order;
  1251. }
  1252. public static function debtCount($mainId)
  1253. {
  1254. $debtAmount = 0;
  1255. $orders = self::getAllByCondition(['mainId' => $mainId, 'status' => 4, 'debt' => 1], null, 'remainDebtPrice', null, true);
  1256. foreach ($orders as $order) {
  1257. $remainDebtPrice = $order->remainDebtPrice ?? 0;
  1258. $debtAmount = bcadd($debtAmount, $remainDebtPrice, 2);
  1259. }
  1260. return $debtAmount;
  1261. }
  1262. }