ProductClass.php 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  1. <?php
  2. namespace bizGhs\product\classes;
  3. use biz\item\classes\PtItemClass;
  4. use biz\item\classes\PtItemClassClass;
  5. use biz\item\classes\UnitClass;
  6. use biz\shop\services\ShopService;
  7. use biz\wx\classes\WxMessageClass;
  8. use bizGhs\base\classes\BaseClass;
  9. use bizGhs\custom\classes\CustomClass;
  10. use bizGhs\item\classes\ItemClass;
  11. use bizGhs\item\classes\ItemClassClass;
  12. use bizGhs\merchant\classes\ShopClass;
  13. use bizGhs\order\classes\CheckOrderClass;
  14. use bizGhs\order\classes\CheckOrderItemClass;
  15. use bizGhs\order\traits\OrderTrait;
  16. use bizGhs\stock\classes\StockRecordClass;
  17. use bizGhs\stock\services\StockRecordService;
  18. use common\components\dict;
  19. use common\components\imgUtil;
  20. use common\components\noticeUtil;
  21. use common\components\orderSn;
  22. use common\components\stringUtil;
  23. use common\components\util;
  24. use common\services\xhItemService;
  25. use Yii;
  26. use yii\di\ServiceLocator;
  27. class ProductClass extends BaseClass
  28. {
  29. use OrderTrait;
  30. public static $baseFile = '\bizGhs\product\models\Product';
  31. const PRICE_LABEL_AUTO = 1; //自动调价
  32. const PRICE_LABEL_CHANGE = 2; //改价
  33. const LOCK_STOCK = 'lock_stock';//修改库存锁
  34. const LOCK_PRICE = 'lock_price'; //改价锁
  35. const LOCK_CHECK_STOCK = 'lock_check_stock'; //判断库存
  36. //根据itemIds获取相应的花材信息
  37. public static function getProductInfoByItemIds(array $itemIds, $hdMainId)
  38. {
  39. $where = ['itemId' => ['in', $itemIds], 'delStatus' => 0, 'mainId' => $hdMainId];
  40. $data = self::getAllList('*', $where);
  41. $data = self::groupItemBaseInfo($data);
  42. return $data;
  43. }
  44. //根据花材ID,获取花材名称,图片
  45. public static function groupItemBaseInfo($list)
  46. {
  47. //取得itemIds
  48. $itemIds = array_column($list, 'itemId');
  49. //获取相应的图片,名称,py
  50. $where = ['id' => ['in', $itemIds]];
  51. $data = xhItemService::getAllByCondition($where, null, '*');
  52. if (!empty($data)) {
  53. $data = array_column($data, NULL, 'id');
  54. foreach ($list as $k => $v) {
  55. if (isset($data[$v['itemId']]['cover']) && !empty($data[$v['itemId']]['cover'])) {
  56. $cover = self::groupImg($data[$v['itemId']]['cover']);
  57. } else {
  58. //没有图片时取默认图片 ssh 2021.2.18
  59. $cover = imgUtil::getPrefix() . '/hhb_small.png';
  60. }
  61. $unitNum = $data[$v['itemId']]['ratio'] ?? 0;
  62. $stockInfo = self::formatStock($v['stock'], $unitNum);
  63. $list[$k]['cover'] = $cover;
  64. $list[$k]['bigNum'] = $stockInfo['bigNum'];
  65. $list[$k]['smallNum'] = $stockInfo['smallNum'];
  66. $list[$k]['itemName'] = $data[$v['itemId']]['name'] ?? '';
  67. $list[$k]['py'] = $data[$v['itemId']]['py'] ?? '';
  68. $list[$k]['ratio'] = $unitNum ?? 0;
  69. //换算大小单位对应价格
  70. $list[$k]['bigPrice'] = $v['price']; //大单位价格就是product表存的价格
  71. $smallPrice = 0;
  72. if ($unitNum) {
  73. $smallPrice = bcdiv($v['price'], $unitNum, 2);
  74. }
  75. $list[$k]['smallPrice'] = $smallPrice;
  76. $list[$k]['bigUnit'] = $data[$v['itemId']]['bigUnit'];
  77. $list[$k]['smallUnit'] = $data[$v['itemId']]['smallUnit'];
  78. }
  79. }
  80. return $list;
  81. }
  82. //获取详情 ruidian 2021.5.3
  83. public static function getItemInfo($id, $ghs = [])
  84. {
  85. $info = self::getById($id);
  86. if (empty($info)) {
  87. return $info;
  88. }
  89. $level = $ghs->giveLevel ?? 1;
  90. $list = self::groupProductInfo([$info], $level);
  91. return current($list);
  92. }
  93. //花材图片,名称,大小单位,小单位价格
  94. public static function groupProductInfo($list, $level = 0)
  95. {
  96. //各个等级对应的price addPrice字段
  97. $priceMap = CustomClass::$levelPriceKeyMap;
  98. $addPriceMap = CustomClass::$levelAddPriceKeyMap;
  99. foreach ($list as $k => $v) {
  100. $shortCover = $v['cover'] ?? '';
  101. $cover = imgUtil::getPrefix() . 'hhb_small.png';
  102. $bigCover = imgUtil::getPrefix() . 'hhb_small.png';
  103. if (!empty($shortCover)) {
  104. $parse = parse_url(self::groupImg($shortCover));
  105. if (empty($parse['query'])) {
  106. $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_110,w_110";
  107. } else {
  108. $cover = self::groupImg($shortCover);
  109. }
  110. $bigCover = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_700,w_700";
  111. }
  112. $ratio = isset($v['ratio']) && $v['ratio'] > 0 ? $v['ratio'] : 1;
  113. $stockInfo = self::formatStock($v['stock'], $ratio);
  114. $list[$k]['cover'] = $cover;
  115. $list[$k]['bigCover'] = $bigCover;
  116. $list[$k]['shortCover'] = $shortCover;
  117. $list[$k]['bigNum'] = $stockInfo['bigNum'];
  118. $list[$k]['smallNum'] = $stockInfo['smallNum'];
  119. $list[$k]['itemName'] = $v['name'] ?? '';
  120. $list[$k]['prePrice'] = $v['price'] ?? 0;
  121. //今日特价、会员价
  122. $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
  123. $list[$k]['price'] = $price;
  124. $list[$k]['bigPrice'] = $price;
  125. $smallRatio = $v['smallRatio'] ?? 0;
  126. $smallPrice = bcdiv($price, $ratio, 2);
  127. $smallPrice = bcmul($smallPrice, $smallRatio, 2);
  128. $list[$k]['smallPrice'] = $smallPrice;
  129. //这个很重要不能随意乱改
  130. $autoPrice = bcadd($v['cost'], $v['addPrice'], 2);
  131. $skMore = $v['skMore'] ?? 0;
  132. $skAutoPrice = bcadd($autoPrice, $skMore, 2);
  133. $list[$k]['autoPrice'] = $autoPrice;
  134. $list[$k]['autoSkPrice'] = $skAutoPrice;
  135. }
  136. return $list;
  137. }
  138. //输出价格 ssh 20211009
  139. public static function getFinalPrice($product, $level, $priceMap, $addPriceMap, $changePrice = 0)
  140. {
  141. //开单改价优先级最高
  142. if ($changePrice > 0) {
  143. return $changePrice;
  144. }
  145. if (empty($product) || isset($product['price']) == false) {
  146. return 0;
  147. }
  148. //今日特价
  149. $discountPrice = $product['discountPrice'] ?? 0;
  150. $currentPriceField = $priceMap[$level] ?? 'price';
  151. $price = $product[$currentPriceField] ?? 0;
  152. if ($discountPrice > 0) {
  153. $discountAddPrice = $product['addPrice'] ?? 0;
  154. $currentAddPriceField = $addPriceMap[$level] ?? 'addPrice';
  155. $currentAddPrice = $product[$currentAddPriceField] ?? 0;
  156. $diff = bcsub($discountAddPrice, $currentAddPrice, 2);
  157. $price = bcsub($discountPrice, $diff, 2);
  158. }
  159. return $price;
  160. }
  161. //根据花材ID,库存=》 计算出多少扎,多少支
  162. public static function formatStockByItemId($itemId, $stock)
  163. {
  164. $unitNum = xhItemService::getItemUnitNum($itemId);
  165. return self::formatStock($stock, $unitNum);
  166. }
  167. //花材的库存转换: 库存是小数,根据各个花材的unitNum, 计算出多少扎,多少支
  168. public static function formatStock($stock, $unitNum)
  169. {
  170. $pn = true; //正数
  171. if ($stock < 0) {
  172. $pn = false;
  173. $stock = abs($stock);
  174. }
  175. $bigNum = floor($stock); // 扎
  176. $stockArr = explode('.', $stock);
  177. $smallNum = 0; //支
  178. if (count($stockArr) === 2) {
  179. $smallNum = bcmul(($stock - $bigNum), $unitNum);
  180. }
  181. if (!$pn) {
  182. $bigNum *= -1;
  183. $smallNum *= -1;
  184. }
  185. return [
  186. 'bigNum' => $bigNum,
  187. 'smallNum' => $smallNum,
  188. ];
  189. }
  190. /**
  191. * 根据 花材ID,将花材大小数量 换算成小数
  192. * @param $bigNum 大单位 数量
  193. * @param $smallNum 小单位 数量
  194. * @param $itemId 花材ID
  195. * @return string
  196. */
  197. public static function mergeItemNumByItemId($bigNum, $smallNum, $itemId)
  198. {
  199. $unitNum = xhItemService::getItemUnitNum($itemId);
  200. return self::mergeItemNum($bigNum, $smallNum, $unitNum);
  201. }
  202. //花材扎、支 合并转换 小数
  203. /**
  204. * @param $bigNum 大单位 数量
  205. * @param $smallNum 小单位 数量
  206. * @param $unitNum 花材比例
  207. * @return string
  208. */
  209. public static function mergeItemNum($bigNum, $smallNum, $unitNum)
  210. {
  211. $stockDecimal = 0;
  212. if ($unitNum > 0) {
  213. $stockDecimal = bcdiv($smallNum, $unitNum, 2);
  214. }
  215. $itemNum = bcadd($bigNum, $stockDecimal, 2);
  216. return $itemNum;
  217. }
  218. //获取常用的itemIds
  219. public static function getOftenItemIds($shopId)
  220. {
  221. $data = self::getLimitList("itemId", ['shopId' => $shopId], 10, ['actualSold' => SORT_DESC, 'inTurn' => SORT_DESC]);
  222. if ($data) {
  223. $data = array_column($data, 'itemId');
  224. }
  225. return $data;
  226. }
  227. //加库存,允许负库存,负数数量(盘点时)
  228. /**
  229. * @param $productId 门店下的花材ID(xhGhsItemInfo 主键ID)
  230. * @param $itemNumBundle 花材数量(扎)
  231. * @param $itemNumPiece 花材数量(支)
  232. * @return mixed
  233. */
  234. public static function addStock($productId, $itemNumBundle, $itemNumPiece)
  235. {
  236. $key = self::LOCK_STOCK . '_' . $productId;
  237. $lock = util::lock($key);
  238. if (!$lock) {
  239. util::fail("系统繁忙中,请稍后再试!");
  240. }
  241. $productData = self::getById($productId);
  242. if (!$productData) {
  243. util::unlock($key);
  244. util::fail("花材不存在");
  245. }
  246. // $itemId = $productData['itemId'];
  247. $ratio = $productData['ratio'];
  248. //转成小数,加库存
  249. $itemNum = self::mergeItemNum($itemNumBundle, $itemNumPiece, $ratio);
  250. $newStock = bcadd($productData['stock'], $itemNum, 2);
  251. self::updateStockById($productId, $newStock);
  252. //上架
  253. if ($newStock > 0 && $productData['status'] == 2) {
  254. self::changeStatus($productId, 1);
  255. }
  256. util::unlock($key);
  257. return ['oldStock' => $productData['stock'], 'newStock' => $newStock, 'itemNum' => $itemNum];
  258. }
  259. //todo 库存修改 加锁
  260. /**
  261. * 对商品ID 加库存
  262. * @param $productId 商品ID
  263. * @param $itemNum 数量
  264. * @return mixed
  265. */
  266. public static function addStockByItemNum($productId, $itemNum)
  267. {
  268. $key = self::LOCK_STOCK . '_' . $productId;
  269. $lock = util::lock($key);
  270. if (!$lock) {
  271. util::fail("系统繁忙中,请稍后再试!");
  272. }
  273. $productData = self::getById($productId, true);
  274. if (!$productData) {
  275. util::unlock($key);
  276. util::fail("花材不存在");
  277. }
  278. $newStock = bcadd($productData->stock, $itemNum, 2);
  279. self::updateStockById($productId, $newStock);
  280. //上架
  281. if ($newStock > 0 && $productData->status == 2) {
  282. self::changeStatus($productId, 1);
  283. }
  284. util::unlock($key);
  285. return ['oldStock' => $productData['stock'], 'newStock' => $newStock, 'itemNum' => $itemNum];
  286. }
  287. //减库存,允许负库存,负数数量(盘点时)
  288. /**
  289. * @param $productId 门店下的花材ID(xhGhsItemInfo 主键ID)
  290. * @param $itemNumBundle 花材数量(扎)
  291. * @param $itemNumPiece 花材数量(支)
  292. * @param $checkStock boolean 是否需要判断库存
  293. * @return mixed
  294. */
  295. public static function decreaseStock($productId, $itemNumBundle, $itemNumPiece, $checkStock = false)
  296. {
  297. $key = self::LOCK_STOCK . '_' . $productId;
  298. $lock = util::lock($key);
  299. if (!$lock) {
  300. util::fail("系统繁忙中,请稍后再试!");
  301. }
  302. $productData = self::getById($productId, true);
  303. if (!$productData) {
  304. util::unlock($key);
  305. util::fail("花材不存在");
  306. }
  307. $ratio = $productData->ratio;
  308. //转成小数,更新库存
  309. $itemNum = self::mergeItemNum($itemNumBundle, $itemNumPiece, $ratio);
  310. $newStock = bcsub($productData->stock, $itemNum, 2);
  311. if ($checkStock && $newStock < 0) {
  312. //需要判断库存是否充足
  313. util::unlock($key);
  314. $currentName = $productData->name ?? '';
  315. $currentRemainStock = floatval($productData->stock);
  316. util::fail("{$currentName} 只剩{$currentRemainStock}{$productData->bigUnit}");
  317. }
  318. self::updateStockById($productId, $newStock);
  319. //减库存,加销量 2021.6.21 lqh
  320. $actualSold = $productData->actualSold;
  321. $newActualSold = bcadd($actualSold, $itemNum, 2);
  322. self::updateActualSoldById($productId, $newActualSold);
  323. //库存=0 下架商品 lqh 2021.7.9
  324. if ($newStock <= 0) {
  325. self::changeStatus($productId, 2);
  326. }
  327. util::unlock($key);
  328. return ['oldStock' => $productData['stock'], 'newStock' => $newStock, 'itemNum' => $itemNum];
  329. }
  330. //根据数量减库存
  331. /**
  332. * @param $productId
  333. * @param $itemNum
  334. * @return mixed 返回减之前的库存,和减之后的库存
  335. */
  336. public static function decreaseStockByItemNum($productId, $itemNum, $checkStock = false)
  337. {
  338. $key = self::LOCK_STOCK . '_' . $productId;
  339. $lock = util::lock($key);
  340. if (!$lock) {
  341. util::fail("系统繁忙中,请稍后再试!");
  342. }
  343. $productData = self::getById($productId);
  344. if (!$productData) {
  345. util::unlock($key);
  346. util::fail("花材不存在");
  347. }
  348. $newStock = bcsub($productData['stock'], $itemNum, 2);
  349. if ($checkStock && $newStock < 0) {
  350. //需要判断库存是否充足
  351. util::unlock($key);
  352. util::fail("库存不足");
  353. }
  354. self::updateStockById($productId, $newStock);
  355. //减库存,加销量 2021.6.21 lqh
  356. $actualSold = $productData['actualSold'];
  357. $newActualSold = bcadd($actualSold, $itemNum, 2);
  358. self::updateActualSoldById($productId, $newActualSold);
  359. util::unlock($key);
  360. return ['oldStock' => $productData['stock'], 'newStock' => $newStock, 'itemNum' => $itemNum];
  361. }
  362. //计算价格
  363. /**
  364. * @param $productId 门店下的花材ID(xhGhsItemInfo 主键ID)
  365. * @param $bigNum 花材数量(扎)
  366. * @param $smallNum 花材数量(支)
  367. * @return float
  368. */
  369. public static function computedPrice($productId, $bigNum, $smallNum)
  370. {
  371. //获取itemId的价格
  372. $productData = self::getById($productId);
  373. if (!$productData) {
  374. util::fail("花材不存在");
  375. }
  376. $price = $productData['price'];
  377. $itemId = $productData['itemId'];
  378. $unitNum = xhItemService::getItemUnitNum($itemId);
  379. //换算出一支多少钱
  380. $piecePrice = 0;
  381. if ($unitNum > 0) {
  382. //有支
  383. $unitPrice = bcdiv($price, $unitNum, 2);
  384. $piecePrice = bcmul($unitPrice, $smallNum, 2);
  385. }
  386. $bundlePrice = bcmul($price, $bigNum, 2);
  387. $total = bcadd($bundlePrice, $piecePrice, 2);
  388. return $total;
  389. }
  390. //根据门店ID, 平台花材ID, 获取门店的花材ID
  391. public static function getGhsProductId($shopId, $itemId)
  392. {
  393. $data = self::getGhsProductDataByItemId($shopId, $itemId);
  394. if ($data) {
  395. return $data['id'];
  396. }
  397. return 0;
  398. }
  399. public static function getGhsProductDataByItemId($shopId, $itemId)
  400. {
  401. $where = ['shopId' => $shopId, 'itemId' => $itemId];
  402. $data = self::getByCondition($where);
  403. return $data;
  404. }
  405. //根据多个itemIds shopId 获取对应的 productId lqh 2021.1.24
  406. public static function getGhsProductDataByItemIds($mainId, $itemIds)
  407. {
  408. $where = ['itemId' => ['in', $itemIds], 'mainId' => $mainId];
  409. $data = self::getAllByCondition($where, null, "*");
  410. return $data;
  411. }
  412. //补全itemId (针对入库时 当前门店下无对应的花材 itemId) lqh 2021.1.24
  413. public static function complementProduct($sjId, $mainId, $shopId, $itemInfo)
  414. {
  415. $itemIds = array_column($itemInfo, "itemId");
  416. $oldProductIds = array_column($itemInfo, "productId");
  417. $productData = self::getGhsProductDataByItemIds($mainId, $itemIds);
  418. $defaultClass = ItemClassClass::getByCondition(['mainId' => $mainId, 'isDefault' => 1], true);
  419. $defaultClassId = $defaultClass->id ?? 0;
  420. if (empty($defaultClassId)) {
  421. util::fail('没有找到默认分类');
  422. }
  423. $shop = ShopClass::getById($shopId, true);
  424. if (empty($shop)) {
  425. util::fail('没有找到门店');
  426. }
  427. if (count($productData) !== count($itemIds)) {
  428. $productDataItemIds = array_column($productData, 'itemId');
  429. //取差集
  430. $diffItemIds = array_diff($itemIds, $productDataItemIds);
  431. if ($diffItemIds) {
  432. $oldProductInfo = ProductClass::getAllByCondition(['id' => ['in', $oldProductIds]], null, '*', 'itemId');
  433. //新增到product表,price = itemPrice (出库时的售价), stock=0
  434. foreach ($diffItemIds as $v) {
  435. $addData = [];
  436. $addData['sjId'] = $sjId;
  437. $addData['shopId'] = $shopId;
  438. $addData['mainId'] = $mainId;
  439. $addData['itemId'] = $v;
  440. $addData['name'] = $oldProductInfo[$v]['name'] ?? '';
  441. $addData['price'] = $oldProductInfo[$v]['price'] ?? 0;
  442. $addData['classId'] = $defaultClassId;
  443. $addData['smallRatio'] = $oldProductInfo[$v]['smallRatio'] ?? 2;
  444. $addData['skPrice'] = $oldProductInfo[$v]['skPrice'] ?? 0;
  445. $addData['hjPrice'] = $oldProductInfo[$v]['hjPrice'] ?? 0;
  446. $addData['cost'] = $oldProductInfo[$v]['cost'] ?? 0;
  447. $addData['addPrice'] = $oldProductInfo[$v]['addPrice'] ?? 0;
  448. $addData['skAddPrice'] = $oldProductInfo[$v]['skAddPrice'] ?? 0;
  449. $addData['hjAddPrice'] = $oldProductInfo[$v]['hjAddPrice'] ?? 0;
  450. $addData['stockWarning'] = $oldProductInfo[$v]['stockWarning'] ?? 5;
  451. $addData['weight'] = $oldProductInfo[$v]['weight'] ?? 0;
  452. $addData['alias'] = $oldProductInfo[$v]['alias'] ?? '';
  453. $addData['py'] = $oldProductInfo[$v]['py'] ?? '';
  454. $addData['ratio'] = $oldProductInfo[$v]['ratio'] ?? 20;
  455. $addData['bigUnit'] = $oldProductInfo[$v]['bigUnit'] ?? '';
  456. $addData['smallUnit'] = $oldProductInfo[$v]['smallUnit'] ?? '';
  457. $addData['bigUnitId'] = $oldProductInfo[$v]['bigUnitId'] ?? 0;
  458. $addData['smallUnitId'] = $oldProductInfo[$v]['smallUnitId'] ?? 0;
  459. $addData['status'] = 1;
  460. $addData['delStatus'] = 0;
  461. $addData['inTurn'] = 100;
  462. self::addProduct($addData, $shop);
  463. }
  464. }
  465. }
  466. }
  467. public static function check($info, $mainId)
  468. {
  469. if (empty($info)) {
  470. util::fail('没有花材信息');
  471. }
  472. if (isset($info->mainId) == false || $info->mainId != $mainId) {
  473. util::fail('无效花材');
  474. }
  475. return true;
  476. }
  477. //有效花材判断,包括id有效、同个门店等 ssh 2021.1.19
  478. public static function valid($list, $mainId)
  479. {
  480. $ids = array_unique(array_filter(array_column($list, 'productId')));
  481. $productList = self::getByIds($ids, null, 'id');
  482. if (!empty($productList)) {
  483. foreach ($productList as $product) {
  484. if (isset($product['mainId']) == false || $product['mainId'] != $mainId) {
  485. util::fail('只能选择同一家的商品下单');
  486. }
  487. }
  488. if (count($productList) != count($ids)) {
  489. util::fail('存在无效商品');
  490. }
  491. } else {
  492. util::fail('商品不存在');
  493. }
  494. }
  495. //通过ids 批量获取花材商品的信息
  496. public static function getProductByIds($ids)
  497. {
  498. return self::getByIds($ids);
  499. }
  500. //修改花材商品的库存: 统一方法
  501. public static function updateStockById($id, $stock, $adminId = 0)
  502. {
  503. $data['stock'] = $stock;
  504. if ($adminId) {
  505. $data['adminId'] = $adminId;
  506. }
  507. $res = self::updateById($id, $data);
  508. return $res;
  509. }
  510. //订单退回库存
  511. public static function backStockByOrderItemInfo($orderItemInfo)
  512. {
  513. foreach ($orderItemInfo as $v) {
  514. ProductClass::addStockByItemNum($v['productId'], $v['itemNum']);
  515. }
  516. }
  517. //获取当前门店下商品信息 lqh 2021.1.28
  518. public static function getProductData($id, $mainId, $obj = false)
  519. {
  520. return ProductClass::getByCondition(['id' => $id, 'mainId' => $mainId], $obj);
  521. }
  522. //单个修改价格 lqh 2021.1.28
  523. public static function changeSinglePrice($shop, $ptItemId, $price, $skPrice = null)
  524. {
  525. $mainId = $shop->mainId ?? 0;
  526. $productInfo = ProductClass::getByCondition(['itemId' => $ptItemId, 'mainId' => $mainId], true);
  527. if (empty($productInfo)) {
  528. return false;
  529. }
  530. $productInfo->price = $price;
  531. if (empty($skPrice)) {
  532. $skMore = $productInfo->skMore ?? 0;
  533. $productInfo->skPrice = bcadd($price, $skMore, 2);
  534. } else {
  535. $productInfo->skPrice = $skPrice;
  536. }
  537. $productInfo->save();
  538. }
  539. //下单时计算商品的价格 lqh 2021.1.28
  540. public static function formatProductInfo($itemInfo, $level = 0)
  541. {
  542. $data = [];
  543. if (empty($itemInfo)) {
  544. util::fail('请选择花材');
  545. }
  546. $itemInfo = self::mergeItemInfo($itemInfo);
  547. $productIds = array_column($itemInfo, 'productId');
  548. $productData = ProductClass::getProductByIds($productIds);
  549. $productData = array_column($productData, NULL, 'id');
  550. $totalPrice = 0;
  551. $totalBigNum = 0;
  552. $totalSmallNum = 0;
  553. //不同等级对应 price addPrice
  554. $priceMap = CustomClass::$levelPriceKeyMap;
  555. $addPriceMap = CustomClass::$levelAddPriceKeyMap;
  556. $totalItemNum = 0;
  557. foreach ($itemInfo as $v) {
  558. $productId = $v['productId'];
  559. $itemId = $productData[$productId]['itemId'] ?? 0;
  560. $ratio = $productData[$productId]['ratio'] ?? 0;
  561. $smallRatio = $productData[$productId]['smallRatio'] ?? 1;
  562. $cost = $productData[$productId]['cost'] ?? 0;
  563. $bigNum = $v['bigNum'] ?? 0;
  564. $smallNum = $v['smallNum'] ?? 0;
  565. //大小数量合并多少扎
  566. $itemNum = self::mergeItemNum($bigNum, $smallNum, $ratio);
  567. $totalItemNum = bcadd($totalItemNum, $itemNum, 2);
  568. //供货商开单可以传单价过来
  569. $changePrice = isset($v['price']) && $v['price'] > 0 ? $v['price'] : 0;
  570. //今日特价、会员价
  571. $currentProduct = $productData[$productId] ?? [];
  572. $itemPrice = self::getFinalPrice($currentProduct, $level, $priceMap, $addPriceMap, $changePrice);
  573. $bigItemPrice = $itemPrice;
  574. if ($smallNum > 0) {
  575. //如果是小单位数量,则传过来的就是小单位价格,无需转换
  576. if (empty($changePrice)) {
  577. $itemPrice = bcdiv($itemPrice, $ratio, 2);
  578. $itemPrice = bcmul($itemPrice, $smallRatio, 2);
  579. }
  580. $price = bcmul($smallNum, $itemPrice, 2);
  581. } else {
  582. $price = bcmul($bigNum, $itemPrice, 2);
  583. }
  584. $tmp = [];
  585. $tmp['productId'] = $productId;
  586. $tmp['price'] = $price;
  587. $totalPrice = bcadd($totalPrice, $price, 2);
  588. $tmp['name'] = $productData[$productId]['name'] ?? '';
  589. $tmp['smallUnit'] = $productData[$productId]['smallUnit'] ?? '支';
  590. $tmp['bigUnit'] = $productData[$productId]['bigUnit'] ?? '扎';
  591. $tmp['cover'] = $productData[$productId]['cover'] ?? '';
  592. $tmp['itemId'] = $itemId;
  593. $tmp['rank'] = $productData[$productId]['rank'] ?? '';
  594. $tmp['ratio'] = $productData[$productId]['ratio'] ?? 1;
  595. $tmp['variety'] = $productData[$productId]['variety'] ?? 0;
  596. $tmp['unitPrice'] = $bigItemPrice;
  597. $tmp['unitWeight'] = $productData[$productId]['weight'] ?? 0;;
  598. $tmp['num'] = $itemNum;
  599. $tmp['bigNum'] = $v['bigNum'];
  600. $tmp['smallNum'] = $v['smallNum'];
  601. $tmp['preNum'] = $itemNum;
  602. $tmp['preBigNum'] = $v['bigNum'];
  603. $tmp['preSmallNum'] = $v['smallNum'];
  604. $tmp['userPrice'] = $price;
  605. $tmp['cost'] = $cost;
  606. $tmp['weight'] = $productData[$productId]['weight'] ?? 0;
  607. $tmp['sjId'] = $productData[$productId]['sjId'] ?? 0;
  608. $tmp['shopId'] = $productData[$productId]['shopId'] ?? 0;
  609. $tmp['mainId'] = $productData[$productId]['mainId'] ?? 0;
  610. $tmp['smallUnitPrice'] = $itemPrice;
  611. $totalBigNum += $bigNum;
  612. $totalSmallNum += $smallNum;
  613. if ($bigNum > 0) {
  614. $xhUnitType = dict::getDict('unitType', 'big');
  615. $xhNum = $bigNum;
  616. $xhUnitName = $tmp['bigUnit'] ?? '';
  617. } else {
  618. $xhUnitType = dict::getDict('unitType', 'small');
  619. $xhNum = $smallNum;
  620. $xhUnitName = $tmp['smallUnit'] ?? '';
  621. }
  622. $xhPrice = bcmul($xhNum, $itemPrice, 2);
  623. $tmp['xhNum'] = $xhNum;
  624. $tmp['xhUnitName'] = $xhUnitName;
  625. $tmp['xhUnitType'] = $xhUnitType;
  626. $tmp['xhUnitPrice'] = $itemPrice;
  627. $tmp['xhPrice'] = $xhPrice;
  628. $tmp['xhPreNum'] = $xhNum;
  629. $tmp['xhPreUnitName'] = $xhUnitName;
  630. $tmp['xhPreUnitType'] = $xhUnitType;
  631. $tmp['xhPreUnitPrice'] = $itemPrice;
  632. $tmp['xhPrePrice'] = $xhPrice;
  633. $data[] = $tmp;
  634. }
  635. return ['product' => $data, 'smallNum' => $totalSmallNum, 'bigNum' => $totalBigNum, 'price' => $totalPrice, 'totalItemNum' => $totalItemNum];
  636. }
  637. // //修改某个花材的成本价(采购之后要用到) lqh 2021.04.06
  638. public static function changeCost($productId, $cost)
  639. {
  640. return self::updateById($productId, ['cost' => $cost]);
  641. }
  642. //更新某个花材的加价 2021.04.06
  643. public static function changeAddPrice($productId, $addPrice)
  644. {
  645. return self::updateById($productId, ['addPrice' => $addPrice]);
  646. }
  647. //根据productId 计算花材的重量
  648. public static function getWeight($productId, $bigNum, $smallNum)
  649. {
  650. $productInfo = self::getById($productId);
  651. if (empty($productInfo)) {
  652. return 0;
  653. }
  654. $ratio = $productInfo['ratio'];
  655. $weight = $productInfo['weight'];
  656. $mergeNum = self::mergeItemNum($bigNum, $smallNum, $ratio);
  657. return bcmul($mergeNum, $weight, 2);
  658. }
  659. //修改product
  660. public static function updateProduct($data, $shop)
  661. {
  662. $id = $data['id'] ?? 0;
  663. $sjId = $shop->sjId ?? 0;
  664. $shopId = $shop->id ?? 0;
  665. $mainId = $shop->mainId ?? 0;
  666. $product = self::getLockById($id);
  667. if (empty($product)) {
  668. util::fail("该花材不存在");
  669. }
  670. $upData = [];
  671. //库存可以修改
  672. if (isset($data['stock']) && is_numeric($data['stock'])) {
  673. $preStock = $product->stock ?? 0;
  674. if ($data['stock'] != $preStock) {
  675. if ($data['stock'] < 0) {
  676. util::fail("库存不能小于0");
  677. }
  678. if (floor($data['stock']) != $data['stock']) {
  679. util::fail('库存请填写整数');
  680. }
  681. //增加盘点记录 2021.7.27
  682. $ratio = $product->ratio ?? 0;
  683. $formNum = ProductClass::formatStock($data['stock'], $ratio);
  684. $ghsItemInfo = [['productId' => $product->id, 'bigNum' => $formNum['bigNum'], 'smallNum' => $formNum['smallNum'],]];
  685. $pdData = [];
  686. $pdData['itemInfo'] = $ghsItemInfo;
  687. $pdData['sjId'] = $sjId;
  688. $pdData['shopId'] = $shopId;
  689. $pdData['adminId'] = $data['adminId'];
  690. $pdData['mainId'] = $mainId;
  691. $pdData['staffName'] = $data['staffName'] ?? '';
  692. CheckOrderClass::opOrder($pdData, false, false);
  693. }
  694. unset($data['stock']);
  695. }
  696. unset($data['adminId']);
  697. if (isset($data['name'])) {
  698. if (empty($data['name'])) {
  699. util::fail("请输入花材名称");
  700. }
  701. $upData['name'] = $data['name'];
  702. }
  703. if (isset($data['py']) && !empty($data['py'])) {
  704. $upData['py'] = $data['py'];
  705. }
  706. if (isset($data['cover']) && !empty($data['cover'])) {
  707. $upData['cover'] = $data['cover'];
  708. }
  709. if (isset($data['discountPrice']) && is_numeric($data['discountPrice'])) {
  710. $discountPrice = $data['discountPrice'] ?? 0;
  711. $currentPrice = $data['price'] ?? 0;
  712. if ($discountPrice >= $currentPrice) {
  713. util::fail('今日特价要小于售价');
  714. }
  715. $upData['discountPrice'] = $discountPrice;
  716. }
  717. //加价
  718. $addPrice = $data['addPrice'] ?? 0;
  719. $upData['addPrice'] = $addPrice;
  720. //价格
  721. $price = $data['price'] ?? 0;
  722. if (is_numeric($price) == false || $price < 0) {
  723. util::fail('请填写价格');
  724. }
  725. if (isset($data['skMore']) && is_numeric($data['skMore'])) {
  726. $upData['skMore'] = $data['skMore'];
  727. }
  728. if (isset($data['stockWarning'])) {
  729. $upData['stockWarning'] = $data['stockWarning'];
  730. }
  731. if (isset($data['inTurn'])) {
  732. $upData['inTurn'] = $data['inTurn'];
  733. }
  734. if (isset($data['delStatus'])) {
  735. if (!in_array($data['delStatus'], [0, 1])) {
  736. util::fail("上下架参数错误");
  737. }
  738. $upData['delStatus'] = $data['delStatus'];
  739. }
  740. if (isset($data['status']) && is_numeric($data['status'])) {
  741. $upData['status'] = $data['status'];
  742. }
  743. if (isset($data['variety']) && is_numeric($data['variety'])) {
  744. $upData['variety'] = $data['variety'];
  745. }
  746. //分类ID
  747. if (isset($data["classId"])) {
  748. $classId = $data['classId'];
  749. $upData['classId'] = $classId;
  750. }
  751. if (isset($data["scanNum"]) && is_numeric($data["scanNum"])) {
  752. $upData['scanNum'] = $data['scanNum'];
  753. }
  754. if (isset($data["smallRatio"]) && is_numeric($data["smallRatio"])) {
  755. $upData['smallRatio'] = $data['smallRatio'];
  756. }
  757. if (isset($data["smallShow"]) && is_numeric($data["smallShow"])) {
  758. $upData['smallShow'] = $data['smallShow'];
  759. }
  760. $paramsBack = $upData;
  761. $ptItemId = $product->itemId ?? 0;
  762. $currentSkPrice = null;
  763. if (isset($data['skMore']) && is_numeric($data['skMore'])) {
  764. $currentSkPrice = bcadd($price, $data['skMore'], 2);
  765. }
  766. if ($price != $product->price) {
  767. //花店价有变化
  768. self::changeSinglePrice($shop, $ptItemId, $price, $currentSkPrice);
  769. unset($upData['price']);
  770. } else {
  771. //花店价没有变化,但散客价比花店价贵多少有修改时,也要改价
  772. if (isset($data['skMore']) && is_numeric($data['skMore']) && $data['skMore'] != $product->skMore) {
  773. self::changeSinglePrice($shop, $ptItemId, $price, $currentSkPrice);
  774. unset($upData['price']);
  775. }
  776. }
  777. self::updateById($id, $upData);
  778. //不影响其它直营店花材的上下架
  779. unset($upData['status']);
  780. if (isset($shop->default) && $shop->default == 1) {
  781. //首店修改同步到所有直营店
  782. $chainShopList = ShopClass::getAllByCondition(['sjId' => $sjId], null, '*', null, true);
  783. foreach ($chainShopList as $chainShop) {
  784. $chainShopId = $chainShop->id ?? 0;
  785. if (isset($chainShop->join) && $chainShop->join == 1) {
  786. continue;
  787. }
  788. if ($chainShopId == $shop->id) {
  789. //前面已经添加过了
  790. continue;
  791. }
  792. $chainMainId = $chainShop->mainId ?? 0;
  793. $params = $paramsBack;
  794. //所有直营店上下架、启用停用不同步
  795. unset($params['status']);
  796. unset($params['delStatus']);
  797. //如果有同步分类则移动,没有则不移动
  798. if (isset($params['classId'])) {
  799. $masterClassId = $params['classId'];
  800. unset($params['classId']);
  801. $masterClass = ItemClassClass::getById($masterClassId, true);
  802. $masterClassName = $masterClass->name ?? '';
  803. $classList = ItemClassClass::getAllByCondition(['mainId' => $chainMainId], null, '*', null, true);
  804. if (!empty($classList)) {
  805. foreach ($classList as $currentClass) {
  806. if ($currentClass->name == $masterClassName) {
  807. $params['classId'] = $currentClass->id ?? 0;
  808. }
  809. }
  810. }
  811. }
  812. $chainProduct = ProductClass::getByCondition(['mainId' => $chainMainId, 'itemId' => $ptItemId], true);
  813. if (empty($chainProduct)) {
  814. continue;
  815. }
  816. if ($price != $chainProduct->price) {
  817. //花店价有变化
  818. self::changeSinglePrice($chainShop, $ptItemId, $price, $currentSkPrice);
  819. unset($params['price']);
  820. } else {
  821. //花店价没有变化,但散客价比花店价贵多少有修改时,也要改价
  822. if (isset($data['skMore']) && is_numeric($data['skMore']) && $data['skMore'] != $chainProduct->skMore) {
  823. self::changeSinglePrice($chainShop, $ptItemId, $price, $currentSkPrice);
  824. unset($params['price']);
  825. }
  826. }
  827. self::updateById($chainProduct->id, $params);
  828. }
  829. }
  830. }
  831. //变成自动改价 2021.4.14
  832. public static function autoPriceById($productId)
  833. {
  834. $product = self::getById($productId, true);
  835. if (empty($product)) {
  836. return false;
  837. }
  838. $price = bcadd($product->cost, $product->addPrice, 2);
  839. self::changePrice($product, $price, self::PRICE_LABEL_AUTO);
  840. }
  841. //获取当前门店下所有的product
  842. public static function getAllProduct($sjId, $shopId, $field = "*")
  843. {
  844. $where = [
  845. 'sjId' => $sjId,
  846. 'shopId' => $shopId,
  847. ];
  848. return self::getAllByCondition($where, null, $field);
  849. }
  850. //获取当前门店下所有花材的库存数量,及成本价,库存预警的花材数量 lqh 2021-04-20
  851. public static function getProductStockByShopId($sjId, $shopId)
  852. {
  853. $productInfo = self::getAllProduct($sjId, $shopId, "*");
  854. $data = [
  855. 'stockBigNum' => 0,
  856. 'stockSmallNum' => 0,
  857. 'stockCost' => 0,
  858. 'stockWarning' => 0,
  859. ];
  860. if ($productInfo) {
  861. foreach ($productInfo as $v) {
  862. $stock = self::formatStock($v['stock'], $v['ratio']);
  863. $data['stockBigNum'] = bcadd($data['stockBigNum'], $stock['bigNum']);
  864. $data['stockSmallNum'] = bcadd($data['stockSmallNum'], $stock['smallNum']);
  865. $data['stockCost'] = bcadd($data['stockCost'], bcmul($v['stock'], $v['cost'], 2), 2);
  866. if ($v['stock'] <= $v['stockWarning']) {
  867. $data['stockWarning']++;
  868. }
  869. }
  870. }
  871. return $data;
  872. }
  873. //补className
  874. public static function groupClassName($sjId, $data)
  875. {
  876. $itemClassInfo = ItemClassClass::getAll($sjId, "id,name");
  877. $classNameMap = [];
  878. foreach ($itemClassInfo as $v) {
  879. $classNameMap[$v['id']] = $v['name'];
  880. }
  881. foreach ($data as $k => $v) {
  882. $classId = $v['classId'];
  883. $className = $classNameMap[$classId] ?? '';
  884. $v['className'] = $className;
  885. $data[$k] = $v;
  886. }
  887. return $data;
  888. }
  889. //供货商的productId => 零售端的productId ,不存在的补productId(放在默认分类)
  890. //productList [{"productId":"113","bigNum":1,"smallNum":0,"classId":"-2","itemId":1}]
  891. public static function toggleProductList($productList, $hdShopId, $hdSjId, $hdMainId)
  892. {
  893. $itemIds = array_column($productList, "itemId");
  894. $hdProductData = self::getProductInfoByItemIds($itemIds, $hdMainId);
  895. $hdProductData = array_column($hdProductData, null, "itemId");
  896. //获取默认分类ID
  897. $defaultClassId = ItemClassClass::getDefaultClassId($hdMainId);
  898. if (empty($defaultClassId)) {
  899. util::fail('没有找到花材的默认分类');
  900. }
  901. foreach ($productList as $k => $v) {
  902. $itemId = $v['itemId'] ?? 0;
  903. if (!isset($hdProductData[$itemId])) {
  904. //不存在,则从平台新增
  905. $ptItem = \biz\item\classes\PtItemClass::getById($itemId);
  906. unset($ptItem['addTime']);
  907. unset($ptItem['updateTime']);
  908. $productData = $ptItem;
  909. $productData['sjId'] = $hdSjId;
  910. $productData['shopId'] = $hdShopId;
  911. $productData['mainId'] = $hdMainId;
  912. $productData['itemId'] = $itemId;
  913. $productData['classId'] = $defaultClassId;
  914. unset($productData['id']);
  915. $productData['rank'] = 'A';
  916. //计算价格
  917. $cost = $v['cost'] ?? 0;
  918. $addPrice = $v['addPrice'] ?? 0;
  919. $productData['price'] = bcadd($cost, $addPrice, 2);
  920. $addProduct = ProductClass::add($productData);
  921. $hdProductId = $addProduct['id'];
  922. } else {
  923. $hdProductId = $hdProductData[$itemId]['id'];
  924. }
  925. $productList[$k]['hdProductId'] = $hdProductId;
  926. }
  927. return $productList;
  928. }
  929. //供货商、零售端新开门店时,初始化花材
  930. public static function newShopInitProduct($sjId, $shopId, $newShopId, $adminId)
  931. {
  932. $product = self::getAllProduct($sjId, $shopId, "name,cover,classId,itemId,rank,price,priceLabel,cost,addPrice,stockWarning,weight,alias,py,ratio,bigUnit,smallUnit,bigUnitId,smallUnitId,inTurn");
  933. $productData = [];
  934. foreach ($product as $v) {
  935. $tmp = $v;
  936. $tmp['sjId'] = $sjId;
  937. $tmp['shopId'] = $newShopId;
  938. $tmp['adminId'] = $adminId;
  939. $productData[] = $tmp;
  940. }
  941. self::batchAdd($productData);
  942. }
  943. //花材销量增加
  944. public static function updateActualSoldById($id, $itemNum)
  945. {
  946. $data['actualSold'] = $itemNum;
  947. $res = self::updateById($id, $data);
  948. return $res;
  949. }
  950. //新增花材
  951. public static function addProduct($data, $currentShop)
  952. {
  953. $currentMainId = $currentShop->mainId ?? 0;
  954. $classId = $data['classId'] ?? 0;
  955. $mainId = $data['mainId'] ?? 0;
  956. $stockWarning = $data['stockWarning'] ?? false;
  957. $data['py'] = stringUtil::py($data['name']);
  958. $name = $data['name'] ?? false;
  959. $data['alias'] = $data['alias'] ?? '';
  960. $data['cover'] = isset($data['cover']) && !empty($data['cover']) ? $data['cover'] : '';
  961. $ratio = $data['ratio'] ?? false;
  962. $weight = $data['weight'] ?? false;
  963. $data['bigUnit'] = $data['bigUnit'] ?? '扎';
  964. $data['smallUnit'] = $data['smallUnit'] ?? '支';
  965. $data['shopId'] = $data['shopId'] ?? 0;
  966. $currentShopId = $data['shopId'];
  967. $data['sjId'] = $data['sjId'] ?? 0;
  968. if (!$data['sjId']) {
  969. util::fail("参数错误");
  970. }
  971. $stock = 0;
  972. if (isset($data['stock']) && is_numeric($data['stock'])) {
  973. if ($data['stock'] < 0) {
  974. util::fail("库存数不能小于0");
  975. }
  976. $stock = $data['stock'];
  977. }
  978. //没有库存则下架
  979. $data['status'] = $stock == 0 ? 2 : 1;
  980. if (empty($classId)) {
  981. util::fail("请选择分类");
  982. }
  983. if (isset($data['price']) == false || is_numeric($data['price']) == false || $data['price'] < 0) {
  984. util::fail("请输入价格");
  985. }
  986. if (isset($data['addPrice']) == false || is_numeric($data['addPrice']) == false) {
  987. util::fail("请输入加价");
  988. }
  989. if ($stockWarning === false) {
  990. util::fail("请输入库存预警值");
  991. }
  992. if ($name === false) {
  993. util::fail("请输入花材名称");
  994. }
  995. if ($ratio === false) {
  996. util::fail("请输入花材比例");
  997. }
  998. if ($weight === false) {
  999. util::fail("请输入花材重量");
  1000. }
  1001. $cat = ItemClassClass::getById($classId, true);
  1002. if (empty($cat)) {
  1003. util::fail("花材分类不存在");
  1004. }
  1005. if ($cat->mainId != $mainId) {
  1006. util::fail('不是您的分类');
  1007. }
  1008. $catName = $cat->name ?? '';
  1009. $connection = Yii::$app->db;
  1010. $transaction = $connection->beginTransaction();
  1011. try {
  1012. if (isset($data['itemId']) == false || empty($data['itemId'])) {
  1013. //添加新品种先在平台新增花材
  1014. $defaultInfo = PtItemClassClass::getByCondition(['isDefault' => 1]);
  1015. $defaultClassId = $defaultInfo['id'] ?? 0;
  1016. if (empty($defaultClassId)) {
  1017. util::fail('没有找到平台默认分类');
  1018. }
  1019. $itemData = $data;
  1020. $itemData['classId'] = $defaultClassId;
  1021. $itemData['skAddPrice'] = $itemData['skAddPrice'] ?? 3;
  1022. $itemData['hjAddPrice'] = $itemData['hjAddPrice'] ?? 2;
  1023. $itemData['zsAddPrice'] = $itemData['zsAddPrice'] ?? 1;
  1024. $ptItemInfo = PtItemClass::addItem($itemData);
  1025. $data['itemId'] = $ptItemInfo['id'];
  1026. } else {
  1027. //从平台导入花材
  1028. $has = self::getByCondition(['mainId' => $mainId, 'itemId' => $data['itemId']], true);
  1029. if (!empty($has)) {
  1030. util::fail('已经导入过了哦');
  1031. }
  1032. }
  1033. $ptItemId = $data['itemId'] ?? 0;
  1034. //小菊的结构
  1035. $ptItemInfo = PtItemClass::getById($ptItemId, true);
  1036. $data['variety'] = $ptItemInfo->variety ?? 0;
  1037. //花店价比进货价贵多少 2021-12-07 lqh 如果前端有传取前端的,没有则取pt
  1038. $addPrice = $data['addPrice'] ?? $ptItemInfo->addPrice;
  1039. $data['addPrice'] = $addPrice;
  1040. //花店价
  1041. $price = $data['price'] ?? 0;
  1042. if (empty($price) || $price <= 0) {
  1043. util::fail('请填写价格');
  1044. }
  1045. //散客价
  1046. $skMore = isset($data['skMore']) && $data['skMore'] > 0 ? $data['skMore'] : 0;
  1047. if ($skMore <= 0) {
  1048. util::fail('请填写散客价比花店价贵多少');
  1049. }
  1050. $data['skPrice'] = bcadd($price, $skMore, 2);
  1051. $data['property'] = 1;
  1052. $respond = self::add($data, true);
  1053. if ($stock > 0) {
  1054. //有库存数量,增加盘盈记录 2021.7.9 lqh
  1055. //增加盘点订单
  1056. $pdOrderSn = orderSn::getGhsCheckSn();
  1057. $pdOrderData = [];
  1058. $pdOrderData['orderSn'] = $pdOrderSn;
  1059. $pdOrderData['sjId'] = $data['sjId'];
  1060. $pdOrderData['shopId'] = $data['shopId'];
  1061. $pdOrderData['status'] = CheckOrderClass::STATUS_COMPLETE;
  1062. $pdOrderData['bigNum'] = $stock;
  1063. $pdOrderData['adminId'] = $data['adminId'];
  1064. $pdOrderData['smallNum'] = 0;
  1065. $pdOrderData['price'] = $data['price'];
  1066. $pdOrderData['remark'] = '初始库存';
  1067. CheckOrderClass::add($pdOrderData);
  1068. $pdOrderItemData = [];
  1069. $pdOrderItemData['orderSn'] = $pdOrderSn;
  1070. $pdOrderItemData['productId'] = $respond->id ?? 0;
  1071. $pdOrderItemData['itemId'] = $data['itemId'];
  1072. $pdOrderItemData['itemId'] = $data['itemId'];
  1073. $pdOrderItemData['itemNum'] = $stock;
  1074. $pdOrderItemData['itemStock'] = 0;
  1075. $pdOrderItemData['profitLostNum'] = $stock;
  1076. $itemInfo = [
  1077. 'itemName' => $name,
  1078. 'itemCover' => $data['cover'],
  1079. 'bigNum' => $stock,
  1080. 'smallNum' => 0,
  1081. 'bigNumStock' => 0,
  1082. 'smallNumStock' => 0,
  1083. 'bigNumProfitLoss' => $stock,
  1084. 'smallNumProfitLoss' => 0,
  1085. 'itemUnit' => 0,
  1086. 'ratio' => $ratio,
  1087. 'rank' => 'A',
  1088. 'bigUnit' => $data['bigUnit'],
  1089. 'smallUnit' => $data['smallUnit'],
  1090. ];
  1091. $pdOrderItemData['itemInfo'] = json_encode($itemInfo);
  1092. $pdOrderItemData['itemPrice'] = $data['price'];
  1093. $pdOrderItemData['itemCost'] = $data['cost'];
  1094. CheckOrderItemClass::add($pdOrderItemData);
  1095. $record = [];
  1096. $record['sjId'] = $data['sjId'];
  1097. $record['shopId'] = $data['shopId'];
  1098. //增加中央ID
  1099. $record['mainId'] = $currentMainId;
  1100. $record['orderSn'] = $pdOrderSn;
  1101. $record['itemId'] = $data['itemId'];
  1102. $record['productId'] = $respond->id ?? 0;
  1103. $record['itemNum'] = $stock;//盈亏数
  1104. $record['oldStock'] = 0;
  1105. $record['newStock'] = $stock; //新库存直接等于盘点的数量
  1106. $record['relateName'] = $data['staffName'] ?? '';
  1107. StockRecordClass::addCheckOrderRecord($record);
  1108. }
  1109. //在首店添加,则找到父级sj下的所有直营店,同步添加花材
  1110. if (isset($currentShop->default) && $currentShop->default == 1) {
  1111. $shopList = ShopClass::getAllByCondition(['sjId' => $data['sjId']], null, '*', null, true);
  1112. foreach ($shopList as $shop) {
  1113. $shopId = $shop->id ?? 0;
  1114. if (isset($shop->join) && $shop->join == 1) {
  1115. continue;
  1116. }
  1117. if ($shopId == $currentShop->id) {
  1118. //前面已经添加过了
  1119. continue;
  1120. }
  1121. $thisMainId = $shop->mainId ?? 0;
  1122. $data['shopId'] = $shopId;
  1123. $data['mainId'] = $thisMainId;
  1124. //不是当前门店,库存默认为0并且是下架状态。花材分类放在同名分类下,如果没有则放默认分类
  1125. if ($currentShopId != $shopId) {
  1126. $data['stock'] = 0;
  1127. $data['status'] = 2;
  1128. $currentClassId = 0;
  1129. $classList = ItemClassClass::getAllByCondition(['mainId' => $thisMainId], null, '*', null, true);
  1130. if (!empty($classList)) {
  1131. foreach ($classList as $currentClass) {
  1132. $currentName = $currentClass->name ?? '';
  1133. if ($currentName == $catName) {
  1134. $currentClassId = $currentClass->id ?? 0;
  1135. }
  1136. }
  1137. }
  1138. if (empty($currentClassId)) {
  1139. $defaultCat = ItemClassClass::getByCondition(['mainId' => $thisMainId, 'isDefault' => 1], true);
  1140. $currentClassId = $defaultCat->id ?? 0;
  1141. }
  1142. if (empty($currentClassId)) {
  1143. util::fail('直营店没有分类,也没有默认分类');
  1144. }
  1145. $data['classId'] = $currentClassId;
  1146. }
  1147. //已经有了不再添加
  1148. $chainHas = self::getByCondition(['mainId' => $thisMainId, 'itemId' => $ptItemId], true);
  1149. if (!empty($chainHas)) {
  1150. continue;
  1151. }
  1152. self::add($data);
  1153. }
  1154. }
  1155. $transaction->commit();
  1156. } catch (\Exception $exception) {
  1157. $transaction->rollBack();
  1158. Yii::info('失败原因:' . $exception->getMessage());
  1159. util::fail('添加失败');
  1160. }
  1161. }
  1162. //花材上下架
  1163. public static function changeStatus($productId, $status)
  1164. {
  1165. $data = ['status' => $status];
  1166. if ($status == 2) {
  1167. //库存=0时下架,特价一起去掉
  1168. $data['discountPrice'] = 0;
  1169. }
  1170. return self::updateById($productId, $data);
  1171. }
  1172. //获取itemId=>classId
  1173. public static function getItemIdClassIdMap($sjId)
  1174. {
  1175. $map = [];
  1176. $itemData = self::getGhsItemAll($sjId, "itemId,classId");
  1177. foreach ($itemData as $v) {
  1178. $map[$v['itemId']] = $v['classId'];
  1179. }
  1180. return $map;
  1181. }
  1182. //获取当前供货商下的所有item
  1183. public static function getGhsItemAll($sjId, $select = "*")
  1184. {
  1185. $where = [
  1186. 'sjId' => $sjId
  1187. ];
  1188. $data = self::getAllList($select, $where);
  1189. return $data;
  1190. }
  1191. //库存预警通知 ssh 20210909
  1192. public static function stockWarningAddQueue($product, $stock)
  1193. {
  1194. $warningNum = $product['stockWarning'] ?? 0;
  1195. if ($warningNum <= 0) {
  1196. return false;
  1197. }
  1198. $date = date("Y-m-d");
  1199. $productId = $product['id'] ?? 0;
  1200. $key = 'stockWarning_' . $productId . '_' . $date;
  1201. //当天已经放入队列通知的不再通知
  1202. $hasWarning = Yii::$app->redis->executeCommand('GET', [$key]);
  1203. if (isset($hasWarning) && !empty($hasWarning)) {
  1204. return false;
  1205. }
  1206. if ($stock <= $warningNum) {
  1207. Yii::$app->redis->executeCommand('SETEX', [$key, 86400, 'hasWarning']);
  1208. $shopId = $product['shopId'] ?? 0;
  1209. if (empty($shopId)) {
  1210. return false;
  1211. }
  1212. //队列方式去处理
  1213. $stockWarningListKey = 'stockWarningList_' . $shopId;
  1214. Yii::$app->redis->executeCommand('LPUSH', [$stockWarningListKey, $productId]);
  1215. }
  1216. }
  1217. //所有门店进行库存通知 ssh 20210909
  1218. public static function allShopStockWarningFromQueue()
  1219. {
  1220. $ghs = dict::getDict('ptStyle', 'ghs');
  1221. $shopList = ShopClass::getAllByCondition(['ptStyle' => $ghs], null, '*', null, true);
  1222. if (!empty($shopList)) {
  1223. foreach ($shopList as $key => $shop) {
  1224. $ids = [];
  1225. $shopId = $shop->id ?? 0;
  1226. $stockWarningListKey = 'stockWarningList_' . $shopId;
  1227. while ($count = Yii::$app->redis->executeCommand('LLEN', [$stockWarningListKey])) {
  1228. $productId = Yii::$app->redis->executeCommand('RPOP', [$stockWarningListKey]);
  1229. if (is_numeric($productId)) {
  1230. $ids[] = $productId;
  1231. }
  1232. }
  1233. if (empty($ids)) {
  1234. continue;
  1235. }
  1236. $ids = array_unique(array_filter($ids));
  1237. $productList = ProductClass::getAllByCondition(['id' => ['in', $ids]], null, '*', null, true);
  1238. if (!empty($productList)) {
  1239. WxMessageClass::stockWarningInform($shop, $productList);
  1240. }
  1241. }
  1242. }
  1243. }
  1244. //通过花材ID 获取mainId lqh 2022.03.20
  1245. public static function getMainIdByProductId($productId)
  1246. {
  1247. $product = self::getById($productId, false);
  1248. return $product['mainId'] ?? 0;
  1249. }
  1250. }