PurchaseClass.php 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. <?php
  2. namespace bizHd\purchase\classes;
  3. use biz\ghs\classes\GhsClass;
  4. use biz\product\classes\XjClass;
  5. use biz\shop\classes\ShopCapitalClass;
  6. use biz\shop\classes\ShopClass;
  7. use biz\shop\classes\ShopCouponClass;
  8. use biz\sj\classes\SjClass;
  9. use biz\stat\classes\StatCgClass;
  10. use biz\stat\classes\StatCgGhsClass;
  11. use biz\stat\classes\StatOutClass;
  12. use biz\stock\classes\StockClass;
  13. use biz\wx\classes\WxMessageClass;
  14. use bizGhs\admin\classes\AdminClass;
  15. use bizGhs\custom\classes\CustomClass;
  16. use bizGhs\order\traits\OrderTrait;
  17. use bizGhs\product\classes\ProductClass;
  18. use bizGhs\stock\classes\StockRecordClass;
  19. use bizGhs\stock\services\StockRecordService;
  20. use bizHd\cg\classes\CgRefundClass;
  21. use bizHd\cg\classes\CgXjClass;
  22. use bizHd\shop\classes\MainClass;
  23. use bizHd\stat\classes\StatIncomeClass;
  24. use bizHd\wx\classes\WxOpenClass;
  25. use common\components\dict;
  26. use common\components\imgUtil;
  27. use common\components\mapUtil;
  28. use common\components\orderSn;
  29. use common\components\util;
  30. use bizHd\base\classes\BaseClass;
  31. use Yii;
  32. class PurchaseClass extends BaseClass
  33. {
  34. use OrderTrait;
  35. public static $baseFile = '\bizHd\purchase\models\Purchase';
  36. //订单状态 1待付款,待确认,2待配送,3配送中,4已完成,5取消,失败
  37. const STATUS_UN_PAY = 1;
  38. const STATUS_UN_SEND = 2;
  39. const STATUS_SENDING = 3;
  40. const STATUS_COMPLETE = 4;
  41. const STATUS_CANCEL = 5;
  42. //未知
  43. const DEBT_UNKNOWN = 0;
  44. //欠款
  45. const DEBT_YES = 1;
  46. //没有欠款
  47. const DEBT_NO = 2;
  48. //配送
  49. const GET_TYPE_SEND = 1;
  50. //自取
  51. const GET_TYPE_SELF_GET = 2;
  52. const REFUND_NO = 1;
  53. const REFUND_YES = 2;
  54. //计算距离和运费 ssh 20221003
  55. public static function getDistanceFee($shop, $ghsShop, $weight)
  56. {
  57. $shopLat = isset($shop->lat) ? $shop->lat : '';
  58. $shopLong = isset($shop->long) ? $shop->long : '';
  59. $ghsShopLat = isset($ghsShop->lat) ? $ghsShop->lat : '';
  60. $ghsShopLong = isset($ghsShop->long) ? $ghsShop->long : '';
  61. //跑腿费用设置,基础费用8—10元,3—100公里每公里增加2元,超过5公斤,5—21公斤每公斤增加2元
  62. //起步价
  63. $baseFee = 9;
  64. $distance = mapUtil::calculateDistance($shopLong, $shopLat, $ghsShopLong, $ghsShopLat);
  65. //每公里增加多少元
  66. $perKmFee = 2;
  67. //每公斤增加多少元
  68. $perKiloFee = 2;
  69. //免费距离
  70. $freeDistance = 2;
  71. $freeKm = 5;
  72. $addDistanceFee = 0;
  73. if ($distance > $freeDistance * 1000) {
  74. $addDistanceFee = ceil(($distance - $freeDistance * 1000) / 1000) * $perKmFee;
  75. }
  76. $addWeightFee = 0;
  77. if ($weight > $freeKm) {
  78. $addWeightFee = ceil(bcsub($weight, $freeKm, 2)) * $perKiloFee;
  79. }
  80. $addFee = bcadd($addDistanceFee, $addWeightFee, 2);
  81. $totalFee = bcadd($baseFee, $addFee, 2);
  82. $showDistance = sprintf("%.1f", ($distance / 1000));
  83. return ['distance' => $distance, 'showDistance' => $showDistance, 'fee' => $totalFee];
  84. }
  85. //到货之后 ssh 20220321
  86. public static function arrival($cg, $data)
  87. {
  88. if ($cg->stockChange == 1) {
  89. util::fail('您已操作过了');
  90. }
  91. $sjId = $data['sjId'] ?? 0;
  92. $shopId = $data['shopId'] ?? 0;
  93. //product [{"productId":"3674","num":0,"price":1}]
  94. $product = $data['product'] ?? '';
  95. if (empty($product)) {
  96. util::fail('请填写成本价和到货数量');
  97. }
  98. $ghsName = $cg->ghsName ?? '';
  99. $orderSn = $cg->orderSn ?? '';
  100. $list = PurchaseItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  101. if (empty($list)) {
  102. util::fail('没有找到花材哦');
  103. }
  104. $weight = 0;
  105. $itemPrice = 0;
  106. foreach ($list as $key => $val) {
  107. $productId = $val->productId ?? 0;
  108. if (isset($product[$productId]) == false) {
  109. util::fail('没有找到对应采购花材');
  110. }
  111. $num = $product[$productId]['num'] ?? 0;
  112. $price = $product[$productId]['price'] ?? 0;
  113. if ($price <= 0) {
  114. util::fail('花材金额需要大于0');
  115. }
  116. $totalPrice = bcmul($num, $price, 2);
  117. $itemPrice = bcadd($itemPrice, $totalPrice, 2);
  118. $val->price = $price;
  119. $val->itemNum = $num;
  120. $val->preTotalPrice = $totalPrice;
  121. $val->totalPrice = $totalPrice;
  122. $val->xhNum = $num;
  123. $val->xhUnitPrice = $price;
  124. $val->xhPrice = $totalPrice;
  125. $val->save();
  126. $unitWeight = $val->unitWeight ?? 0;
  127. $currentWeight = bcmul($num, $unitWeight, 2);
  128. $weight = bcadd($weight, $currentWeight, 2);
  129. $unitType = $val->xhUnitType ?? 0;
  130. $bigNum = 0;
  131. $smallNum = 0;
  132. if ($unitType == dict::getDict('unitType', 'big')) {
  133. $bigNum = $num;
  134. } else {
  135. $smallNum = $num;
  136. }
  137. //增加库存
  138. $option = ['relateName' => $ghsName];
  139. StockClass::purchaseItem($orderSn, $sjId, $shopId, $productId, $bigNum, $smallNum, $option);
  140. }
  141. $cg->itemPrice = $itemPrice;
  142. $sendCost = 0;
  143. $currentPrice = bcadd($itemPrice, $sendCost, 2);
  144. $kiloFee = $data['kiloFee'] ?? 0;
  145. $miniKilo = $data['miniKilo'] ?? 0;
  146. $calcWeight = $weight > $miniKilo ? $weight : $miniKilo;
  147. $allKiloFee = bcmul($calcWeight, $kiloFee, 2);
  148. $currentPrice = bcadd($currentPrice, $allKiloFee, 2);
  149. $cg->prePrice = $currentPrice;
  150. $cg->orderPrice = $currentPrice;
  151. $cg->actPrice = $currentPrice;
  152. $cg->realPrice = $currentPrice;
  153. $cg->stockChange = 1;
  154. $cg->status = self::STATUS_COMPLETE;
  155. $cg->save();
  156. $mainId = $cg->mainId ?? 0;
  157. $sjId = $cg->sjId ?? 0;
  158. $shopId = $cg->shopId ?? 0;
  159. $cgId = $cg->id ?? 0;
  160. $saleRefundId = $data['saleRefundId'] ?? 0;
  161. $shop = ShopClass::getLockById($shopId);
  162. if (empty($shop)) {
  163. util::fail('没有找到零售店的门店');
  164. }
  165. $main = MainClass::getLockById($mainId);
  166. if (empty($main)) {
  167. util::fail('没有main信息');
  168. }
  169. $main->cgUnSend -= 1;
  170. $main->cgFinish += 1;
  171. $main->save();
  172. $cgRefund = null;
  173. $bookPrice = $cg->bookPrice ?? 0;
  174. if ($bookPrice == $currentPrice) {
  175. return ['refund' => $cgRefund];
  176. } elseif ($bookPrice > $currentPrice) {
  177. //退款
  178. $refundPrice = bcsub($bookPrice, $currentPrice, 2);
  179. $book = 1;
  180. $refundOrderSn = orderSn::getCgRefundSn();
  181. $refundType = CgRefundClass::REFUND_TYPE_MONEY;
  182. $refundData = [
  183. 'book' => $book,
  184. 'mainId' => $mainId,
  185. 'orderSn' => $refundOrderSn,
  186. 'cgId' => $cgId,
  187. 'status' => CgRefundClass::STATUS_UN_COMPLETE,
  188. 'shopAdminId' => 0,
  189. 'shopAdminName' => '',
  190. 'refundType' => $refundType,
  191. 'refundPrice' => $refundPrice,
  192. 'saleRefundId' => $saleRefundId,
  193. 'sjId' => $sjId,
  194. 'shopId' => $shopId,
  195. ];
  196. $cgRefund = CgRefundClass::add($refundData, true);
  197. //门店收入增加
  198. $currentTotalIncome = bcadd($main->totalIncome, $refundPrice, 2);
  199. $main->totalIncome = $currentTotalIncome;
  200. $main->save();
  201. //供货商退款,向供货商采购总金额减少
  202. StatCgClass::replace($main, $shop, $refundPrice, 0, false);
  203. //供货商退款,按供货商分别采购的金额减少
  204. StatCgGhsClass::hdCgGhsReplace(false, $cg, $refundPrice, 0);
  205. $currentType = dict::getDict('capitalType', 'hdBookRefund', 'id');
  206. $sjId = $cg->sjId ?? 0;
  207. $shopId = $cg->shopId ?? 0;
  208. $event = "预订单{$orderSn}多退少补({$ghsName})";
  209. $capitalData = [
  210. 'capitalType' => $currentType,
  211. 'io' => 1,
  212. 'totalIncome' => $currentTotalIncome,
  213. 'payWay' => 0,
  214. 'amount' => $refundPrice,
  215. 'sjId' => $sjId,
  216. 'shopId' => $shopId,
  217. 'event' => $event,
  218. 'mainId' => $mainId,
  219. ];
  220. ShopCapitalClass::addCapital($capitalData);
  221. //收入统计
  222. StatIncomeClass::updateOrInsert($main, $shop, $refundPrice);
  223. //微信收款的原路退回
  224. ini_set('date.timezone', 'Asia/Shanghai');
  225. $wx = Yii::getAlias("@vendor/wxPayApi_v3.0.10");
  226. require_once($wx . '/lib/WxPay.Api.php');
  227. require_once($wx . '/example/WxPay.Config.php');
  228. $totalFee = $cg->bookPrice * 100;
  229. $refundFee = $refundPrice * 100;
  230. $transaction_id = $cg->thirdNo ?? '';
  231. $merchantExt = WxOpenClass::getWxInfo();
  232. $mid = $merchantExt['wxPayMerchantId'] ?? '';
  233. $appId = $merchantExt['miniAppId'] ?? '';
  234. $key = $merchantExt['wxPayKey'] ?? '';
  235. $input = new \WxPayRefund();
  236. $input->SetTransaction_id($transaction_id);
  237. $input->SetTotal_fee($totalFee);
  238. $input->SetRefund_fee($refundFee);
  239. $input->SetNotify_url(Yii::$app->params['hdHost'] . '/notice/wx-refund-callback/');
  240. $config = new \WxPayConfig();
  241. $config->SetAppId($appId);
  242. $config->SetMerchantId($mid);
  243. $config->SetKey($key);
  244. $input->SetOut_refund_no($refundOrderSn);
  245. $input->SetOp_user_id($mid);
  246. $return = \WxPayApi::refund($config, $input);
  247. if (isset($return['return_code']) == false || $return['return_code'] != 'SUCCESS') {
  248. $msg = $return['return_msg'] ?? '';
  249. Yii::info("退款失败 cgId:{$cgId} msg:{$msg}");
  250. util::fail('退款失败');
  251. }
  252. $wxRefundId = $return['refund_id'] ?? '';
  253. $cgRefund->thirdRefundNo = $wxRefundId;
  254. $cgRefund->save();
  255. $cg->refundPrice = $refundPrice;
  256. $cg->tkPrice = bcadd($cg->tkPrice, $refundPrice, 2);
  257. $cg->refund = self::REFUND_YES;
  258. $cg->save();
  259. } else {
  260. //欠款
  261. $currentDebt = bcsub($currentPrice, $bookPrice, 2);
  262. $cg->debtPrice = $currentDebt;
  263. $cg->remainDebtPrice = $currentDebt;
  264. $cg->debt = PurchaseClass::DEBT_YES;
  265. $cg->save();
  266. $payWay = dict::getDict('payWay', 'debtPay');
  267. $ghsId = $cg->ghsId ?? 0;
  268. $ghs = GhsClass::getLockById($ghsId);
  269. if (empty($ghs)) {
  270. util::fail('没有找到供货商');
  271. }
  272. \bizHd\ghs\classes\GhsClass::cgDebtAmountAdd($ghs, $cg, true);
  273. //支出统计
  274. StatOutClass::updateOrInsert($main, $shop, $currentDebt);
  275. //支出流水
  276. $capitalType = dict::getDict('capitalType', 'hdBookFinalPay', 'id');
  277. $sjId = $cg->sjId ?? 0;
  278. $shopId = $cg->shopId ?? 0;
  279. $currentExpend = bcadd($main->totalExpend, $currentDebt, 2);
  280. $main->totalExpend = $currentExpend;
  281. $main->save();
  282. $event = "预订单{$orderSn}补尾款欠款";
  283. $capitalData = [
  284. 'capitalType' => $capitalType,
  285. 'io' => 0,
  286. 'totalExpend' => $currentExpend,
  287. 'payWay' => $payWay,
  288. 'amount' => $currentDebt,
  289. 'sjId' => $sjId,
  290. 'shopId' => $shopId,
  291. 'event' => $event,
  292. 'mainId' => $mainId,
  293. ];
  294. ShopCapitalClass::addCapital($capitalData);
  295. //补款给供货商,采购总金额增加
  296. StatCgClass::replace($main, $shop, $currentDebt, 0, true);
  297. //补款给供货商,按供货商分别统计采购量增加
  298. StatCgGhsClass::hdCgGhsReplace(true, $cg, $currentDebt, 0);
  299. }
  300. return ['refund' => $cgRefund];
  301. }
  302. //添加采购 ssh 2021.1.18
  303. public static function addPurchase($data, $ghs)
  304. {
  305. $orderSn = orderSn::getPurchaseSn();
  306. $data['orderSn'] = $orderSn;
  307. $prePrice = 0;
  308. $sendTimeWant = isset($data['sendTimeWant']) && !empty($data['sendTimeWant']) ? $data['sendTimeWant'] : date("Y-m-d");
  309. if ($sendTimeWant < date("Y-m-d")) {
  310. util::fail('您选了过去时间');
  311. }
  312. $data['sendTimeWant'] = $sendTimeWant;
  313. if (isset($data['product']) == false || empty($data['product'])) {
  314. util::fail('请选择花材');
  315. }
  316. $productList = $data['product'];
  317. $productList = self::mergeItemInfo($productList);
  318. $data['kindNum'] = count($productList); //多少种花材
  319. //传过来的是供货商的productId,需要转换为零售端的productId
  320. //数据格式 [{"productId":"113","bigNum":1,"smallNum":0,"classId":"-2","hdProductId":1}]
  321. $shopId = $data['shopId'] ?? 0;
  322. $sjId = $data['sjId'] ?? 0;
  323. $mainId = $data['mainId'] ?? 0;
  324. $productList = ProductClass::toggleProductList($productList, $shopId, $sjId, $mainId);
  325. $productData = self::getProductMapData($productList, "productId");
  326. $hdProductData = self::getProductMapData($productList, "hdProductId");
  327. $giveLevel = $ghs['giveLevel'] ?? 0;
  328. $priceMap = CustomClass::$levelPriceKeyMap;
  329. $addPriceMap = CustomClass::$levelAddPriceKeyMap;
  330. //计算价格= 各个productId的price*num(bigNum,smallNum) + sendCost(配送费)
  331. $bigNum = 0; //总共多少扎
  332. $smallNum = 0; //总共多少支
  333. $totalWeight = 0;
  334. foreach ($productList as $key => $product) {
  335. $currentBigNum = $product['bigNum'] ?? 0;
  336. $currentSmallNum = $product['smallNum'] ?? 0;
  337. $bigNum += $product['bigNum'] ?? 0;
  338. $smallNum += $product['smallNum'] ?? 0;
  339. $productList[$key]['orderSn'] = $orderSn;
  340. $productId = $product['productId'];
  341. $hdProductId = $product['hdProductId'];
  342. $unitWeight = $hdProductData[$hdProductId]['weight'] ?? 0;
  343. $variety = $hdProductData[$hdProductId]['variety'] ?? 0;
  344. $ratio = $hdProductData[$hdProductId]['ratio'] ?? 0;
  345. $itemId = $hdProductData[$hdProductId]['itemId'] ?? 0;
  346. $rank = $hdProductData[$hdProductId]['rank'] ?? 'B';
  347. $stock = $hdProductData[$hdProductId]['stock'] ?? 0;
  348. $stockFormat = ProductClass::formatStock($stock, $ratio);
  349. $itemNum = ProductClass::mergeItemNum($product['bigNum'], $product['smallNum'], $ratio);
  350. $weight = $hdProductData[$hdProductId]['weight'] ?? 0;
  351. $currentWeight = bcmul($weight, $itemNum, 2);
  352. $totalWeight = bcadd($currentWeight, $totalWeight, 2);
  353. //供货商开单改价,这个价格优先级最高
  354. $changePrice = isset($product['userPrice']) && $product['userPrice'] > 0 ? $product['userPrice'] : 0;
  355. $currentProduct = $productData[$productId] ?? [];
  356. $price = ProductClass::getFinalPrice($currentProduct, $giveLevel, $priceMap, $addPriceMap, $changePrice);
  357. $bigPrice = $price;
  358. if ($currentSmallNum > 0) {
  359. //如果是小单位数量,则传过来的就是小单位价格,无需转换
  360. if (empty($changePrice)) {
  361. $ghsRatio = $currentProduct['ratio'] ?? 0;
  362. $ghsSmallRatio = $currentProduct['smallRatio'] ?? 1;
  363. $price = bcdiv($price, $ghsRatio, 2);
  364. $price = bcmul($price, $ghsSmallRatio, 2);
  365. }
  366. $productTotalPrice = bcmul($currentSmallNum, $price, 2);
  367. } else {
  368. $productTotalPrice = bcmul($currentBigNum, $price, 2);
  369. }
  370. $itemInfo = [
  371. 'itemName' => $hdProductData[$hdProductId]['name'] ?? '',//花材名称
  372. 'itemCover' => $hdProductData[$hdProductId]['cover'] ?? '',//花材图片
  373. 'bigNum' => $product['bigNum'] ?? 0,//采购数量(大单位)
  374. 'smallNum' => $product['smallNum'] ?? 0,//采购数量(小单位)
  375. 'bigNumStock' => $stockFormat['bigNum'],// 当时库存大单位数
  376. 'smallNumStock' => $stockFormat['smallNum'],//当时库存 小单位数
  377. 'itemUnit' => $ratio ? 2 : 1,//单位
  378. 'ratio' => $ratio,// 比例
  379. 'rank' => $rank,// 花材级别
  380. 'bigUnit' => $hdProductData[$hdProductId]['bigUnit'],//大单位名称 扎
  381. 'smallUnit' => $hdProductData[$hdProductId]['smallUnit'],//小单位名称 支
  382. ];
  383. $productList[$key]['itemInfo'] = json_encode($itemInfo);
  384. $productList[$key]['variety'] = $variety;
  385. $productList[$key]['itemId'] = $itemId;
  386. $productList[$key]['preItemNum'] = $itemNum;
  387. $productList[$key]['itemNum'] = $itemNum;
  388. $productList[$key]['bigNum'] = $product['bigNum'] ?? 0;
  389. $productList[$key]['smallNum'] = $product['smallNum'] ?? 0;
  390. $productList[$key]['price'] = $bigPrice;
  391. $productList[$key]['ratio'] = $ratio;
  392. $productList[$key]['unitWeight'] = $unitWeight;
  393. $productList[$key]['totalPrice'] = $productTotalPrice;
  394. $productList[$key]['preTotalPrice'] = $productTotalPrice;
  395. $productList[$key]['productId'] = $hdProductId;
  396. $productList[$key]['ghsProductId'] = $productId;
  397. $productList[$key]['smallPrice'] = $price;
  398. $productList[$key]['mainId'] = $mainId;
  399. if ($currentBigNum > 0) {
  400. $xhNum = $currentBigNum;
  401. $xhUnitName = $hdProductData[$hdProductId]['bigUnit'] ?? '';
  402. $xhUnitType = dict::getDict('unitType', 'big');
  403. } else {
  404. $xhNum = $currentSmallNum;
  405. $xhUnitName = $hdProductData[$hdProductId]['smallUnit'] ?? '';
  406. $xhUnitType = dict::getDict('unitType', 'small');
  407. }
  408. $itemPrice = $price;
  409. $price = bcmul($itemPrice, $xhNum, 2);
  410. $productList[$key]['xhNum'] = $xhNum;
  411. $productList[$key]['xhUnitName'] = $xhUnitName;
  412. $productList[$key]['xhUnitType'] = $xhUnitType;
  413. $productList[$key]['xhUnitPrice'] = $itemPrice;
  414. $productList[$key]['xhPrice'] = $price;
  415. $productList[$key]['xhPreNum'] = $xhNum;
  416. $productList[$key]['xhPreUnitName'] = $xhUnitName;
  417. $productList[$key]['xhPreUnitType'] = $xhUnitType;
  418. $productList[$key]['xhPreUnitPrice'] = $itemPrice;
  419. $productList[$key]['xhPrePrice'] = $price;
  420. $prePrice = bcadd($prePrice, $productTotalPrice, 2);
  421. }
  422. $data['itemPrice'] = $prePrice;
  423. $sendCost = $data['sendCost'] ?? 0.00;
  424. $prePrice = bcadd($prePrice, $sendCost, 2);
  425. $data['weight'] = $totalWeight;
  426. //预订单需要增加服务费
  427. $book = $data['book'] ?? 0;
  428. if ($book == 1) {
  429. $kiloFee = $ghs['kiloFee'] ?? 0;
  430. $miniKilo = $ghs['miniKilo'] ?? 0;
  431. $calcWeight = $totalWeight > $miniKilo ? $totalWeight : $miniKilo;
  432. $allKiloFee = bcmul($calcWeight, $kiloFee, 2);
  433. $prePrice = bcadd($prePrice, $allKiloFee, 2);
  434. $data['allKiloFee'] = $allKiloFee;
  435. $data['kiloFee'] = $kiloFee;
  436. $data['miniKilo'] = $miniKilo;
  437. $data['stockChange'] = 0;
  438. }
  439. $actPrice = $prePrice;
  440. $realPrice = $prePrice;
  441. if (isset($data['modifyPrice'])) {
  442. $modifyPrice = $data['modifyPrice'] ?? 0;
  443. if ($modifyPrice < $prePrice) {
  444. //优惠金额
  445. $data['discountAmount'] = bcsub($prePrice, $modifyPrice, 2);
  446. $data['discountType'] = dict::getDict('discountType', 'discount');
  447. }
  448. if ($modifyPrice > $prePrice) {
  449. //人工和资材费用
  450. $data['labourCost'] = bcsub($modifyPrice, $prePrice, 2);
  451. }
  452. $actPrice = $modifyPrice;
  453. $realPrice = $modifyPrice;
  454. }
  455. $data['prePrice'] = $prePrice;
  456. $data['bookPrice'] = $actPrice;
  457. $data['orderPrice'] = $actPrice;
  458. $data['actPrice'] = $actPrice;
  459. $data['realPrice'] = $realPrice;
  460. $data['bigNum'] = $bigNum;
  461. $data['smallNum'] = $smallNum;
  462. $data['discount'] = 1;
  463. //采购单有效期
  464. $currentTime = time();
  465. $validTime = dict::getDict('order_pay_has_time');
  466. $current = $currentTime + $validTime;
  467. $data['deadline'] = $data['deadline'] ?? date("Y-m-d H:i:s", $current);
  468. //采购单自动记为欠款单时间
  469. $localConfirmTime = dict::getDict('local_gys_kd_auto_set_debt_time');
  470. $currentSet = $currentTime + $localConfirmTime;
  471. $data['autoSetTime'] = $data['autoSetTime'] ?? date("Y-m-d H:i:s", $currentSet);
  472. //保存订单
  473. $respond = self::add($data, true);
  474. foreach ($productList as $productKey => $productVal) {
  475. //增加采购单的花材
  476. $returnItem = PurchaseItemClass::add($productVal, true);
  477. $unitPrice = $returnItem->price ?? 0;
  478. $currentId = $returnItem->id ?? 0;
  479. $currentPtItemId = $returnItem->itemId ?? 0;
  480. if (isset($data['xj'][$currentPtItemId]) && !empty($data['xj'][$currentPtItemId])) {
  481. $xjArr = $data['xj'][$currentPtItemId];
  482. if (is_array($xjArr)) {
  483. $ids = array_column($xjArr, 'id');
  484. $sjInfo = XjClass::getByIds($ids, null, 'id');
  485. $xjData = [];
  486. foreach ($xjArr as $xjItem) {
  487. $id = $xjItem['id'] ?? 0;
  488. $num = $xjItem['num'] ?? 0;
  489. $name = $sjInfo[$id]['name'] ?? '';
  490. $cover = $sjInfo[$id]['cover'] ?? '';
  491. $xjData[] = ['xjId' => $id, 'name' => $name, 'ptItemId' => $currentPtItemId,
  492. 'num' => $num, 'price' => $unitPrice, 'itemId' => $currentId, 'cover' => $cover];
  493. }
  494. CgXjClass::batchAdd($xjData);
  495. $returnItem->variety = 1;
  496. $returnItem->save();
  497. }
  498. }
  499. }
  500. $shop = ShopClass::getLockById($shopId);
  501. if (empty($shop)) {
  502. util::fail('没有找到门店');
  503. }
  504. $mainId = $shop->mainId ?? 0;
  505. $main = MainClass::getLockById($mainId);
  506. if (empty($main)) {
  507. util::fail('没有main信息');
  508. }
  509. $main->totalPurchaseOrder += 1;
  510. $main->cgUnPay += 1;
  511. $main->save();
  512. return $respond;
  513. }
  514. //添加采购 ssh 2021.1.18
  515. public static function updatePurchase($purchase, $data)
  516. {
  517. $orderSn = $purchase->orderSn ?? '';
  518. $shopId = $purchase->shopId ?? 0;
  519. $sjId = $purchase->sjId ?? 0;
  520. $prePrice = 0;
  521. $data['sendTimeWant'] = date("Y-m-d") . ' ' . $data['sendTime'];
  522. unset($data['sendTime']);
  523. if (isset($data['product']) == false || empty($data['product'])) {
  524. util::fail('请选择花材');
  525. }
  526. $productList = $data['product'];
  527. $productList = self::mergeItemInfo($productList);
  528. $data['kindNum'] = count($productList); //多少种花材
  529. //供货商productId转成零售的productId
  530. $mainId = $purchase->mainId ?? 0;
  531. $productList = ProductClass::toggleProductList($productList, $shopId, $sjId, $mainId);
  532. $productData = self::getProductMapData($productList, "productId");
  533. $hdProductData = self::getProductMapData($productList, "hdProductId");
  534. //计算价格= 各个productId的price*num(bigNum,smallNum) + sendCost(配送费)
  535. $bigNum = 0; //总共多少扎
  536. $smallNum = 0; //总共多少支
  537. foreach ($productList as $key => $product) {
  538. $bigNum += $product['bigNum'] ?? 0;
  539. $smallNum += $product['smallNum'] ?? 0;
  540. $productList[$key]['orderSn'] = $orderSn;
  541. $productId = $product['productId'];
  542. $hdProductId = $product['hdProductId'];
  543. $ratio = $hdProductData[$hdProductId]['ratio'] ?? 0; //比例必须一致
  544. $itemId = $hdProductData[$hdProductId]['itemId'] ?? 0;
  545. $rank = $hdProductData[$hdProductId]['rank'] ?? 'B';// 花材级别
  546. $stock = $hdProductData[$hdProductId]['stock'] ?? 0;//当时库存
  547. $stockFormat = ProductClass::formatStock($stock, $ratio);
  548. $itemNum = ProductClass::mergeItemNum($product['bigNum'], $product['smallNum'], $ratio);//采购数量
  549. $price = $productData[$productId]['price']; //卖的单价
  550. //每个花材总价(原价)
  551. $productPrePrice = bcmul($itemNum, $price, 2); //采购总价
  552. //供货商开单的每个花材总价,可能会改价
  553. $productTotalPrice = isset($product['userPrice']) && $product['userPrice'] > 0 ? $product['userPrice'] : $productPrePrice;
  554. $itemInfo = [
  555. 'itemName' => $hdProductData[$hdProductId]['name'] ?? '',//花材名称
  556. 'itemCover' => $hdProductData[$hdProductId]['cover'] ?? '',//花材图片
  557. 'bigNum' => $product['bigNum'] ?? 0,//采购数量(大单位)
  558. 'smallNum' => $product['smallNum'] ?? 0,//采购数量(小单位)
  559. 'bigNumStock' => $stockFormat['bigNum'],// 当时库存大单位数
  560. 'smallNumStock' => $stockFormat['smallNum'],//当时库存 小单位数
  561. 'itemUnit' => $ratio ? 2 : 1,//单位
  562. 'ratio' => $ratio,// 比例
  563. 'rank' => $rank,// 花材级别
  564. 'bigUnit' => $hdProductData[$hdProductId]['bigUnit'],//大单位名称 扎
  565. 'smallUnit' => $hdProductData[$hdProductId]['smallUnit'],//小单位名称 支
  566. ];
  567. $productList[$key]['itemInfo'] = json_encode($itemInfo);
  568. $productList[$key]['itemId'] = $itemId;
  569. $productList[$key]['itemNum'] = $itemNum;
  570. $productList[$key]['price'] = $price;
  571. $productList[$key]['ratio'] = $ratio;
  572. $productList[$key]['totalPrice'] = $productTotalPrice;
  573. $productList[$key]['preTotalPrice'] = $productPrePrice;
  574. $productList[$key]['productId'] = $hdProductId;
  575. $productList[$key]['ghsProductId'] = $productId;
  576. //小单位单价
  577. $smallPrice = bcdiv($price, $ratio, 2);
  578. $productList[$key]['smallPrice'] = $smallPrice;
  579. $prePrice = bcadd($prePrice, $productTotalPrice, 2);
  580. }
  581. //删除花材再添加
  582. PurchaseItemClass::deleteByCondition(['orderSn' => $orderSn]);
  583. PurchaseItemClass::batchAdd($productList);
  584. $data['itemPrice'] = $prePrice;
  585. $sendCost = $data['sendCost'] ?? 0.00;
  586. $prePrice = bcadd($prePrice, $sendCost, 2);
  587. $actPrice = $prePrice;
  588. $realPrice = $prePrice;
  589. if (isset($data['modifyPrice'])) {
  590. //商家打折,修改金额
  591. $modifyPrice = $data['modifyPrice'] ?? 0;
  592. if ($modifyPrice > $prePrice) {
  593. util::fail('实收金额大于订单总金额');
  594. }
  595. if ($modifyPrice < $prePrice) {
  596. $data['discountAmount'] = bcsub($prePrice, $modifyPrice, 2);
  597. $data['discountType'] = dict::getDict('discountType', 'discount');
  598. $actPrice = $modifyPrice;
  599. $realPrice = $modifyPrice;
  600. }
  601. } else {
  602. //验证优惠券
  603. $hbId = isset($data['hbId']) ? $data['hbId'] : 0;
  604. if (!empty($hbId)) {
  605. $coupon = ShopCouponClass::getLockById($hbId);
  606. ShopCouponClass::valid($coupon, $data['shopId']);
  607. if ($coupon->miniCost != 0 && $coupon->miniCost > $prePrice) {
  608. util::fail('达到最低消费才能使用优惠券');
  609. }
  610. if ($prePrice < $coupon->amount) {
  611. util::fail('总价应大于优惠金额');
  612. }
  613. $coupon->take = ShopCouponClass::TAKE_HAS;
  614. $coupon->save();
  615. $realPrice = bcsub($actPrice, $coupon->amount, 2);
  616. $data['discountType'] = dict::getDict('discountType', 'usePtCoupon');
  617. $data['discountAmount'] = $coupon->amount;
  618. $data['hbId'] = $hbId;
  619. }
  620. }
  621. $data['prePrice'] = $prePrice;
  622. $data['actPrice'] = $actPrice;
  623. $data['realPrice'] = $realPrice;
  624. $data['bigNum'] = $bigNum;
  625. $data['smallNum'] = $smallNum;
  626. //采购单有效期
  627. $validTime = dict::getDict('order_pay_has_time');
  628. $current = time() + $validTime;
  629. $data['deadline'] = $data['deadline'] ?? date("Y-m-d H:i:s", $current);
  630. $purchaseId = $purchase->id ?? 0;
  631. self::updateById($purchaseId, $data);
  632. $respond = self::getLockById($purchaseId);
  633. $shop = ShopClass::getLockById($shopId);
  634. if (empty($shop)) {
  635. util::fail('没有找到门店');
  636. }
  637. $shop->cancelOrder -= 1;
  638. $shop->cgUnPay += 1;
  639. $shop->save();
  640. return $respond;
  641. }
  642. //组合数据 ssh 2021.1.25
  643. public static function groupPurchase($list, $showButton = false, $showProduct = false)
  644. {
  645. $ghsIds = array_unique(array_filter(array_column($list, 'ghsId')));
  646. $ghsInfo = GhsClass::getGhsByIds($ghsIds);
  647. $adminIds = array_unique(array_filter(array_column($list, 'adminId')));
  648. $adminInfo = AdminClass::getAdminByIds($adminIds, null, 'id');
  649. $time = time();
  650. foreach ($list as $key => $val) {
  651. //剩余支付时间
  652. $remainPayTime = 0;
  653. $deadline = $val['deadline'] ?? '';
  654. if (!empty($deadline)) {
  655. $deadTime = strtotime($deadline);
  656. if (($deadTime - $time - 30) > 0) {
  657. $remainPayTime = $deadTime - $time;
  658. $remainPayTime = $remainPayTime - 30;
  659. }
  660. }
  661. $list[$key]['remainPayTime'] = $remainPayTime;
  662. $adminId = $val['adminId'] ?? 0;
  663. $list[$key]['adminName'] = $adminInfo[$adminId]['name'] ?? '';
  664. $ghsId = $val['ghsId'] ?? 0;
  665. $list[$key]['supplierName'] = $ghsInfo[$ghsId]['name'] ?? '';
  666. $list[$key]['supplierAvatar'] = $ghsInfo[$ghsId]['smallLogoUrl'] ?? '';
  667. $list[$key]['supplierMobile'] = $ghsInfo[$ghsId]['mobile'] ?? '';
  668. $list[$key]['supplierAddress'] = $ghsInfo[$ghsId]['address'] ?? '';
  669. $list[$key]['debtAmount'] = $ghsInfo[$ghsId]['debtAmount'] ?? '';
  670. $list[$key]['lat'] = $ghsInfo[$ghsId]['lat'] ?? '';
  671. $list[$key]['long'] = $ghsInfo[$ghsId]['long'] ?? '';
  672. $list[$key]['supplierId'] = $ghsInfo[$ghsId]['id'] ?? '';
  673. if ($showButton) {
  674. $list[$key]['buttonList'] = [
  675. ['type' => 'pay', 'show' => 1, 'disable' => 1],
  676. ['type' => 'debtPay', 'show' => 1, 'disable' => 0],
  677. ];
  678. }
  679. $list[$key]['sendProgress'] = [];
  680. if ($showProduct) {
  681. $orderSn = $val['orderSn'];
  682. $orderItem = PurchaseItemClass::getOrderItemDetail($orderSn);
  683. $itemData = [];
  684. $xjData = [];
  685. if ($orderItem) {
  686. foreach ($orderItem as $v) {
  687. $info = json_decode($v['itemInfo'], true);
  688. $tmp = $info;
  689. $tmp['cover'] = self::groupImg($info['itemCover']);
  690. unset($v['itemInfo']);
  691. if (!isset($tmp['rank'])) {
  692. $tmp['rank'] = 'B';
  693. }
  694. $tmp['name'] = $tmp['itemName'];
  695. $tmp = array_merge($tmp, $v);
  696. if (isset($tmp['variety']) && $tmp['variety'] == 1) {
  697. $currentItemId = $tmp['id'] ?? 0;
  698. $xjList = CgXjClass::getAllByCondition(['itemId' => $currentItemId], null, '*');
  699. if (!empty($xjList)) {
  700. foreach ($xjList as $xjKey => $xj) {
  701. $xjBase = $tmp;
  702. $num = $xj['num'] ?? 0;
  703. $name = $xj['name'] ?? '';
  704. $cover = $xj['cover'] ?? '';
  705. $price = $xj['price'] ?? '';
  706. $totalPrice = bcmul($num, $price, 2);
  707. if ($num > 0) {
  708. $xjBase['cover'] = imgUtil::groupImg($cover) . "?x-oss-process=image/resize,m_fill,h_130,w_130";
  709. $xjBase['name'] = $name;
  710. $xjBase['itemNum'] = floatval($num);
  711. $xjBase['bigNum'] = floatval($num);
  712. $xjBase['smallNum'] = 0;
  713. $xjBase['price'] = $price;
  714. $xjBase['totalPrice'] = $totalPrice;
  715. $xjBase['xhNum'] = floatval($num);
  716. $xjAddList[] = $xjBase;
  717. }
  718. $xjData[] = $xjBase;
  719. }
  720. } else {
  721. $itemData[] = $tmp;
  722. }
  723. } else {
  724. $itemData[] = $tmp;
  725. }
  726. }
  727. if (!empty($xjData)) {
  728. $itemData = array_merge($itemData, $xjData);
  729. }
  730. }
  731. $list[$key]['product'] = $itemData;
  732. }
  733. }
  734. return $list;
  735. }
  736. //订单取消,变更状态,占用库存释放 ssh 2021.5.8
  737. public static function cancel($id)
  738. {
  739. $purchase = PurchaseClass::getLockById($id);
  740. $purchase->status = self::STATUS_CANCEL;
  741. $purchase->save();
  742. $shopId = $purchase->shopId;
  743. $shop = ShopClass::getLockById($shopId);
  744. if (empty($shop)) {
  745. util::fail('没有找到门店');
  746. }
  747. $mainId = $shop->mainId ?? 0;
  748. $main = MainClass::getLockById($mainId);
  749. if (empty($main)) {
  750. util::fail('没有main信息');
  751. }
  752. $main->cgUnPay -= 1;
  753. $main->cgCancel += 1;
  754. $main->save();
  755. return $purchase;
  756. }
  757. //采购统计2021-05-08
  758. //采购数,采购金额统计(根据时间,今日,昨天,7天,30天)
  759. public static function statOrderInfo($shopId, $statType)
  760. {
  761. $start = '';
  762. $end = '';
  763. switch ($statType) {
  764. case "today":
  765. $start = date('Y-m-d');
  766. $end = $start;
  767. break;
  768. case "yesterday" :
  769. $start = date('Y-m-d', strtotime("-1 day"));
  770. $end = $start;
  771. break;
  772. case "seven":
  773. $start = date('Y-m-d', strtotime("-6 day"));
  774. $end = date('Y-m-d');
  775. break;
  776. case "thirty":
  777. $start = date('Y-m-d', strtotime("-29 day"));
  778. $end = date('Y-m-d');
  779. break;
  780. default:
  781. }
  782. $where = [];
  783. $where['shopId'] = $shopId;
  784. $where['addTime'] = ['between', [$start, $end]];
  785. $res = self::getAllByCondition($where, null, "id,actPrice");
  786. $totalAmount = 0;
  787. $totalNum = count($res);
  788. foreach ($res as $v) {
  789. $totalAmount = bcadd($totalAmount, $v['actPrice'], 2);
  790. }
  791. return [
  792. 'totalAmount' => $totalAmount,
  793. 'totalNum' => $totalNum,
  794. ];
  795. }
  796. //采购单完成 ssh 2021.5.15
  797. public static function complete($purchase)
  798. {
  799. $purchase->status = self::STATUS_COMPLETE;
  800. $purchase->save();
  801. $shopId = $purchase->shopId;
  802. $shop = ShopClass::getLockById($shopId);
  803. if (empty($shop)) {
  804. util::fail('没有找到门店');
  805. }
  806. $mainId = $shop->mainId ?? 0;
  807. $main = MainClass::getLockById($mainId);
  808. if (empty($main)) {
  809. util::fail('没有main信息');
  810. }
  811. $main->cgSending -= 1;
  812. $main->cgFinish += 1;
  813. $main->save();
  814. /********订单完成后加库存 lqh 2021-05-10*********/
  815. $orderSn = $purchase->orderSn;
  816. $purchaseItem = PurchaseItemClass::getAllByCondition(['orderSn' => $orderSn], null, "*");
  817. foreach ($purchaseItem as $v) {
  818. $stockInfo = ProductClass::addStockByItemNum($v['productId'], $v['itemNum']);
  819. //记录库存流水
  820. $recordData = [];
  821. $recordData['sjId'] = $purchase->sjId;
  822. $recordData['shopId'] = $purchase->shopId;
  823. $recordData['mainId'] = $purchase->mainId;
  824. $recordData['itemId'] = $v['itemId'] ?? 0;
  825. $recordData['itemNum'] = $v['itemNum'];
  826. $recordData['oldStock'] = $stockInfo['oldStock'];
  827. $recordData['newStock'] = $stockInfo['newStock'];
  828. $recordData['productId'] = $v['productId'];
  829. $recordData['orderSn'] = $orderSn;
  830. StockRecordClass::addPurchaseOrderRecord($recordData);
  831. }
  832. }
  833. //订单信息变更为配送中 ssh 2021.5.15
  834. public static function sending($purchaseId)
  835. {
  836. $purchase = PurchaseClass::getById($purchaseId, true);
  837. if (empty($purchase)) {
  838. util::fail('没有采购单信息');
  839. }
  840. $purchase->status = PurchaseClass::STATUS_SENDING;
  841. $purchase->save();
  842. $shopId = $purchase->shopId;
  843. $shop = ShopClass::getLockById($shopId);
  844. if (empty($shop)) {
  845. util::fail('没有找到门店');
  846. }
  847. $shop->cgUnSend -= 1;
  848. $shop->cgSending += 1;
  849. $shop->save();
  850. //自动完成订单时不需要通知
  851. $noNeedWxNotice = isset(Yii::$app->params['noNeedWxNotice']) ? Yii::$app->params['noNeedWxNotice'] : 0;
  852. if ($noNeedWxNotice == 0) {
  853. WxMessageClass::cgOrderHasSend($shop, $purchase);
  854. }
  855. }
  856. public static function valid($cg, $shopId)
  857. {
  858. if (isset($cg->shopId) == false || $cg->shopId != $shopId) {
  859. util::fail('没有权限访问');
  860. }
  861. }
  862. }