GoodsClass.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. <?php
  2. namespace bizHd\goods\classes;
  3. use biz\shop\classes\MainClass;
  4. use biz\stock\classes\GoodsStockRecordClass;
  5. use biz\shop\classes\ShopCapitalClass;
  6. use biz\stat\classes\StatCgPlantClass;
  7. use biz\stat\classes\StatOutClass;
  8. use bizHd\goods\services\GoodsCategoryService;
  9. use bizHd\message\classes\ChatClass;
  10. use bizHd\order\classes\OrderClass;
  11. use bizHd\work\classes\WorkClass;
  12. use bizHd\work\classes\WorkItemClass;
  13. use common\components\business;
  14. use common\components\dict;
  15. use common\components\imgUtil;
  16. use common\components\orderSn;
  17. use common\components\stringUtil;
  18. use common\components\util;
  19. use Yii;
  20. use bizHd\base\classes\BaseClass;
  21. use bizHd\goods\models\GoodsCategory;
  22. class GoodsClass extends BaseClass
  23. {
  24. public static $baseFile = '\bizHd\goods\models\Goods';
  25. const LOCK_STOCK_GOODS = 'lock_stock_goods_';//修改库存锁
  26. public static function orderCreateGoods($data)
  27. {
  28. $name = $data['name'] ?? '';
  29. $salePrice = $data['unitGoodsPrice'] ?? 0;
  30. $sjId = $data['sjId'] ?? 0;
  31. $mainId = $data['mainId'] ?? 0;
  32. $shopId = $data['shopId'] ?? 0;
  33. $kindId = $data['kindId'] ?? 0;
  34. $kindName = $data['kindName'] ?? '';
  35. $flowerNum = $data['flowerNum'] ?? 0;
  36. $status = 0;
  37. $delStatus = 0;
  38. $catId = $data['catId'] ?? 0;
  39. if (empty($catId)) {
  40. //制作台过来的使用默认分类id
  41. $hasCat = CategoryClass::getByCondition(['mainId' => $mainId, 'flower' => 1, 'default' => 1], true);
  42. if (empty($hasCat)) {
  43. $catData = [
  44. 'mainId' => $mainId,
  45. 'sjId' => $sjId,
  46. 'shopId' => $shopId,
  47. 'default' => 1,
  48. 'flower' => 1,
  49. 'categoryName' => '未分类',
  50. 'inTurn' => 0,
  51. 'status' => 0,
  52. ];
  53. $hasCat = CategoryClass::add($catData, true);
  54. }
  55. $catId = $hasCat->id ?? 0;
  56. if (empty($catId)) {
  57. util::fail('没有找到分类');
  58. }
  59. }
  60. $catIds = [$catId];
  61. $cover = !empty($data['cover']) ? $data['cover'] : 'default-img.png';
  62. $shopImg = [$cover];
  63. if (isset($data['shopImg']) && is_array($data['shopImg'])) {
  64. $shopImg = $data['shopImg'];
  65. }
  66. $spu = $data['spu'] ?? '';
  67. $addGoodsData = [
  68. 'name' => $name,
  69. 'flower' => 1,
  70. 'property' => 0,
  71. 'price' => $salePrice,
  72. 'sjId' => $sjId,
  73. 'mainId' => $mainId,
  74. 'shopId' => $shopId,
  75. 'status' => $status,
  76. 'delStatus' => $delStatus,
  77. 'shopImg' => $shopImg,
  78. 'catIds' => $catIds,
  79. 'cover' => $cover,
  80. 'spu' => $spu,
  81. 'stock' => 999,
  82. 'priceType' => 0,
  83. 'kindId' => $kindId,
  84. 'kindName' => $kindName,
  85. 'flowerNum' => $flowerNum,
  86. ];
  87. $respond = self::addGoods($addGoodsData);
  88. $id = $respond->id ?? 0;
  89. $property = dict::getDict('property', 'goods');
  90. $num = $data['num'] ?? 0;
  91. $unitType = 0;
  92. $unitPrice = $data['unitGoodsPrice'] ?? 0;
  93. return [['productId' => $id, 'num' => $num, 'unitType' => $unitType, 'unitPrice' => $unitPrice, 'property' => $property]];
  94. }
  95. public static function cgPlant($data, $shop)
  96. {
  97. $goodsData = $data['goods'] ?? '';
  98. if (empty($goodsData)) {
  99. $name = $data['name'] ?? '';
  100. if (empty($name)) {
  101. util::fail('请填写名称');
  102. }
  103. $salePrice = $data['salePrice'] ?? 0;
  104. $sjId = $data['sjId'] ?? 0;
  105. $shopId = $data['shopId'] ?? 0;
  106. $mainId = $data['mainId'] ?? 0;
  107. $status = $data['status'] ?? 0;
  108. $kindId = $data['kindId'] ?? 0;
  109. $kindName = $data['kindName'] ?? '';
  110. $delStatus = $data['delStatus'] ?? 0;
  111. $num = $data['num'] ?? 0;
  112. $cgPrice = $data['cgPrice'] ?? 0;
  113. $sendCost = $data['sendCost'] ?? 0;
  114. $shopImg = $data['shopImg'] ?? [];
  115. if ($sendCost > 0) {
  116. $div = bcdiv($sendCost, $num, 2);
  117. $cgPrice = bcadd($cgPrice, $div, 2);
  118. }
  119. $cover = isset($shopImg[0]) ? $shopImg[0] : '';
  120. $catId = $data['catId'] ?? 0;
  121. if (empty($catId)) {
  122. $hasCat = CategoryClass::getByCondition(['mainId' => $mainId, 'flower' => 0, 'default' => 1], true);
  123. if (empty($hasCat)) {
  124. $catData = [
  125. 'mainId' => $mainId,
  126. 'sjId' => $sjId,
  127. 'shopId' => $shopId,
  128. 'default' => 1,
  129. 'flower' => 0,
  130. 'categoryName' => '未分类',
  131. 'inTurn' => 0,
  132. 'status' => 0,
  133. ];
  134. $hasCat = CategoryClass::add($catData, true);
  135. }
  136. $catId = $hasCat->id ?? 0;
  137. if (empty($catId)) {
  138. util::fail('还是没有找到分类');
  139. }
  140. }
  141. $catIds = [$catId];
  142. $addGoodsData = [
  143. 'name' => $name,
  144. 'flower' => 0,
  145. 'property' => 0,
  146. 'price' => $salePrice,
  147. 'sjId' => $sjId,
  148. 'mainId' => $mainId,
  149. 'shopId' => $shopId,
  150. 'status' => $status,
  151. 'delStatus' => $delStatus,
  152. 'shopImg' => $shopImg,
  153. 'catIds' => $catIds,
  154. 'cover' => $cover,
  155. 'kindId' => $kindId,
  156. 'kindName' => $kindName
  157. ];
  158. $respond = self::addGoods($addGoodsData);
  159. $goodsId = $respond->id ?? 0;
  160. $goodsSn = $respond->sn ?? '';
  161. $goodsData = json_encode([['goodsId' => $goodsId, 'num' => $num, 'price' => $cgPrice, 'salePrice' => $salePrice, 'goodsSn' => $goodsSn, 'cover' => $cover]]);
  162. }
  163. $goodsData = json_decode($goodsData, true);
  164. if (empty($goodsData) || !is_array($goodsData)) {
  165. util::fail('没有找到商品');
  166. }
  167. $ids = array_column($goodsData, 'goodsId');
  168. $ids = array_unique(array_filter($ids));
  169. if (empty($ids)) {
  170. util::fail('没有商品哦');
  171. }
  172. $goodsInfo = self::getByIds($ids, null, 'id');
  173. $orderSn = orderSn::getGoodsCgSn();
  174. $mainId = $data['mainId'] ?? 0;
  175. $sjId = $data['sjId'] ?? 0;
  176. $shopId = $data['shopId'] ?? 0;
  177. $staffName = $data['staffName'] ?? '';
  178. $staffId = $data['staffId'] ?? 0;
  179. $goodsPrice = 0;
  180. $totalNum = 0;
  181. foreach ($goodsData as $postGoods) {
  182. $goodsId = $postGoods['goodsId'] ?? 0;
  183. $goodsSn = $postGoods['goodsSn'] ?? '';
  184. $name = $goodsInfo[$goodsId]['name'] ?? '';
  185. $kindId = $goodsInfo[$goodsId]['kindId'] ?? 0;
  186. $kindName = $goodsInfo[$goodsId]['kindName'] ?? '';
  187. $cover = $postGoods['cover'] ?? '';
  188. $num = $postGoods['num'] ?? 0;
  189. $totalNum = bcadd($num, $totalNum);
  190. $cgPrice = $postGoods['price'] ?? 0;
  191. $salePrice = $postGoods['salePrice'] ?? 0;
  192. if (empty($salePrice)) {
  193. $salePrice = $goodsInfo[$goodsId]['price'] ?? 0;
  194. }
  195. $totalPrice = bcmul($cgPrice, $num, 2);
  196. $addCgItem = [
  197. 'orderSn' => $orderSn,
  198. 'goodsId' => $goodsId,
  199. 'goodsSn' => $goodsSn,
  200. 'name' => $name,
  201. 'cover' => $cover,
  202. 'num' => $num,
  203. 'price' => $cgPrice,
  204. 'totalPrice' => $totalPrice,
  205. 'salePrice' => $salePrice,
  206. 'mainId' => $mainId,
  207. 'shopId' => $shopId,
  208. 'sjId' => $sjId,
  209. 'relateName' => $staffName,
  210. 'kindId' => $kindId,
  211. 'kindName' => $kindName,
  212. ];
  213. PlantCgItemClass::addData($addCgItem);
  214. $goodsPrice = bcadd($totalPrice, $goodsPrice, 2);
  215. }
  216. $remark = $data['remark'] ?? '';
  217. $sendCost = isset($data['sendCost']) && is_numeric($data['sendCost']) ? $data['sendCost'] : 0;
  218. $labourCost = $data['labourCost'] ?? 0;
  219. $otherCost = bcadd($sendCost, $labourCost, 2);
  220. $prePrice = bcadd($goodsPrice, $otherCost, 2);
  221. $orderPrice = $prePrice;
  222. $orderData = [
  223. 'orderSn' => $orderSn,
  224. 'mainId' => $mainId,
  225. 'orderSn' => $orderSn,
  226. 'stockChange' => 1,
  227. 'sjId' => $sjId,
  228. 'shopId' => $shopId,
  229. 'sendCost' => $sendCost,
  230. 'goodsPrice' => $goodsPrice,
  231. 'prePrice' => $prePrice,
  232. 'orderPrice' => $orderPrice,
  233. 'actPrice' => $prePrice,
  234. 'realPrice' => $prePrice,
  235. 'num' => $totalNum,
  236. 'staffName' => $staffName,
  237. 'staffId' => $staffId,
  238. 'status' => 3,
  239. 'remark' => $remark,
  240. ];
  241. $return = PlantCgClass::addData($orderData);
  242. $id = $return->id ?? 0;
  243. //总支出增加
  244. $main = MainClass::getLockById($mainId);
  245. if (empty($main)) {
  246. util::fail('没有找到门店53');
  247. }
  248. $currentCg = bcadd($main->totalPurchase, $orderPrice, 2);
  249. $main->totalPurchase = $currentCg;
  250. $currentCgPlant = bcadd($main->totalPurchasePlant, $orderPrice, 2);
  251. $main->totalPurchase = $currentCgPlant;
  252. $currentExpend = bcadd($main->totalExpend, $orderPrice, 2);
  253. $main->totalExpend = $currentExpend;
  254. $main->save();
  255. //支出统计
  256. StatOutClass::updateOrInsert($main, $shop, $orderPrice);
  257. //支出流水
  258. $capitalType = dict::getDict('capitalType', 'hdCgPlant', 'id');
  259. $event = '采购盆栽绿植等';
  260. $capitalData = [
  261. 'capitalType' => $capitalType,
  262. 'io' => 0,
  263. 'relateId' => $id,
  264. 'totalExpend' => $currentExpend,
  265. 'amount' => $orderPrice,
  266. 'mainId' => $mainId,
  267. 'event' => $event,
  268. 'mainId' => $mainId,
  269. ];
  270. ShopCapitalClass::addCapital($capitalData);
  271. //采购总量统计
  272. $cgNum = $return->num ?? 0;
  273. StatCgPlantClass::replace($main, $orderPrice, $cgNum);
  274. return $return;
  275. }
  276. //获取商品完整详情,包括商品的分类 ssh 2019.12.3
  277. public static function getGoodsInfo($id, $shop, $custom, $params)
  278. {
  279. $info = self::getById($id);
  280. if (empty($info)) {
  281. return [];
  282. }
  283. $list = self::groupGoodsBaseInfo([$info], $shop, $custom, $params);
  284. return current($list);
  285. }
  286. public static function getGoodsData($where, $params)
  287. {
  288. // 获取分页参数
  289. $page = Yii::$app->request->get('page', 1);
  290. $pageSize = Yii::$app->request->get('pageSize', 20);
  291. $flowerNum = $params['flowerNum'] ?? 0;
  292. // 查询某分类下有库存的商品
  293. $query = GoodsCategory::find()
  294. ->where($where)
  295. ->joinWith(['goods' => function ($query) use ($flowerNum) {
  296. $query->andWhere(['>', 'xhGoods.stock', 0]);
  297. if (isset($flowerNum) && $flowerNum > 0) {
  298. $query->andWhere(['xhGoods.flowerNum' => $flowerNum]);
  299. }
  300. }])
  301. ->andWhere(['xhGoodsCategory.delStatus' => 0])
  302. ->orderBy(['inTurn' => SORT_DESC]);
  303. // 获取总数
  304. $total = $query->count();
  305. // 分页查询
  306. $goodsList = $query->offset(($page - 1) * $pageSize)
  307. ->limit($pageSize)
  308. ->all();
  309. // 整理结果,只要有库存的商品
  310. $list = [];
  311. foreach ($goodsList as $goodsCategory) {
  312. if ($goodsCategory->goods) { // 只要有关联且有库存的商品
  313. $list[] = $goodsCategory->goods->attributes;
  314. }
  315. }
  316. if (!empty($list)) {
  317. $list = self::groupGoodsBaseInfo($list);
  318. }
  319. $totalPage = ceil($total / $pageSize);
  320. $moreData = $totalPage > $page ? 1 : 0;//是否还有更多数据
  321. return [
  322. 'list' => $list,
  323. 'total' => $total,
  324. 'page' => $page,
  325. 'pageSize' => $pageSize,
  326. 'moreData' => $moreData
  327. ];
  328. }
  329. //$data 可以是一维数组,也可以二维数组
  330. //花束的价格全部由这边输出 $custom $params 必须预留,为后面做准备
  331. //会返回两个参数 price 价格,涨价后的价格 priceBeforeRise 涨价前的价格,如果price==priceBeforeRise说明没有涨价
  332. public static function getFinalPrice($data, $shop, $custom, $params)
  333. {
  334. if (empty($data)) {
  335. return $data;
  336. }
  337. $mainId = $shop->mainId;
  338. $rise = GoodsSettingClass::getRise($mainId);
  339. $riseSwitch = $rise['riseSwitch'] ?? 0;
  340. $riseType = $rise['riseType'] ?? 0;
  341. $riseAmount = $rise['riseAmount'] ?? 0;
  342. reset($data);
  343. $current = current($data);
  344. if (is_array($current)) {
  345. //处理多个商品
  346. foreach ($data as $key => $item) {
  347. $item = self::modifyAndRisePrice($item, $shop, $riseSwitch, $riseType, $riseAmount, $custom, $params);
  348. $data[$key] = $item;
  349. }
  350. } else {
  351. //单个商品
  352. $data = self::modifyAndRisePrice($data, $shop, $riseSwitch, $riseType, $riseAmount, $custom, $params);
  353. }
  354. return $data;
  355. }
  356. //改价和涨价的处理 ssh 20250907
  357. public static function modifyAndRisePrice($data, $shop, $riseSwitch, $riseType, $riseAmount, $custom, $params)
  358. {
  359. $shopId = $shop->id;
  360. $userId = $custom['userId'] ?? 0;
  361. $goodsId = $data['id'] ?? 0;
  362. // $key = 'report_price:' . $shopId . '_' . $userId . '_' . $goodsId; // 从redis获取报价,关键词 shopId_userId_goodsId
  363. $key = ChatClass::getQuotedPriceKey($shopId, $userId, $goodsId);
  364. $reportPrice = Yii::$app->redis->executeCommand('GET', [$key]);
  365. if (floatval($reportPrice) > 0) {
  366. //只要报价,不管是有无价格类型,就从报价里取,不参与涨价
  367. $data['price'] = $reportPrice;
  368. //无价类型变成有价类型
  369. $data['priceType'] = 1;
  370. } else {
  371. if (isset($data['priceType']) && $data['priceType'] == 0) {
  372. //没有报价,无价商品不参与涨价
  373. } else {
  374. //没有报价,有价商品参与涨价
  375. $data = self::obeyRiseRule($data, $riseSwitch, $riseType, $riseAmount, $custom, $params);
  376. }
  377. }
  378. return $data;
  379. }
  380. //遵循涨价规则 ssh 20250828
  381. //会返回两个参数 price 价格或涨价后的价格 priceBeforeRise 涨价前的价格,如果price==priceBeforeRise说明没有涨价
  382. public static function obeyRiseRule($data, $riseSwitch, $riseType, $riseAmount, $custom, $params)
  383. {
  384. //注意制作单那边也会调到这个方法 $custom暂时传的是空的,搜索关键词 work_if_need_custom !!!!!!!!!!!!!!!!!!!!!
  385. $price = $data['price'] ?? 0;
  386. $priceBeforeRise = $price;
  387. //后台修改商品时,取原价,不需要显示涨价金额 getOriginalPrice=1 有涨价也强制取原价
  388. $getOriginalPrice = $params['getOriginalPrice'] ?? 0;
  389. if ($riseSwitch == 1 && $riseAmount > 0 && $getOriginalPrice == 0) {
  390. if ($riseType == 0) {
  391. //百分比
  392. $add = sprintf("%.1f", ($price * $riseAmount / 100));
  393. $price = bcadd($price, $add, 2);
  394. } else {
  395. //金额
  396. $price = bcadd($price, $riseAmount, 2);
  397. }
  398. }
  399. $data['price'] = $price;
  400. $data['priceBeforeRise'] = $priceBeforeRise;
  401. return $data;
  402. }
  403. public static function groupGoodsBaseInfo($list, $shop, $custom, $params)
  404. {
  405. if (empty($list)) {
  406. return [];
  407. }
  408. // 收集所有商品ID
  409. $goodsIds = array_column($list, 'id');
  410. // 一次性获取所有商品的分类关系
  411. $allGoodsCategories = GoodsCategoryClass::getGoodsHasCategoryIdsBatch($goodsIds);
  412. // &$val 这里的指向符号不能去掉
  413. foreach ($list as $key => &$val) {
  414. $id = $val['id'];
  415. //大中小图片转化
  416. $val = business::formatGoodsImg($val);
  417. //免费配送范围
  418. $val['freeSendDist'] = 5;
  419. $val['createDate'] = isset($val['createTime']) ? date("Y-m-d", strtotime($val['createTime'])) : '';
  420. //商品的分类
  421. $categoryIds = $allGoodsCategories[$id] ?? [];
  422. $val['categoryIdList'] = $categoryIds;
  423. $shortCover = $val['cover'] ?? '';
  424. $val['shortCover'] = $shortCover;
  425. $val['cover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_800,w_800";
  426. $val['smallCover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_230,w_230";
  427. $val['miniCover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_130,w_130";
  428. $val['bigCover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_800,w_800";
  429. $actualSold = $val['actualSold'] ?? 0;
  430. $sold = $val['sold'] ?? 0;
  431. $totalSold = bcadd($actualSold, $sold);
  432. $val['totalSold'] = $totalSold;
  433. $val = self::getFinalPrice($val, $shop, $custom, $params);
  434. $price = $val['price'] ?? 0;
  435. //冗余给前端使用的字段,这样花束开单前端很多东西就不再需要修改,重要,不要删除 ssh
  436. $val['bigCount'] = 0;
  437. $stock = $val['stock'] ?? 0;
  438. $val['bigNum'] = $stock;
  439. $val['smallNum'] = 0;
  440. $val['classId'] = 0;
  441. $val['bigPrice'] = $price;
  442. $val['smallPrice'] = $price;
  443. }
  444. //获取最终需要的价格
  445. return $list;
  446. }
  447. //新建商品 ssh 20220404
  448. public static function addGoods($data, $work = null)
  449. {
  450. $data['createTime'] = date("Y-m-d H:i:s");
  451. if (!empty($data['shopImg'])) {
  452. $data['shopImg'] = json_encode($data['shopImg']);
  453. }
  454. $data['py'] = stringUtil::py($data['name']);
  455. $flowerNum = $data['flowerNum'] ?? 0;
  456. $kindId = $data['kindId'] ?? 0;
  457. $kindName = $data['kindName'] ?? '';
  458. $sn = orderSn::getGoodsSn($data);
  459. $data['sn'] = $sn;
  460. $addStock = $data['stock'] ?? 0;
  461. unset($data['stock']);
  462. $info = self::add($data, true);
  463. $id = $info->id;
  464. $name = $info->name;
  465. $py = $data['py'] ?? '';
  466. $sjId = $data['sjId'] ?? 0;
  467. $mainId = $data['mainId'] ?? 0;
  468. $shopId = $data['shopId'] ?? 0;
  469. $flower = $data['flower'] ?? 0;
  470. $status = $data['status'] ?? 0;
  471. $staffName = $data['staffName'] ?? '';
  472. if ($addStock > 0) {
  473. $stockRespond = GoodsClass::addStock($id, $mainId, $addStock);
  474. $oldStock = $stockRespond['oldStock'] ?? 0;
  475. $newStock = $stockRespond['newStock'] ?? 0;
  476. $recordData = [];
  477. $recordData['sjId'] = $sjId;
  478. $recordData['shopId'] = $shopId;
  479. $recordData['mainId'] = $mainId;
  480. $recordData['orderSn'] = '';
  481. $recordData['goodsId'] = $id;
  482. $recordData['goodsNum'] = $addStock;
  483. $recordData['oldStock'] = $oldStock;
  484. $recordData['newStock'] = $newStock;
  485. $recordData['relateName'] = $staffName;
  486. GoodsStockRecordClass::pdGoods($recordData);
  487. }
  488. $delStatus = $data['delStatus'] ?? 0;
  489. $setItemNum = $data['setItemNum'] ?? 0;
  490. $categoryData = CategoryClass::getCategory($mainId);
  491. $catIds = $data['catIds'] ?? [];
  492. foreach ($catIds as $catId) {
  493. $cName = $categoryData[$catId]['categoryName'];
  494. $addCategory = [
  495. 'gId' => $id,
  496. 'name' => $name,
  497. 'cId' => $catId,
  498. 'cName' => $cName,
  499. 'sjId' => $sjId,
  500. 'py' => $py,
  501. 'mainId' => $mainId,
  502. 'flower' => $flower,
  503. 'flowerNum' => $flowerNum,
  504. 'sn' => $sn,
  505. 'status' => $status,
  506. 'delStatus' => $delStatus,
  507. 'setItemNum' => $setItemNum,
  508. 'kindId' => $kindId,
  509. 'kindName' => $kindName,
  510. ];
  511. GoodsCategoryClass::add($addCategory);
  512. CategoryClass::counters(['goodsNum' => 1], ['id' => $catId]);
  513. }
  514. if (!empty($work)) {
  515. $workSn = $work->workSn ?? '';
  516. $workItemList = WorkItemClass::getAllByCondition(['workSn' => $workSn], null, '*', null, true);
  517. if (!empty($workItemList)) {
  518. foreach ($workItemList as $item) {
  519. $itemId = $item->itemId ?? 0;
  520. $ptItemId = $item->ptItemId ?? 0;
  521. $num = $item->num ?? 0;
  522. $count = $item->count ?? 0;
  523. $ratio = $item->ratio ?? 0;
  524. $bigName = $item->bigName ?? '';
  525. $smallName = $item->smallName ?? '';
  526. $unitType = $item->unitType ?? 0;
  527. $unitName = $item->unitName ?? 0;
  528. $currentName = $item->name ?? '';
  529. $cover = $item->cover ?? '';
  530. $goodsItemData = [
  531. 'name' => $currentName,
  532. 'cover' => $cover,
  533. 'sjId' => $sjId,
  534. 'shopId' => $shopId,
  535. 'mainId' => $mainId,
  536. 'goodsId' => $id,
  537. 'itemId' => $itemId,
  538. 'ptItemId' => $ptItemId,
  539. 'num' => $num,
  540. 'count' => $count,
  541. 'ratio' => $ratio,
  542. 'bigName' => $bigName,
  543. 'smallName' => $smallName,
  544. 'unitType' => $unitType,
  545. 'unitName' => $unitName,
  546. ];
  547. GoodsItemClass::addData($goodsItemData);
  548. }
  549. }
  550. } else {
  551. $itemList = $data['itemList'] ?? '';
  552. $itemArr = json_decode($itemList, true);
  553. //新建花束有子项,采购绿植没有子项
  554. if (!empty($itemArr)) {
  555. foreach ($itemArr as $item) {
  556. $goodsItemData = [
  557. 'name' => $item['name'] ?? '',
  558. 'cover' => $item['cover'] ?? '',
  559. 'sjId' => $sjId,
  560. 'shopId' => $shopId,
  561. 'mainId' => $mainId,
  562. 'goodsId' => $id,
  563. 'itemId' => $item['id'] ?? 0,
  564. 'ptItemId' => $item['ptItemId'] ?? 0,
  565. 'num' => $item['num'] ?? 0,
  566. 'count' => $item['count'] ?? 0,
  567. 'ratio' => $item['ratio'] ?? 0,
  568. 'bigName' => $item['bigName'] ?? '',
  569. 'smallName' => $item['smallName'] ?? '',
  570. 'unitType' => $item['unitType'] ?? 0,
  571. 'unitName' => $item['unitName'] ?? '',
  572. ];
  573. GoodsItemClass::addData($goodsItemData);
  574. }
  575. }
  576. }
  577. return $info;
  578. }
  579. //更新商品
  580. public static function updateGoods($goods, $data, $staff)
  581. {
  582. $id = $goods['id'] ?? 0;
  583. $preSetItemNum = $goods['setItemNum'] ?? 0;
  584. $categoryIdList = !empty($data['categoryIdList']) ? $data['categoryIdList'] : [];
  585. unset($data['categoryIdList']);
  586. if (empty($categoryIdList)) {
  587. util::fail('没有选择分类');
  588. }
  589. $name = $data['name'] ?? '';
  590. $py = stringUtil::py($name);
  591. $flower = $data['flower'] ?? 0;
  592. $sjId = $data['sjId'] ?? 0;
  593. $mainId = $data['mainId'] ?? 0;
  594. $shopId = $data['shopId'] ?? 0;
  595. $status = $data['status'] ?? 0;
  596. $setItemNum = isset($data['setItemNum']) && is_numeric($data['setItemNum']) ? $data['setItemNum'] : $preSetItemNum;
  597. $categoryData = CategoryClass::getCategory($mainId);
  598. $hasCategoryIds = array_keys($categoryData);
  599. $diff = array_diff($categoryIdList, $hasCategoryIds);
  600. if (!empty($diff)) {
  601. util::fail('不能使用别人的分类');
  602. }
  603. //精确处理分类变更:分别处理删除、新增、修改三种情况
  604. $goodsHasCategoryIds = GoodsCategoryService::getGoodsHasCategoryIds($id);
  605. // 1. 找出需要删除的分类:原有分类中不在新分类列表中的
  606. $toDeleteCategoryIds = array_diff($goodsHasCategoryIds, $categoryIdList);
  607. if (!empty($toDeleteCategoryIds)) {
  608. //GoodsCategoryClass::deleteByCondition(['gId' => $id, 'cId' => ['in', $toDeleteCategoryIds]]); //不支持,改用 ActiveRecord 的 deleteAll 方法
  609. GoodsCategoryClass::getModel()::deleteAll(['and', ['gId' => $id], ['in', 'cId', $toDeleteCategoryIds]]); //先通过 getModel 获取 AR 实例,再调用 deleteAll 方法
  610. //\bizHd\goods\models\GoodsCategory::deleteAll(['and', ['gId' => $id], ['in', 'cId', $toDeleteCategoryIds]]); //直接调用 deleteAll 方法
  611. CategoryClass::counters(['goodsNum' => -1], ['id' => $toDeleteCategoryIds]);
  612. }
  613. // 2. 找出需要新增的分类:新分类列表中不在原有分类中的
  614. $toAddCategoryIds = array_diff($categoryIdList, $goodsHasCategoryIds);
  615. if (!empty($toAddCategoryIds)) {
  616. $addCategory = [];
  617. foreach ($toAddCategoryIds as $categoryId) {
  618. $cName = $categoryData[$categoryId]['categoryName'];
  619. $addCategory[] = [
  620. 'gId' => $id,
  621. 'name' => $name,
  622. 'py' => $py,
  623. 'cId' => $categoryId,
  624. 'cName' => $cName,
  625. 'sjId' => $sjId,
  626. 'flower' => $flower,
  627. 'mainId' => $mainId,
  628. 'setItemNum' => $setItemNum,
  629. ];
  630. }
  631. GoodsCategoryClass::batchAdd($addCategory);
  632. CategoryClass::counters(['goodsNum' => 1], ['id' => $toAddCategoryIds]);
  633. }
  634. // 3. 处理需要修改的分类:既在原有分类中也在新分类列表中的
  635. $toUpdateCategoryIds = array_intersect($goodsHasCategoryIds, $categoryIdList);
  636. if (!empty($toUpdateCategoryIds)) {
  637. foreach ($toUpdateCategoryIds as $categoryId) {
  638. $cName = $categoryData[$categoryId]['categoryName'];
  639. $updateData = [
  640. 'name' => $name,
  641. 'py' => $py,
  642. 'cName' => $cName,
  643. 'setItemNum' => $setItemNum,
  644. ];
  645. GoodsCategoryClass::updateByCondition(['gId' => $id, 'cId' => $categoryId], $updateData);
  646. }
  647. }
  648. // 字符串的,即认为是 图片URL
  649. if (isset($data['cover']) && is_string($data['cover'])) {
  650. } else {
  651. $data['cover'] = $data['shopImg'][0] ?? '';
  652. }
  653. $data['shopImg'] = json_encode($data['shopImg']);
  654. $data['py'] = $py;
  655. //库存可以修改
  656. if (isset($data['stock']) && is_numeric($data['stock'])) {
  657. $preStock = $goods['stock'] ?? 0;
  658. $newStock = $data['stock'];
  659. if ($newStock != $preStock) {
  660. if ($staff->super != 1) {
  661. util::fail('管理员才能修改库存');
  662. }
  663. if ($newStock < 0) {
  664. util::fail("库存不能小于0");
  665. }
  666. if (floor($newStock) != $newStock) {
  667. util::fail('库存请填写整数');
  668. }
  669. if ($newStock > $preStock) {
  670. $diffNum = bcsub($newStock, $preStock);
  671. $respond = GoodsClass::addStock($id, $mainId, $diffNum);
  672. } else {
  673. $diffNum = bcsub($preStock, $newStock);
  674. $checkStock = false;
  675. $params = [];
  676. $respond = GoodsClass::decreaseStock($id, $mainId, $diffNum, $checkStock, $params);
  677. }
  678. $oldStock = $respond['oldStock'] ?? 0;
  679. $newStock = $respond['newStock'] ?? 0;
  680. $recordData = [];
  681. $recordData['sjId'] = $sjId;
  682. $recordData['shopId'] = $shopId;
  683. $recordData['mainId'] = $mainId;
  684. $recordData['orderSn'] = '';
  685. $recordData['goodsId'] = $id;
  686. $recordData['goodsNum'] = $diffNum;
  687. $recordData['oldStock'] = $oldStock;
  688. $recordData['newStock'] = $newStock;
  689. $recordData['relateName'] = $staff->name ?? '';
  690. GoodsStockRecordClass::pdGoods($recordData);
  691. }
  692. unset($data['stock']);
  693. }
  694. self::updateById($id, $data);
  695. $itemList = $data['itemList'] ?? '';
  696. $itemArr = json_decode($itemList, true);
  697. if ($preSetItemNum == 0 && !empty($itemArr)) {
  698. GoodsItemClass::deleteByCondition(['goodsId' => $id]);
  699. foreach ($itemArr as $item) {
  700. $goodsItemData = [
  701. 'name' => $item['name'] ?? '',
  702. 'cover' => $item['cover'] ?? '',
  703. 'sjId' => $sjId,
  704. 'shopId' => $shopId,
  705. 'mainId' => $mainId,
  706. 'goodsId' => $id,
  707. 'itemId' => $item['id'] ?? 0,
  708. 'ptItemId' => $item['ptItemId'] ?? 0,
  709. 'num' => $item['num'] ?? 0,
  710. 'count' => $item['count'] ?? 0,
  711. 'ratio' => $item['ratio'] ?? 0,
  712. 'bigName' => $item['bigName'] ?? '',
  713. 'smallName' => $item['smallName'] ?? '',
  714. 'unitType' => $item['unitType'] ?? 0,
  715. 'unitName' => $item['unitName'] ?? '',
  716. ];
  717. GoodsItemClass::addData($goodsItemData);
  718. }
  719. }
  720. }
  721. // 删除商品 ruidian 2021.5.7
  722. public static function deleteGoods($id)
  723. {
  724. // 当前商品的分类
  725. $goodsHasCategoryIds = GoodsCategoryService::getGoodsHasCategoryIds($id);
  726. // 分类商品数-1
  727. CategoryClass::counters(['goodsNum' => -1], ['id' => $goodsHasCategoryIds]);
  728. GoodsClass::updateById($id, ['delStatus' => 1]);
  729. GoodsCategoryClass::updateByCondition(['gId' => $id], ['delStatus' => 1]);
  730. }
  731. //产品上下架 ssh 2019.12.8
  732. public static function changeStatus($id, $status)
  733. {
  734. self::updateById($id, ['status' => $status]);
  735. GoodsCategoryClass::updateByCondition(['gId' => $id], ['status' => $status]);
  736. }
  737. //验证商品的有效性 ssh 20201.2.1
  738. public static function valid($goods, $mainId)
  739. {
  740. if (empty($goods)) {
  741. util::fail('没有找到商品');
  742. }
  743. if (isset($goods['mainId']) && $goods['mainId'] == $mainId) {
  744. return true;
  745. }
  746. util::fail('此商品您无法查看哦');
  747. }
  748. //库存变动入口
  749. //加库存
  750. public static function addStock($goodsId, $mainId, $num, $params = [])
  751. {
  752. $key = self::LOCK_STOCK_GOODS . '_' . $goodsId;
  753. $lock = util::lock($key);
  754. if (!$lock) {
  755. util::fail("系统繁忙中,请稍后再试!");
  756. }
  757. $goodsData = self::getById($goodsId);
  758. if (!$goodsData) {
  759. util::unlock($key);
  760. util::fail("商品不存在");
  761. }
  762. $goodsMainId = $goodsData['mainId'];
  763. if ($mainId != $goodsMainId) {
  764. util::unlock($key);
  765. util::fail("非法参数");
  766. }
  767. //改库存
  768. $newStock = $goodsData['stock'] + $num;
  769. $data['stock'] = $newStock;
  770. $reduceSale = $params['reduceSale'] ?? 0;
  771. if ($reduceSale == 1) {
  772. $actualSold = $goodsData['actualSold'];
  773. $newSold = bcsub($actualSold, $num);
  774. $newSold = max($newSold, 0);
  775. $data['actualSold'] = $newSold;
  776. }
  777. self::updateById($goodsId, $data);
  778. util::unlock($key);
  779. return ['oldStock' => $goodsData['stock'], 'newStock' => $newStock];
  780. }
  781. //减库存
  782. public static function decreaseStock($goodsId, $mainId, $num, $checkStock = true, $params = [])
  783. {
  784. $key = self::LOCK_STOCK_GOODS . '_' . $goodsId;
  785. $lock = util::lock($key);
  786. if (!$lock) {
  787. util::fail("系统繁忙中,请稍后再试!");
  788. }
  789. $goodsData = self::getById($goodsId);
  790. if (!$goodsData) {
  791. util::unlock($key);
  792. util::fail("商品不存在");
  793. }
  794. $goodsMainId = $goodsData['mainId'];
  795. if ($mainId != $goodsMainId) {
  796. util::unlock($key);
  797. util::fail("非法参数");
  798. }
  799. //改库存
  800. $preStock = $goodsData['stock'] ?? 0;
  801. $newStock = bcsub($preStock, $num);
  802. if ($newStock < 0) {
  803. if ($checkStock) {
  804. $goodsName = $goodsData['name'] ?? '';
  805. util::fail($goodsName . ',库存不足,剩余:' . $preStock);
  806. }
  807. }
  808. $data['stock'] = $newStock;
  809. $addSale = $params['addSale'] ?? 0;
  810. if ($addSale == 1) {
  811. //开单减库存增加销量
  812. $actualSold = $goodsData['actualSold'] ?? 0;
  813. $newActualSold = bcadd($actualSold, $num);
  814. $data['actualSold'] = $newActualSold;
  815. }
  816. self::updateById($goodsId, $data);
  817. util::unlock($key);
  818. return ['oldStock' => $goodsData['stock'], 'newStock' => $newStock];
  819. }
  820. public static function generateSn($goods, $shop)
  821. {
  822. if (!empty($goods->sn)) {
  823. return $goods;
  824. }
  825. $shopId = $shop->id;
  826. $mainId = $shop->mainId;
  827. $data = ['shopId' => $shopId, 'mainId' => $mainId];
  828. $sn = orderSn::getGoodsSn($data);
  829. $goods->sn = $sn;
  830. $goods->save();
  831. return $goods;
  832. }
  833. }