PurchaseOrderClass.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. <?php
  2. namespace bizGhs\order\classes;
  3. use biz\ghs\classes\GhsClass;
  4. use biz\shop\classes\ShopCapitalClass;
  5. use biz\shop\classes\ShopClass;
  6. use biz\stat\classes\StatCgClass;
  7. use biz\stat\classes\StatOutClass;
  8. use bizGhs\base\classes\BaseClass;
  9. use bizGhs\custom\classes\CustomClass;
  10. use bizGhs\order\traits\OrderTrait;
  11. use bizGhs\stock\services\StockRecordService;
  12. use bizGhs\product\classes\ProductClass;
  13. use common\components\dict;
  14. use common\components\orderSn;
  15. use common\components\util;
  16. use Yii;
  17. //采购单 lqh 2021.1.20
  18. class PurchaseOrderClass extends BaseClass
  19. {
  20. use OrderTrait;
  21. public static $baseFile = '\bizGhs\order\models\PurchaseOrder';
  22. const PURCHASE_ORDER_STATUS_WAIT = 1; //待确认
  23. const PURCHASE_ORDER_STATUS_UN_SEND = 2; //待配送
  24. const PURCHASE_ORDER_STATUS_SENDING = 3; //配送中
  25. const PURCHASE_ORDER_STATUS_COMPLETE = 4; //已完成
  26. public static $statusMap = [
  27. self::PURCHASE_ORDER_STATUS_WAIT => '待确认',
  28. self::PURCHASE_ORDER_STATUS_UN_SEND => '待配送',
  29. self::PURCHASE_ORDER_STATUS_SENDING => '配送中',
  30. self::PURCHASE_ORDER_STATUS_COMPLETE => '已完成',
  31. ];
  32. const DEBT_UNKNOWN = 0;
  33. const DEBT_YES = 1;
  34. const DEBT_NO = 2;
  35. //添加采购单 lqh 2021.1.19
  36. public static function addOrder($data)
  37. {
  38. $sjId = $data['sjId'];
  39. $shopId = $data['shopId'];
  40. $data['status'] = self::PURCHASE_ORDER_STATUS_COMPLETE;
  41. $orderSn = orderSn::getGhsPurchaseSn();
  42. $data['orderSn'] = $orderSn;
  43. $ghsItemInfo = $data['itemInfo']; // [{itemId:0,bigNum:0,smallNum:0,productId:1.0,itemPrice:1,weight:1}] //增加重量kg
  44. $ghsItemInfo = self::mergeItemInfo($ghsItemInfo);
  45. //计算出总共多少扎,多少支
  46. $bigNum = 0; //总共多少扎
  47. $smallNum = 0; //总共多少支
  48. $totalItemPrice = 0;
  49. //花材中总重量
  50. $totalItemWeight = 0;
  51. $ghsItemInfoMap = [];
  52. if (!empty($ghsItemInfo)) {
  53. foreach ($ghsItemInfo as $v) {
  54. $bigNum += $v['bigNum'] ?? 0;
  55. $smallNum += $v['smallNum'] ?? 0;
  56. $totalItemPrice = bcadd($totalItemPrice, $v['itemPrice'], 2);
  57. $ghsItemInfoMap[$v['productId']] = $v;
  58. if (getenv('YII_ENV', 'local') == 'production') {
  59. $weight = $v['weight'] ?? 0;
  60. } else {
  61. $weight = 0.6;
  62. }
  63. $totalItemWeight = bcadd($totalItemWeight, $weight, 2);
  64. }
  65. }
  66. $data['bigNum'] = $bigNum;
  67. $data['smallNum'] = $smallNum;
  68. $data['price'] = $totalItemPrice;
  69. //计算订单总价
  70. $data['packingCharge'] = empty($data['packingCharge']) ? 0 : $data['packingCharge'];
  71. $data['shortCharge'] = empty($data['shortCharge']) ? 0 : $data['shortCharge'];
  72. $data['longCharge'] = empty($data['longCharge']) ? 0 : $data['longCharge'];
  73. $data['pickCharge'] = empty($data['pickCharge']) ? 0 : $data['pickCharge'];
  74. $data['localCharge'] = empty($data['localCharge']) ? 0 : $data['localCharge'];
  75. if (empty($data['entryTime'])) {
  76. $data['entryTime'] = date('Y-m-d H:i:s');
  77. }
  78. $packingCharge = $data['packingCharge'] ?? 0;
  79. $shortCharge = $data['shortCharge'] ?? 0;
  80. $longCharge = $data['longCharge'] ?? 0;
  81. $pickCharge = $data['pickCharge'] ?? 0;
  82. $localCharge = $data['localCharge'] ?? 0;
  83. $orderPrice = bcadd($totalItemPrice, $packingCharge, 2);
  84. $orderPrice = bcadd($orderPrice, $shortCharge, 2);
  85. $orderPrice = bcadd($orderPrice, $longCharge, 2);
  86. $orderPrice = bcadd($orderPrice, $pickCharge, 2);
  87. $orderPrice = bcadd($orderPrice, $localCharge, 2);
  88. $data['orderPrice'] = $orderPrice;
  89. $data['prePrice'] = $orderPrice;
  90. $data['actPrice'] = $orderPrice;
  91. $data['realPrice'] = $orderPrice;
  92. //总运费
  93. $totalFreight = bcadd($packingCharge, $shortCharge, 2);
  94. $totalFreight = bcadd($totalFreight, $longCharge, 2);
  95. $totalFreight = bcadd($totalFreight, $pickCharge, 2);
  96. $totalFreight = bcadd($totalFreight, $localCharge, 2);
  97. if ($totalFreight <= 0) {
  98. util::fail('请填写运费');
  99. }
  100. $connection = Yii::$app->db;
  101. $transaction = $connection->beginTransaction();
  102. try {
  103. $order = self::add($data);
  104. //采购支出
  105. //组装详情表数据
  106. $batchData = self::groupOrderItem($ghsItemInfo, $orderSn);
  107. //写入详情表
  108. PurchaseOrderItemClass::batchAddOrderItem($batchData);
  109. //总共多少扎(总扎数)
  110. $totalItemNum = 0;
  111. foreach ($batchData as $v) {
  112. $totalItemNum = bcadd($totalItemNum, $v['itemNum'], 2);
  113. }
  114. //平均计算出每扎得运费:总运费/总扎数
  115. //$avgFreight = bcdiv($totalFreight, $totalItemNum, 2);
  116. //计算每公斤的运费 总运费/总重量
  117. $avgKgWeight = bcdiv($totalFreight, $totalItemWeight, 2);
  118. //现在暂时点击确定,完成 加库存
  119. foreach ($batchData as $v) {
  120. $itemId = $v['itemId'];
  121. $productId = $v['productId'];
  122. //流水记录
  123. $record = [];
  124. $record['sjId'] = $sjId;
  125. $record['shopId'] = $shopId;
  126. $record['orderSn'] = $orderSn;
  127. $record['itemId'] = $itemId;
  128. $record['itemNum'] = $v['itemNum'];
  129. $record['oldStock'] = $v['itemStock'];
  130. $record['newStock'] = bcadd($v['itemStock'], $v['itemNum'], 2);
  131. StockRecordService::addPurchaseOrderRecord($record);
  132. //加库存
  133. ProductClass::addStockByItemNum($productId, $v['itemNum']);
  134. //
  135. //每扎的采购价
  136. //总的采购价/扎数
  137. $avgItemCost = 0;
  138. if ($v['itemNum'] > 0) {
  139. $avgItemCost = bcdiv($v['itemPrice'], $v['itemNum'], 2);
  140. }
  141. // 每扎采购价+每扎运费 = 每扎成本价
  142. //$avgCost = bcadd($avgItemCost, $avgFreight, 2);
  143. //2021-06-11 修改每扎运费计算
  144. $itemInfoTmp = json_decode($v['itemInfo'], true);
  145. //花材的重量
  146. $productWeight = $itemInfoTmp['itemWeight'] ?? 0;
  147. $productFreight = bcmul($avgKgWeight, $productWeight, 2);
  148. $avgCost = bcadd($avgItemCost, $productFreight, 2);
  149. //修改 ghsItem 中的成本价
  150. // ItemClass::changeCost($itemId,$sjId,$avgCost);
  151. //2021.4.6修改product 成本价
  152. ProductClass::changeCost($productId, $avgCost);
  153. //触发自动调价 2021.4.26 linqh
  154. ProductClass::autoPriceById($productId);
  155. }
  156. //门店支出增加
  157. $shop = ShopClass::getLockById($shopId);
  158. if (empty($shop)) {
  159. util::fail('没有找到门店');
  160. }
  161. $currentTotalExpend = bcadd($shop->totalExpend, $order['orderPrice'], 2);
  162. $shop->totalExpend = $currentTotalExpend;
  163. $shop->cgFinish += 1;
  164. $shop->totalPurchaseOrder += 1;
  165. $currentTotalPurchase = bcadd($shop->totalPurchase, $order['orderPrice'], 2);
  166. $shop->totalPurchase = $currentTotalPurchase;
  167. $shop->save();
  168. //采购统计
  169. StatCgClass::replace($shop, $order['orderPrice']);
  170. //当天和当月支出统计
  171. StatOutClass::updateOrInsert($shop, $order['orderPrice']);
  172. //供应商资产增加
  173. $ghsId = $data['ghsId'] ?? 0;
  174. $ghs = GhsClass::getLockById($ghsId);
  175. if (empty($ghs)) {
  176. util::fail('没有找到供应商');
  177. }
  178. $ghs->debt = GhsClass::DEBT_YES;
  179. $ghs->debtAmount = bcadd($ghs->debtAmount, $order['orderPrice'], 2);
  180. $ghs->debtNum += 1;
  181. $ghs->expendAmount = bcadd($ghs->expendAmount, $order['orderPrice'], 2);
  182. $ghs->expendNum += 1;
  183. $ghs->save();
  184. //客户资产增加
  185. $customId = $ghs->customId;
  186. $custom = CustomClass::getLockById($customId);
  187. if (empty($custom)) {
  188. util::fail('没有找到客户信息');
  189. }
  190. $custom->isDebt = CustomClass::IS_DEBT_YES;
  191. $custom->debtAmount = bcadd($custom->debtAmount, $order['orderPrice'], 2);
  192. $custom->debtNum += 1;
  193. $custom->buyNum += 1;
  194. $custom->buyAmount = bcadd($custom->buyAmount, $order['orderPrice'], 2);
  195. $custom->save();
  196. //支出流水
  197. $payWay = dict::getDict('payWay', 'unknown');
  198. $capitalType = dict::getDict('capitalType', 'ghsPurchase', 'id');
  199. $sjId = $order['sjId'] ?? 0;
  200. $shopId = $order['shopId'] ?? 0;
  201. $event = '采购';
  202. $capitalData = [
  203. 'capitalType' => $capitalType,
  204. 'io' => 0,
  205. 'totalExpend' => $currentTotalExpend,
  206. 'payWay' => $payWay,
  207. 'amount' => $order['orderPrice'],
  208. 'sjId' => $sjId,
  209. 'shopId' => $shopId,
  210. 'event' => $event,
  211. ];
  212. ShopCapitalClass::addCapital($capitalData);
  213. $transaction->commit();
  214. return $order;
  215. } catch (\Exception $exception) {
  216. $transaction->rollBack();
  217. util::fail('保存失败:' . $exception->getMessage());
  218. }
  219. return false;
  220. }
  221. //采购单列表 lqh 2021.1.19
  222. public static function getOrderList($where)
  223. {
  224. $data = self::getList('*', $where, 'addTime DESC');
  225. $list = $data['list'] ?? [];
  226. $data['list'] = self::groupSupplierList($list);
  227. $data['list'] = self::groupAdminList($data['list']);
  228. $data['list'] = self::groupStatusName($data['list']);
  229. return $data;
  230. }
  231. //获取订单详情信息 lqh 2021.1.20
  232. public static function getOrderDetail($orderSn, $shopId)
  233. {
  234. $where = [
  235. 'orderSn' => $orderSn,
  236. 'shopId' => $shopId,
  237. ];
  238. $orderData = self::getByCondition($where);
  239. $orderData['ghsInfo'] = json_decode($orderData['ghsInfo']);
  240. if (!$orderData) {
  241. util::fail('订单不存在');
  242. }
  243. $orderInfo = PurchaseOrderItemClass::getOrderItemDetail($orderSn);
  244. $itemData = [];
  245. if ($orderInfo) {
  246. foreach ($orderInfo as $v) {
  247. $info = json_decode($v['itemInfo'], true);
  248. $tmp = $info;
  249. $tmp['itemCover'] = self::groupImg($info['itemCover']);
  250. unset($v['itemInfo']);
  251. //兼容 旧数据,没有 rank (花材等级 默认给B)
  252. if (!isset($tmp['rank'])) {
  253. $tmp['rank'] = 'B';
  254. }
  255. $tmp = array_merge($tmp, $v);
  256. $itemData[] = $tmp;
  257. }
  258. }
  259. $orderData = self::groupAdmin($orderData);
  260. //供应商信息
  261. $ghsId = $orderData['ghsId'] ?? 0;
  262. $ghsInfo = GhsClass::getGhsInfo($ghsId);
  263. $orderData['supplierName'] = $ghsInfo['name'] ?? '';
  264. $orderData['supplierMobile'] = $ghsInfo['mobile'] ?? '';
  265. $orderData['supplierAddress'] = $ghsInfo['address'] ?? '';
  266. $orderData['itemInfo'] = $itemData;
  267. $orderData['statusName'] = self::getStatusName($orderData['status']);
  268. return $orderData;
  269. }
  270. // 组装 orderItem linqh 2021.1.25
  271. public static function groupOrderItem($ghsItemInfo, $orderSn)
  272. {
  273. $productData = self::getProductMapData($ghsItemInfo);
  274. //$itemIds = array_column($productData,'itemId');
  275. //$itemData = xhItemService::getByIds($itemIds);
  276. //$itemData = array_column($itemData, NULL, 'id');
  277. //写入详情表
  278. $batchData = [];
  279. foreach ($ghsItemInfo as $v) {
  280. $tmp = [];
  281. $productId = $v['productId'];
  282. $itemId = $productData[$productId]['itemId'];
  283. $rank = $productData[$productId]['rank'] ?? 'B';// 花材级别
  284. $tmp['orderSn'] = $orderSn;
  285. $tmp['itemId'] = $itemId;
  286. $tmp['productId'] = $v['productId'];
  287. $ratio = $productData[$productId]['ratio'] ?? 0;
  288. $tmp['itemStock'] = $productData[$productId]['stock'] ?? 0;//当时库存
  289. $tmp['itemNum'] = ProductClass::mergeItemNum($v['bigNum'], $v['smallNum'], $ratio);// 采购数量
  290. $tmp['itemPrice'] = $v['itemPrice']; //采购价格
  291. $stockFormat = ProductClass::formatStock($tmp['itemStock'], $ratio); // 库存总单位数量转大小单位的数量
  292. $itemInfo = [
  293. 'itemName' => $productData[$productId]['name'] ?? '',//花材名称
  294. 'itemCover' => $productData[$productId]['cover'] ?? '',//花材图片
  295. 'bigNum' => $v['bigNum'] ?? 0,//采购数量(大单位)
  296. 'smallNum' => $v['smallNum'] ?? 0,//采购数量(小单位)
  297. 'bigNumStock' => $stockFormat['bigNum'],// 当时库存大单位数
  298. 'smallNumStock' => $stockFormat['smallNum'],//当时库存 小单位数
  299. 'itemUnit' => $ratio ? 2 : 1,//单位
  300. 'ratio' => $ratio,// 比例
  301. 'rank' => $rank,// 花材级别
  302. 'bigUnit' => $productData[$productId]['bigUnit'],//大单位名称 扎
  303. 'smallUnit' => $productData[$productId]['smallUnit'],//小单位名称 支
  304. 'purchaseWeight' => $v['weight'] ?? 0, //采购重量
  305. 'itemWeight' => $productData[$productId]['weight'] ?? 0,
  306. ];
  307. $tmp['itemInfo'] = json_encode($itemInfo);
  308. $batchData[] = $tmp;
  309. }
  310. return $batchData;
  311. }
  312. // 组装状态码 linqh 2021.1.30
  313. public static function groupStatusName($list)
  314. {
  315. foreach ($list as $k => $val) {
  316. $status = $val['status'] ?? 0;
  317. $list[$k]['statusName'] = self::getStatusName($status);
  318. }
  319. return $list;
  320. }
  321. // 获取状态码名称
  322. public static function getStatusName($status)
  323. {
  324. return self::$statusMap[$status] ?? '';
  325. }
  326. //获取各个状态下的订单数量 allNum unPayNum unSendNum sendingNum finishNum
  327. public static function statNum($shopId)
  328. {
  329. $data = [
  330. 'allNum' => 0,
  331. 'unPayNum' => 0,
  332. 'unSendNum' => 0,
  333. 'sendingNum' => 0,
  334. 'finishNum' => 0,
  335. ];
  336. $res = self::getAllList("status", ['shopId' => $shopId]);
  337. foreach ($res as $v) {
  338. $data['allNum']++;
  339. $status = $v['status'];
  340. switch ($status) {
  341. case self::PURCHASE_ORDER_STATUS_WAIT:
  342. //待支付
  343. $data['unPayNum']++;
  344. break;
  345. case self::PURCHASE_ORDER_STATUS_UN_SEND:
  346. $data['unSendNum']++;
  347. break;
  348. case self::PURCHASE_ORDER_STATUS_SENDING:
  349. $data['sendingNum']++;
  350. break;
  351. case self::PURCHASE_ORDER_STATUS_COMPLETE:
  352. $data['finishNum']++;
  353. break;
  354. }
  355. }
  356. return $data;
  357. }
  358. //采购数,采购金额统计(根据时间,今日,昨天,7天,30天)
  359. public static function statOrderInfo($shopId, $statType)
  360. {
  361. $start = '';
  362. $end = '';
  363. switch ($statType) {
  364. case "today":
  365. $start = date('Y-m-d');
  366. $end = $start;
  367. break;
  368. case "yesterday" :
  369. $start = date('Y-m-d', strtotime("-1 day"));
  370. $end = $start;
  371. break;
  372. case "seven":
  373. $start = date('Y-m-d', strtotime("-6 day"));
  374. $end = date('Y-m-d');
  375. break;
  376. case "thirty":
  377. $start = date('Y-m-d', strtotime("-29 day"));
  378. $end = date('Y-m-d');
  379. break;
  380. default:
  381. }
  382. $where = [];
  383. $where['shopId'] = $shopId;
  384. $where['addTime'] = ['between', [$start, $end]];
  385. $res = self::getAllByCondition($where, null, "id,orderPrice");
  386. $totalAmount = 0;
  387. $totalNum = count($res);
  388. foreach ($res as $v) {
  389. $totalAmount = bcadd($totalAmount, $v['orderPrice'], 2);
  390. }
  391. return [
  392. 'totalAmount' => $totalAmount,
  393. 'totalNum' => $totalNum,
  394. ];
  395. }
  396. }