| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250 |
- <?php
- namespace bizGhs\product\classes;
- use biz\item\classes\PtItemClass;
- use biz\item\classes\PtItemClassClass;
- use biz\item\classes\UnitClass;
- use biz\wx\classes\WxMessageClass;
- use bizGhs\base\classes\BaseClass;
- use bizGhs\custom\classes\CustomClass;
- use bizGhs\item\classes\CostChangeClass;
- use bizGhs\item\classes\ItemClassClass;
- use bizGhs\item\classes\PriceChangeClass;
- use bizGhs\merchant\classes\ShopClass;
- use bizGhs\order\classes\CheckOrderClass;
- use bizGhs\order\classes\CheckOrderItemClass;
- use bizGhs\order\traits\OrderTrait;
- use bizGhs\shop\classes\ShopAdminClass;
- use bizGhs\stock\classes\StockRecordClass;
- use common\components\dict;
- use common\components\imgUtil;
- use common\components\noticeUtil;
- use common\components\orderSn;
- use common\components\stringUtil;
- use common\components\util;
- use common\services\xhItemService;
- use PhpAmqpLib\Wire\AMQPTable;
- use Yii;
- class ProductClass extends BaseClass
- {
- use OrderTrait;
- public static $baseFile = '\bizGhs\product\models\Product';
- const PRICE_LABEL_AUTO = 1; //自动调价
- const PRICE_LABEL_CHANGE = 2; //改价
- const LOCK_STOCK = 'lock_stock';//修改库存锁
- const LOCK_ON_STOCK = 'lock_on_stock';//修改库存锁
- const LIMIT_BUY_KEY = 'limit_buy_';
- const CLEAR_MARK_KEY = 'limit_buy_clear_at:';
- const CLEAR_LOOP_KEY = 'limit_buy_clear_loop:';
- const LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY = 'limitBuyRollbackSnapshot'; //记录限购旧值快照缓存键
- const RECOVER_LIMIT_BUY_KEY = 'recover_limit_buy:'; //记录限购旧值快照缓存键
- public static function getNotShowFrontHideMainIds()
- {
- if (getenv('YII_ENV', 'local') == 'production') {
- //惠雅(52, 1459, 2126, 2128)、花样年华(1553)、泉城(60,1082)不显示隐藏按钮
- $notShowFrontHide = [52, 1459, 2126, 2128, 1553, 60, 1082];
- } else {
- $notShowFrontHide = [];
- }
- return $notShowFrontHide;
- }
- //添加花材的根方法 ssh 20230224
- public static function addBaseData($data)
- {
- $respond = self::add($data, true);
- $sjId = $data['sjId'] ?? 0;
- $mainId = $data['mainId'] ?? 0;
- $productId = $respond->id ?? 0;
- $ptItemId = $respond->itemId ?? 0;
- $cost = $respond->cost ?? 0;
- $name = $respond->name ?? '';
- $cover = $respond->cover ?? '';
- $staffId = $data['staffId'] ?? 0;
- $staffName = $data['staffName'] ?? '';
- if (isset($respond->hasCpId) == false || $respond->hasCpId == 0) {
- //noticeUtil::push("mainId:" . $mainId . "建的花材【{$name}】没有关联产品", '15280215347');
- }
- $ptItem = PtItemClass::getById($ptItemId, true);
- if (!empty($ptItem)) {
- $ptItem->useNum = 1;
- $ptItem->save();
- }
- if ($cost > 0) {
- $changeData = [
- 'ptStyle' => 2,
- 'sjId' => $sjId,
- 'mainId' => $mainId,
- 'itemId' => $productId,
- 'ptItemId' => $ptItemId,
- 'cost' => $cost,
- 'staffId' => $staffId,
- 'staffName' => $staffName,
- 'name' => $name ?? '',
- 'cover' => $cover,
- 'type' => 3,
- 'targetId' => $productId ?? 0,
- 'event' => '创建花材录入',
- ];
- CostChangeClass::addData($changeData);
- }
- $price = $data['price'] ?? 0;
- $skPrice = $data['skPrice'] ?? 0;
- if ($price > 0) {
- $changeData = [
- 'ptStyle' => 2,
- 'sjId' => $sjId,
- 'mainId' => $mainId,
- 'itemId' => $productId,
- 'ptItemId' => $ptItemId,
- 'price' => $price,
- 'skPrice' => $skPrice,
- 'staffId' => $staffId,
- 'staffName' => $staffName,
- 'name' => $name,
- 'cover' => $cover,
- 'event' => '创建花材录入',
- 'type' => 3,
- 'targetId' => $productId,
- ];
- PriceChangeClass::addData($changeData);
- }
- return $respond;
- }
- //根据itemIds获取相应的花材信息
- public static function getProductInfoByItemIds(array $itemIds, $hdMainId)
- {
- $where = ['itemId' => ['in', $itemIds], 'delStatus' => 0, 'mainId' => $hdMainId];
- $data = self::getAllList('*', $where);
- $data = self::groupItemBaseInfo($data);
- return $data;
- }
- //根据花材ID,获取花材名称,图片
- public static function groupItemBaseInfo($list)
- {
- //取得itemIds
- $itemIds = array_column($list, 'itemId');
- //获取相应的图片,名称,py
- $where = ['id' => ['in', $itemIds]];
- $data = xhItemService::getAllByCondition($where, null, '*');
- if (!empty($data)) {
- $data = array_column($data, NULL, 'id');
- foreach ($list as $k => $v) {
- if (isset($data[$v['itemId']]['cover']) && !empty($data[$v['itemId']]['cover'])) {
- $cover = self::groupImg($data[$v['itemId']]['cover']);
- } else {
- //没有图片时取默认图片 ssh 2021.2.18
- $cover = imgUtil::getPrefix() . '/hhb_small.png';
- }
- $unitNum = $data[$v['itemId']]['ratio'] ?? 0;
- $stockInfo = self::formatStock($v['stock'], $unitNum);
- $list[$k]['cover'] = $cover;
- $list[$k]['bigNum'] = $stockInfo['bigNum'];
- $list[$k]['smallNum'] = $stockInfo['smallNum'];
- $list[$k]['itemName'] = $data[$v['itemId']]['name'] ?? '';
- $list[$k]['py'] = $data[$v['itemId']]['py'] ?? '';
- $list[$k]['ratio'] = $unitNum ?? 0;
- //换算大小单位对应价格
- $list[$k]['bigPrice'] = $v['price']; //大单位价格就是product表存的价格
- $smallPrice = 0;
- if ($unitNum) {
- $smallPrice = bcdiv($v['price'], $unitNum, 2);
- }
- $list[$k]['smallPrice'] = $smallPrice;
- $list[$k]['bigUnit'] = $data[$v['itemId']]['bigUnit'];
- $list[$k]['smallUnit'] = $data[$v['itemId']]['smallUnit'];
- }
- }
- return $list;
- }
- //获取详情 ruidian 2021.5.3
- public static function getItemInfo($id, $ghs = [])
- {
- $info = self::getById($id);
- if (empty($info)) {
- return $info;
- }
- $level = $ghs->giveLevel ?? 1;
- $list = self::groupProductInfo([$info], $level);
- return current($list);
- }
- //库存预警列表用到的数据组合 ssh 20221225
- public static function warningGroup($list, $level = 0)
- {
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $list[$k]['cover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- }
- return $list;
- }
- /**
- * 库存预警分页列表(与 get-item-list 共用 where 条件):stock + onStock < stockWarning
- */
- public static function warningList($where, $order = ['inTurn' => SORT_DESC, 'actualSold' => SORT_DESC])
- {
- $get = Yii::$app->request->get();
- $page = isset($get['page']) ? intval($get['page']) : 1;
- $pageSize = isset($get['pageSize']) && !empty($get['pageSize']) ? intval($get['pageSize']) : Yii::$app->params['pageSize'];
- $offset = ($page - 1) * $pageSize;
- $model = self::getModel();
- $query = $model->conditionQuery($where)->andWhere('(`stock` + `onStock`) < `stockWarning`');
- $count = (clone $query)->count();
- $totalPage = $pageSize > 0 ? (int)ceil($count / $pageSize) : 0;
- if (!empty($order)) {
- $query->orderBy($order);
- }
- $list = $query->offset($offset)->limit($pageSize)->asArray()->all();
- return [
- 'totalNum' => $count,
- 'totalPage' => $totalPage,
- 'moreData' => $totalPage > $page ? 1 : 0,
- 'list' => $list,
- ];
- }
- //盘点用到的数据组合
- public static function checkItemGroup($list, $level = 0)
- {
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $list[$k]['cover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- $ratio = isset($v['ratio']) && $v['ratio'] > 0 ? $v['ratio'] : 1;
- $stockInfo = self::formatStock($v['stock'], $ratio);
- $list[$k]['bigNum'] = $stockInfo['bigNum'];
- $list[$k]['smallNum'] = $stockInfo['smallNum'];
- }
- return $list;
- }
- public static function stockOutGroup($list, $level = 0)
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $list[$k]['cover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- $list[$k]['price'] = $price;
- $list[$k]['bigPrice'] = $price;
- $smallRatio = $v['smallRatio'] ?? 0;
- $ratio = isset($v['ratio']) && $v['ratio'] > 0 ? $v['ratio'] : 20;
- $smallPrice = bcdiv($price, $ratio, 2);
- $smallPrice = bcmul($smallPrice, $smallRatio, 2);
- $list[$k]['smallPrice'] = $smallPrice;
- }
- return $list;
- }
- //拆散花材 ssh 20230329
- public static function partItemGroup($list, $level = 0)
- {
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $ratio = isset($v['ratio']) && $v['ratio'] > 0 ? $v['ratio'] : 20;
- $stockInfo = self::formatStock($v['stock'], $ratio);
- $list[$k]['bigNum'] = $stockInfo['bigNum'];
- $list[$k]['smallNum'] = $stockInfo['smallNum'];
- $list[$k]['cover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- }
- return $list;
- }
- //报损花材列表 ssh 20221226
- public static function breakItemGroup($list, $level = 0)
- {
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $ratio = isset($v['ratio']) && $v['ratio'] > 0 ? $v['ratio'] : 20;
- $stockInfo = self::formatStock($v['stock'], $ratio);
- $list[$k]['bigNum'] = $stockInfo['bigNum'];
- $list[$k]['smallNum'] = $stockInfo['smallNum'];
- $list[$k]['cover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- }
- return $list;
- }
- //采购花材列表用到的数据组合 ssh 20221225
- public static function cgItemGroup($list, $level = 0)
- {
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $list[$k]['cover'] = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- }
- return $list;
- }
- //预订 ssh 20231121
- public static function bookItemGroup($list, $level = 0)
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $cover = imgUtil::getPrefix() . 'hhb_small.png';
- if (!empty($shortCover)) {
- $parse = parse_url(self::groupImg($shortCover));
- if (empty($parse['query'])) {
- $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- } else {
- $cover = self::groupImg($shortCover);
- }
- }
- $ratio = isset($v['ratio']) && $v['ratio'] > 0 ? $v['ratio'] : 1;
- $list[$k]['cover'] = $cover;
- $stockInfo = self::formatStock($v['stock'], $ratio);
- $list[$k]['bigNum'] = $stockInfo['bigNum'];
- $list[$k]['smallNum'] = $stockInfo['smallNum'];
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- $list[$k]['price'] = $price;
- $list[$k]['bigPrice'] = $price;
- $smallRatio = $v['smallRatio'] ?? 0;
- $smallPrice = bcdiv($price, $ratio, 2);
- $smallPrice = bcmul($smallPrice, $smallRatio, 2);
- $list[$k]['smallPrice'] = $smallPrice;
- }
- return $list;
- }
- //花材列表用到的数据组合 ssh 20221225
- public static function kdItemGroup($list, $level = 0, $custom = [])
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- //这个参数应该是要作废的,但下面加的参数是有用的,多处要同步修改,关键词 abandon_add_price_map ,ssh 20260116
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- //但这边加的参数是有用的,给指定客户涨价的
- $addPriceMap['risePercent'] = $custom['risePercent'] ?? 0;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $cover = imgUtil::getPrefix() . 'hhb_small.png';
- if (!empty($shortCover)) {
- $parse = parse_url(self::groupImg($shortCover));
- if (empty($parse['query'])) {
- $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- } else {
- $cover = self::groupImg($shortCover);
- }
- }
- $ratio = isset($v['ratio']) && $v['ratio'] > 0 ? $v['ratio'] : 1;
- $list[$k]['cover'] = $cover;
- $stockInfo = self::formatStock($v['stock'], $ratio);
- $list[$k]['bigNum'] = $stockInfo['bigNum'];
- $list[$k]['smallNum'] = $stockInfo['smallNum'];
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- $list[$k]['originPrice'] = $list[$k]['price']; //原始价
- $list[$k]['price'] = $price;
- $list[$k]['bigPrice'] = $price;
- $smallRatio = $v['smallRatio'] ?? 0;
- $smallPrice = bcdiv($price, $ratio, 2);
- $smallPrice = bcmul($smallPrice, $smallRatio, 2);
- $list[$k]['smallPrice'] = $smallPrice;
- }
- return $list;
- }
- //花材列表用到的数据组合 ssh 20221225
- public static function itemListGroup($list, $level = 0)
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $cover = imgUtil::getPrefix() . 'hhb_small.png';
- if (!empty($shortCover)) {
- $parse = parse_url(self::groupImg($shortCover));
- if (empty($parse['query'])) {
- $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- } else {
- $cover = self::groupImg($shortCover);
- }
- }
- $list[$k]['cover'] = $cover;
- //今日特价、会员价
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- if ($level == 0) {
- //零售做特价时显示的原价,不能删除
- if (isset($v['skPrice'])) {
- $list[$k]['prePrice'] = $v['skPrice'];
- }
- }
- if (isset($v['discountPrice']) && $v['discountPrice'] > 0) {
- //做特价花材时,花材列表和改价列表显示的会员价和零售价,不能删除
- $list[$k]['hjPrice'] = floatval($v['hjDiscountPrice']);
- $list[$k]['skPrice'] = floatval($v['skDiscountPrice']);
- }
- $list[$k]['price'] = $price;
- $cost = $v['cost'] ?? 0;
- if ($price > 0) {
- $profit = bcsub($price, $cost, 2);
- $mll = bcdiv($profit, $price, 3);
- $mll = bcmul($mll, 100);
- $mll = round($mll, 1);
- } else {
- $mll = 0;
- }
- $list[$k]['mll'] = $mll;
- }
- return $list;
- }
- public static function cgStaffListGroup($list, $level = 0)
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $cover = imgUtil::getPrefix() . 'hhb_small.png';
- if (!empty($shortCover)) {
- $parse = parse_url(self::groupImg($shortCover));
- if (empty($parse['query'])) {
- $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- } else {
- $cover = self::groupImg($shortCover);
- }
- }
- $list[$k]['cover'] = $cover;
- //今日特价、会员价
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- if ($level == 0) {
- //零售做特价时显示的原价,不能删除
- if (isset($v['skPrice'])) {
- $list[$k]['prePrice'] = $v['skPrice'];
- }
- }
- if (isset($v['discountPrice']) && $v['discountPrice'] > 0) {
- //做特价花材时,花材列表和改价列表显示的会员价和零售价,不能删除
- $list[$k]['hjPrice'] = floatval($v['hjDiscountPrice']);
- $list[$k]['skPrice'] = floatval($v['skDiscountPrice']);
- }
- $list[$k]['price'] = $price;
- $cost = $v['cost'] ?? 0;
- if ($price > 0) {
- $profit = bcsub($price, $cost, 2);
- $mll = bcdiv($profit, $price, 3);
- $mll = bcmul($mll, 100);
- $mll = round($mll, 1);
- } else {
- $mll = 0;
- }
- $list[$k]['mll'] = $mll;
- }
- return $list;
- }
- //通用花材列表数组组合
- public static function changeStockGroup($list, $level = 0)
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $cover = imgUtil::getPrefix() . 'hhb_small.png';
- if (!empty($shortCover)) {
- $parse = parse_url(self::groupImg($shortCover));
- if (empty($parse['query'])) {
- $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- } else {
- $cover = self::groupImg($shortCover);
- }
- }
- $list[$k]['cover'] = $cover;
- $list[$k]['prePrice'] = $v['price'] ?? 0;
- //今日特价、会员价
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- //零售做特价时的原价
- if ($level == 0) {
- $currentAddPrice = $v['skMore'] ?? 0;
- $list[$k]['prePrice'] = bcadd($v['price'], $currentAddPrice, 2);
- }
- if (isset($v['discountPrice']) && $v['discountPrice'] > 0) {
- $currentAddPrice = $v['skMore'] ?? 0;
- $list[$k]['skPrice'] = bcadd($v['discountPrice'], $currentAddPrice, 2);
- }
- $list[$k]['price'] = $price;
- $cost = $v['cost'] ?? 0;
- $ml = 0;
- if ($price > 0) {
- $profit = bcsub($price, $cost, 2);
- $ml = $profit;
- $mll = bcdiv($profit, $price, 3);
- $mll = bcmul($mll, 100);
- $mll = round($mll, 1);
- } else {
- $mll = 0;
- }
- $list[$k]['mll'] = $mll;
- $list[$k]['ml'] = $ml;
- }
- return $list;
- }
- //通用花材列表数组组合
- public static function changePriceGroup($list, $level = 0)
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $cover = imgUtil::getPrefix() . 'hhb_small.png';
- if (!empty($shortCover)) {
- $parse = parse_url(self::groupImg($shortCover));
- if (empty($parse['query'])) {
- $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- } else {
- $cover = self::groupImg($shortCover);
- }
- }
- $list[$k]['cover'] = $cover;
- $list[$k]['prePrice'] = $v['price'] ?? 0;
- //今日特价、会员价
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- if ($level == 0) {
- //零售做特价时显示的原价,不能删除
- if (isset($v['skPrice'])) {
- $list[$k]['prePrice'] = $v['skPrice'];
- }
- }
- if (isset($v['discountPrice']) && $v['discountPrice'] > 0) {
- //做特价花材时,花材列表和改价列表显示的会员价和零售价,不能删除
- $list[$k]['hjPrice'] = floatval($v['hjDiscountPrice']);
- $list[$k]['skPrice'] = floatval($v['skDiscountPrice']);
- }
- $list[$k]['price'] = $price;
- $cost = $v['avCost'] ?? 0;
- $ml = 0;
- if ($price > 0) {
- $profit = bcsub($price, $cost, 2);
- $ml = $profit;
- $mll = bcdiv($profit, $price, 3);
- $mll = bcmul($mll, 100);
- $mll = round($mll, 1);
- } else {
- $mll = 0;
- }
- $list[$k]['mll'] = $mll;
- $list[$k]['ml'] = $ml;
- }
- return $list;
- }
- //简单组合
- public static function simpleGroup($list, $level = 0)
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $cover = imgUtil::getPrefix() . 'hhb_small.png';
- if (!empty($shortCover)) {
- $parse = parse_url(self::groupImg($shortCover));
- if (empty($parse['query'])) {
- $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- } else {
- $cover = self::groupImg($shortCover);
- }
- }
- $list[$k]['cover'] = $cover;
- $list[$k]['prePrice'] = $v['price'] ?? 0;
- //今日特价、会员价
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- //零售做特价时的原价
- if ($level == 0) {
- $currentAddPrice = $v['skMore'] ?? 0;
- $list[$k]['prePrice'] = bcadd($v['price'], $currentAddPrice, 2);
- }
- if (isset($v['discountPrice']) && $v['discountPrice'] > 0) {
- $currentAddPrice = $v['skMore'] ?? 0;
- $list[$k]['skPrice'] = bcadd($v['discountPrice'], $currentAddPrice, 2);
- }
- $list[$k]['price'] = $price;
- }
- return $list;
- }
- //通用花材列表数组组合
- public static function groupProductInfo($list, $level = 0, $custom = [])
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- //这个参数应该是要作废的,但下面加的参数是有用的,多处要同步修改,关键词 abandon_add_price_map ,ssh 20260116
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- //但这边加的参数是有用的,给指定客户涨价的
- $addPriceMap['risePercent'] = $custom['risePercent'] ?? 0;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $cover = imgUtil::getPrefix() . 'hhb_small.png';
- $bigCover = imgUtil::getPrefix() . 'hhb_small.png';
- $largeCover = imgUtil::getPrefix() . 'hhb_small.png';
- if (!empty($shortCover)) {
- $parse = parse_url(self::groupImg($shortCover));
- if (empty($parse['query'])) {
- $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- } else {
- $cover = self::groupImg($shortCover);
- }
- $bigCover = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_700,w_700";
- $largeCover = imgUtil::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_990,w_990";
- }
- $ratio = isset($v['ratio']) && $v['ratio'] > 0 ? $v['ratio'] : 1;
- $stockInfo = self::formatStock($v['stock'], $ratio);
- $list[$k]['cover'] = $cover;
- $list[$k]['bigCover'] = $bigCover;
- $list[$k]['largeCover'] = $largeCover;
- $list[$k]['shortCover'] = $shortCover;
- $list[$k]['bigNum'] = $stockInfo['bigNum'];
- $list[$k]['smallNum'] = $stockInfo['smallNum'];
- $list[$k]['itemName'] = $v['name'] ?? '';
- $list[$k]['prePrice'] = $v['price'] ?? 0;
- //今日特价、会员价
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- $list[$k]['price'] = $price;
- $list[$k]['bigPrice'] = $price;
- $smallRatio = $v['smallRatio'] ?? 0;
- $smallPrice = bcdiv($price, $ratio, 2);
- $smallPrice = bcmul($smallPrice, $smallRatio, 2);
- $list[$k]['smallPrice'] = $smallPrice;
- $preSellDate = $v['presellDate'] ?? '';
- $preSellDateList = [];
- $preSellDateShow = [];
- if (!empty($preSellDate)) {
- $dateArr = explode(',', trim($preSellDate));
- if (!empty($dateArr)) {
- foreach ($dateArr as $sellTime) {
- $sellDate = date("Y-m-d", $sellTime);
- $showDate = date("n.j", $sellTime);
- $preSellDateList[] = $sellDate;
- $preSellDateShow[] = $showDate;
- }
- }
- }
- $list[$k]['presellDateList'] = $preSellDateList;
- $list[$k]['presellDateShow'] = $preSellDateShow;
- //这个很重要不能随意乱改
- $autoPrice = bcadd($v['cost'], $v['addPrice'], 2);
- $skMore = $v['skMore'] ?? 0;
- $skAutoPrice = bcadd($autoPrice, $skMore, 2);
- $list[$k]['autoPrice'] = $autoPrice;
- $list[$k]['autoSkPrice'] = $skAutoPrice;
- $list[$k]['userPrice'] = 0;
- // 限购缓存
- if ($v['limitBuy'] > 0) {
- $limitKey = self::LIMIT_BUY_KEY . $v['id'];
- $has = Yii::$app->redis->executeCommand('HEXISTS', [$limitKey, 0]);
- if (!empty($has)) {
- // 获取缓存超时时间
- $expire = Yii::$app->redis->executeCommand('TTL', [$limitKey]);
- if ($expire > 0) {
- $list[$k]['limitBuyClearTime'] = date('Y-m-d H:i:s', time() + $expire);
- } else {
- $list[$k]['limitBuyClearTime'] = '';
- }
- } else {
- $list[$k]['limitBuyClearTime'] = '';
- }
- }
- }
- return $list;
- }
- //零售端花店采购
- public static function hdCgGroup($list, $level = 0, $ghs = [])
- {
- //各个等级对应的price addPrice字段
- $priceMap = CustomClass::$levelPriceKeyMap;
- //这个参数应该是要作废的,但下面加的参数是有用的,多处要同步修改,关键词 abandon_add_price_map ,ssh 20260116
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- //这里加的参数是有用的 ssh 20260116
- $addPriceMap['risePercent'] = $ghs['risePercent'] ?? 0;
- foreach ($list as $k => $v) {
- $shortCover = $v['cover'] ?? '';
- $cover = imgUtil::getPrefix() . 'hhb_small.png';
- if (!empty($shortCover)) {
- $parse = parse_url(self::groupImg($shortCover));
- if (empty($parse['query'])) {
- $cover = self::groupImg($shortCover) . "?x-oss-process=image/resize,m_fill,h_100,w_100";
- } else {
- $cover = self::groupImg($shortCover);
- }
- }
- $ratio = isset($v['ratio']) && $v['ratio'] > 0 ? $v['ratio'] : 1;
- $stockInfo = self::formatStock($v['stock'], $ratio);
- $list[$k]['cover'] = $cover;
- $list[$k]['prePrice'] = $v['price'] ?? 0;
- $list[$k]['bigNum'] = $stockInfo['bigNum'];
- $list[$k]['smallNum'] = $stockInfo['smallNum'];
- $list[$k]['itemName'] = $v['name'] ?? '';
- //今日特价、会员价
- $price = self::getFinalPrice($v, $level, $priceMap, $addPriceMap);
- $defaultGradePrice = 0;
- if ($level == 2) {
- //如果是大客户,取出更低一级的客户价格,用于前端对比展示:显示原价和会员价
- $littleLevel = 1;
- $defaultGradePrice = self::getFinalPrice($v, $littleLevel, $priceMap, $addPriceMap);
- }
- $list[$k]['defaultGradePrice'] = $defaultGradePrice;
- $list[$k]['myLevel'] = $level;
- $reachPrice = 0;
- //满10扎多少钱
- if (isset($v['reachNum']) && $v['reachNum'] > 0) {
- $reachNumDiscount = $v['reachNumDiscount'] ?? 0;
- $reachPrice = bcsub($price, $reachNumDiscount, 2);
- $reachPrice = $reachPrice <= 0 ? 0.01 : floatval($reachPrice);
- }
- $list[$k]['reachPrice'] = $reachPrice;
- $list[$k]['price'] = $price;
- $list[$k]['bigPrice'] = $price;
- $smallRatio = $v['smallRatio'] ?? 0;
- $smallPrice = bcdiv($price, $ratio, 2);
- $smallPrice = bcmul($smallPrice, $smallRatio, 2);
- $list[$k]['smallPrice'] = $smallPrice;
- $preSellDate = $v['presellDate'] ?? '';
- $preSellDateShow = [];
- if (!empty($preSellDate)) {
- $dateArr = explode(',', trim($preSellDate));
- if (!empty($dateArr)) {
- foreach ($dateArr as $sellTime) {
- $showDate = date("n.j", $sellTime);
- $preSellDateShow[] = $showDate;
- }
- }
- }
- $list[$k]['presellDateShow'] = $preSellDateShow;
- unset($list[$k]['presellDate']);
- unset($list[$k]['addPrice']);
- unset($list[$k]['cost']);
- unset($list[$k]['skMore']);
- }
- return $list;
- }
- /**
- * 输出价格 ssh 20211009
- * @param $product 花材信息
- * @param $level 等级
- * @param $priceMap 各个等级对应的price addPrice字段
- * @param $params 原来是 $addPriceMap,现在 $addPriceMap 值没用了,把它改成 $params ,用作传别的参数
- * @param int $changePrice 开单改价
- * @param int $buyNum 当前购买数量
- * @param int $totalBuyNum 已购买总数量
- * @return int|string|null
- * @throws \Exception
- */
- public static function getFinalPrice($product, $level, $priceMap, $params, $changePrice = 0, $buyNum = 0, $totalBuyNum = 0)
- {
- //开单改价优先级最高
- if ($changePrice > 0) {
- return $changePrice;
- }
- if (empty($product) || isset($product['price']) == false) {
- return 0;
- }
- if ($level == 9) {
- $avCost = $product['avCost'] ?? 0;
- $price = $avCost;
- if ($price <= 0) {
- $cost = $product['cost'] ?? 0;
- $price = $cost;
- }
- } else {
- $currentPriceField = $priceMap[$level] ?? 'price';
- $price = $product[$currentPriceField] ?? 0;
- }
- //特价与限购的综合处理
- $discountPrice = $product['discountPrice'] ?? 0;
- $hjDiscountPrice = $product['hjDiscountPrice'] ?? 0;
- $skDiscountPrice = $product['skDiscountPrice'] ?? 0;
- $limitBuy = $product['limitBuy'];
- if ($discountPrice > 0) {
- $oldPrice = $price;
- if ($level == 0) {
- $price = $skDiscountPrice;
- }
- if ($level == 1) {
- $price = $discountPrice;
- }
- if ($level == 2) {
- $price = $hjDiscountPrice;
- }
- //超出限购情况的价格计算
- if ($limitBuy > 0 && $totalBuyNum > $limitBuy) {
- $hasBuyNum = $totalBuyNum - $buyNum;
- if ($hasBuyNum >= $limitBuy) {
- $price = $oldPrice;
- } else {
- $overBuyNum = $totalBuyNum - $limitBuy;
- $overBuyPrice = bcmul($overBuyNum, $oldPrice, 2); // 超出限购部分的价格
- $leftBuyNum = $buyNum - $overBuyNum;
- $leftBuyPrice = bcmul($leftBuyNum, $price, 2); // 未超出限购部分的价格
- $price = bcdiv($overBuyPrice + $leftBuyPrice, $buyNum, 2); // 最终价格
- }
- }
- }
- //满多少数量,再优惠多少钱
- $reachNum = $product['reachNum'] ?? 0;
- $reachNumDiscount = $product['reachNumDiscount'] ?? 0;
- if ($reachNum > 0) {
- if ($buyNum >= $reachNum) {
- if ($reachNumDiscount >= $price) {
- util::fail('优惠价比售价还大');
- }
- $price = bcsub($price, $reachNumDiscount, 2);
- }
- }
- //这个 $risePercent 可能是正整数,也可能是负整数,如果是10表示$price涨价10%,如果是-10表示降价10%,同时$price降价后,不能小于0.01
- $risePercent = $params['risePercent'] ?? 0;
- if ($risePercent != 0) {
- // risePercent为正数表示涨价百分比,负数表示降价百分比
- $priceAdjustment = bcmul($price, bcdiv($risePercent, 100, 4), 2);
- $price = bcadd($price, $priceAdjustment, 2);
- // 降价后不能小于0.01
- if ($price < 0.01) {
- $price = 0.01;
- }
- }
- return $price;
- }
- //根据花材ID,库存=》 计算出多少扎,多少支
- public static function formatStockByItemId($itemId, $stock)
- {
- $unitNum = xhItemService::getItemUnitNum($itemId);
- return self::formatStock($stock, $unitNum);
- }
- //花材的库存转换: 库存是小数,根据各个花材的unitNum, 计算出多少扎,多少支
- public static function formatStock($stock, $unitNum)
- {
- $pn = true; //正数
- if ($stock < 0) {
- $pn = false;
- $stock = abs($stock);
- }
- $bigNum = floor($stock); // 扎
- $stockArr = explode('.', $stock);
- $smallNum = 0; //支
- if (count($stockArr) === 2) {
- $smallNum = bcmul(($stock - $bigNum), $unitNum);
- }
- if (!$pn) {
- $bigNum *= -1;
- $smallNum *= -1;
- }
- return [
- 'bigNum' => $bigNum,
- 'smallNum' => $smallNum,
- ];
- }
- //根据 花材ID,将花材大小数量 换算成小数
- public static function mergeItemNumByItemId($bigNum, $smallNum, $itemId)
- {
- $unitNum = xhItemService::getItemUnitNum($itemId);
- return self::mergeItemNum($bigNum, $smallNum, $unitNum);
- }
- //花材扎、支 合并转换 小数
- /**
- * @param $bigNum 大单位 数量
- * @param $smallNum 小单位 数量
- * @param $unitNum 花材比例
- * @return string
- */
- public static function mergeItemNum($bigNum, $smallNum, $unitNum)
- {
- $stockDecimal = 0;
- if ($unitNum > 0) {
- $stockDecimal = bcdiv($smallNum, $unitNum, 2);
- }
- $itemNum = bcadd($bigNum, $stockDecimal, 2);
- return $itemNum;
- }
- //获取常用的itemIds
- public static function getOftenItemIds($shopId)
- {
- $data = self::getLimitList("itemId", ['shopId' => $shopId], 10, ['actualSold' => SORT_DESC, 'inTurn' => SORT_DESC]);
- if ($data) {
- $data = array_column($data, 'itemId');
- }
- return $data;
- }
- /**
- * 库存变动统一入口:用数据库行锁串行化同一花材的读-算-写,避免并发覆盖库存。
- * 出现并发时,会自动重试3次。
- * @param $productId
- * @param callable $callback
- * @return mixed
- * @throws \Exception
- */
- private static function runStockMutation($productId, callable $callback)
- {
- $db = Yii::$app->db;
- $currentTransaction = $db->getTransaction();
- $ownTransaction = empty($currentTransaction) || !$currentTransaction->isActive;
- $mutation = function () use ($db, $currentTransaction, $ownTransaction, $productId, $callback) {
- $transaction = $ownTransaction ? $db->beginTransaction() : $currentTransaction;
- try {
- $productData = self::getLockById($productId);
- if (!$productData) {
- util::fail("花材不存在");
- }
- $respond = call_user_func($callback, $productData);
- if ($ownTransaction) {
- $transaction->commit();
- }
- return $respond;
- } catch (\Exception $exception) {
- if ($ownTransaction && !empty($transaction) && $transaction->isActive) {
- $transaction->rollBack();
- }
- throw $exception;
- }
- };
- if (!$ownTransaction) {
- return call_user_func($mutation);
- }
- return util::runWithDbConcurrencyRetry($mutation);
- }
- //加库存,允许负库存,负数数量(盘点时)
- public static function addStock($productId, $itemNumBundle, $itemNumPiece)
- {
- //小单位库存不再考虑 ssh 20230303
- //$itemNumPiece = 0;
- $callback = function ($productData) use ($itemNumBundle, $itemNumPiece) {
- $oldStock = $productData->stock;
- $ratio = $productData->ratio;
- //转成小数,加库存
- $itemNum = self::mergeItemNum($itemNumBundle, $itemNumPiece, $ratio);
- $newStock = bcadd($oldStock, $itemNum, 2);
- $productData->stock = $newStock;
- //上架
- if ($newStock > 0 && $productData->status == 2) {
- $productData->status = 1;
- }
- $productData->save();
- return ['oldStock' => $oldStock, 'newStock' => $newStock, 'itemNum' => $itemNum];
- };
- return self::runStockMutation($productId, $callback);
- }
- //加路上库存
- public static function addOnStockByItemNum($productId, $itemNum)
- {
- $callback = function ($productInfo) use ($itemNum) {
- $oldOnStock = $productInfo->onStock;
- $newOnStock = bcadd($oldOnStock, $itemNum);
- $productInfo->onStock = $newOnStock;
- $productInfo->save();
- return ['oldOnStock' => $oldOnStock, 'newOnStock' => $newOnStock, 'itemNum' => $itemNum];
- };
- return self::runStockMutation($productId, $callback);
- }
- //加库存
- public static function addStockByItemNum($productId, $itemNum, $params = [])
- {
- $callback = function ($productData) use ($itemNum, $params) {
- $oldStock = $productData->stock;
- $newItemCost = 0;
- $newItemStock = 0;
- $avCost = 0;
- $changeCost = 0;
- $unitCost = 0;
- //涉及平均成本计算的,多处要修改,搜索关键词 calc_av_cost
- if (!empty($params['cost']) && $params['cost'] > 0) {
- //原库存和原成本,也叫剩余库存和剩余成本
- $oldItemStock = $productData->stock ?? 0;
- $oldAvCost = $productData->avCost ?? 0;
- $oldItemCost = bcmul($oldItemStock, $oldAvCost, 2);
- //变动库存和成本
- $unitCost = $params['cost'];
- $changeCost = bcmul($params['cost'], $itemNum, 2);
- //新库存和新成本
- $newItemCost = bcadd($changeCost, $oldItemCost, 2);
- $newItemStock = bcadd($itemNum, $oldItemStock, 2);
- if ($newItemStock > 0) {
- $avCost = bcdiv($newItemCost, $newItemStock, 2);
- } else {
- $newItemStock = 0;
- $newItemCost = 0;
- }
- $productData->avCost = $avCost;
- $productData->totalCost = $newItemCost;
- $productData->totalStock = $newItemStock;
- }
- $newStock = bcadd($oldStock, $itemNum, 2);
- $productData->stock = $newStock;
- //上架
- if ($newStock > 0 && $productData->status == 2) {
- $productData->status = 1;
- }
- //如果花材删除了则要恢复,用于调拨出库时,入库店的花材被删除
- if ($newStock > 0 && $productData->delStatus == 1) {
- $productData->delStatus = 0;
- }
- $productData->save();
- return ['oldStock' => $oldStock, 'newStock' => $newStock, 'itemNum' => $itemNum,
- 'avCost' => $avCost, 'totalCost' => $newItemCost, 'totalStock' => $newItemStock, 'changeCost' => $changeCost, 'unitCost' => $unitCost];
- };
- return self::runStockMutation($productId, $callback);
- }
- //减库存,允许负库存,负数数量(盘点时)
- //checkStock boolean 是否需要判断库存
- //addSold boolean 是否增加销量,报损和拆散不要增加销量
- public static function decreaseStock($productId, $itemNumBundle, $itemNumPiece, $checkStock = false, $addSold = true, $params = [])
- {
- //小单位库存不再考虑 ssh 20230303
- //$itemNumPiece = 0;
- $callback = function ($productData) use ($productId, $itemNumBundle, $itemNumPiece, $checkStock, $addSold, $params) {
- $oldStock = $productData->stock;
- $ratio = $productData->ratio;
- //转成小数,更新库存
- $itemNum = self::mergeItemNum($itemNumBundle, $itemNumPiece, $ratio);
- $newStock = bcsub($oldStock, $itemNum, 2);
- $avCost = 0;
- $newItemStock = 0;
- $newItemCost = 0;
- $changeCost = 0;
- $unitCost = 0;
- //涉及平均成本计算的,多处要修改,搜索关键词 calc_av_cost
- if (!empty($params['cost']) && $params['cost'] > 0) {
- //变成库存和变成成本
- $unitCost = $params['cost'];
- $changeCost = bcmul($params['cost'], $itemNum, 2);
- //原库存和原成本,也叫剩余库存和剩余成本
- $oldItemStock = $productData->stock;
- $oldAvCost = $productData->avCost ?? 0;
- $oldItemCost = bcmul($oldItemStock, $oldAvCost, 2);
- //新库存和新成本
- $newItemCost = bcsub($oldItemCost, $changeCost, 2);
- $newItemStock = bcsub($oldItemStock, $itemNum, 2);
- if ($newItemStock > 0) {
- $avCost = bcdiv($newItemCost, $newItemStock, 2);
- } else {
- $newItemStock = 0;
- $newItemCost = 0;
- }
- //如果减库存之后,还有剩余库存,则变更新的平均成本。如果没有库存不再变更平均成本。如没有库存了还变更,会造成全部调拨出库时,保存的成本是0,重要!!!!!!!!!!
- //确实是,如果没有库存了,平均成本也不能再变化了。如果再变化,平均成本也是变成0。变成0后,如果再盘点几个库存出来,会变成没有成本的库存。 ssh 20251130
- if ($newStock > 0) {
- $productData->avCost = $avCost;
- }
- $productData->totalCost = $newItemCost;
- $productData->totalStock = $newItemStock;
- }
- if ($checkStock && $newStock < 0) {
- //需要判断库存是否充足
- $currentName = $productData->name ?? '';
- $currentRemainStock = floatval($oldStock);
- util::fail("{$currentName} 只剩{$currentRemainStock}{$productData->bigUnit}");
- }
- $productData->stock = $newStock;
- if ($addSold) {
- //减库存,加销量 2021.6.21 lqh
- $actualSold = $productData->actualSold;
- $productData->actualSold = bcadd($actualSold, $itemNum, 2);
- }
- //如果花材是自动补充库存类型的花材,则库存低于900时,自动补充到98520,多处要同步修改,关键词 auto_add_stock
- if ($productData->virtualStock == 1 && $newStock < 9900) {
- $productData->stock = 98520;
- }
- //库存=0 下架商品,特价去掉,限购去掉 lqh 2021.7.9 ssh 20251106 花材满减去掉 20260318
- if ($newStock <= 0) {
- $productData->status = 2;
- //限购数量重置为 0,但会把限购不为 0 的数据记录到缓存
- self::createRecoverLimitBuyCache($productId, $productData->limitBuy);
- }
- $productData->save();
- return ['oldStock' => $oldStock, 'newStock' => $newStock, 'itemNum' => $itemNum,
- 'avCost' => $avCost, 'totalCost' => $newItemCost, 'totalStock' => $newItemStock, 'changeCost' => $changeCost, 'unitCost' => $unitCost];
- };
- return self::runStockMutation($productId, $callback);
- }
- //根据数量减库存
- public static function decreaseStockByItemNum($productId, $itemNum, $checkStock = false)
- {
- $callback = function ($productData) use ($itemNum, $checkStock) {
- $oldStock = $productData->stock;
- $newStock = bcsub($oldStock, $itemNum, 2);
- if ($checkStock && $newStock < 0) {
- //需要判断库存是否充足
- util::fail("库存不足");
- }
- $productData->stock = $newStock;
- //减库存,加销量 2021.6.21 lqh
- $actualSold = $productData->actualSold;
- $productData->actualSold = bcadd($actualSold, $itemNum, 2);
- $productData->save();
- return ['oldStock' => $oldStock, 'newStock' => $newStock, 'itemNum' => $itemNum];
- };
- return self::runStockMutation($productId, $callback);
- }
- //减少在路上的库存
- public static function decreaseOnStockByItemNum($productId, $itemNum, $checkStock = false)
- {
- $callback = function ($productInfo) use ($itemNum, $checkStock) {
- $oldOnStock = $productInfo->onStock;
- $newOnStock = bcsub($oldOnStock, $itemNum);
- if ($checkStock && $newOnStock < 0) {
- //需要判断库存是否充足
- util::fail("库存不足");
- }
- $productInfo->onStock = $newOnStock;
- $productInfo->save();
- return ['oldOnStock' => $oldOnStock, 'newOnStock' => $newOnStock, 'itemNum' => $itemNum];
- };
- return self::runStockMutation($productId, $callback);
- }
- //计算价格
- public static function computedPrice($productId, $bigNum, $smallNum)
- {
- //获取itemId的价格
- $productData = self::getById($productId);
- if (!$productData) {
- util::fail("花材不存在");
- }
- $price = $productData['price'];
- $itemId = $productData['itemId'];
- $unitNum = xhItemService::getItemUnitNum($itemId);
- //换算出一支多少钱
- $piecePrice = 0;
- if ($unitNum > 0) {
- //有支
- $unitPrice = bcdiv($price, $unitNum, 2);
- $piecePrice = bcmul($unitPrice, $smallNum, 2);
- }
- $bundlePrice = bcmul($price, $bigNum, 2);
- $total = bcadd($bundlePrice, $piecePrice, 2);
- return $total;
- }
- //根据门店ID, 平台花材ID, 获取门店的花材ID
- public static function getGhsProductId($shopId, $itemId)
- {
- $data = self::getGhsProductDataByItemId($shopId, $itemId);
- if ($data) {
- return $data['id'];
- }
- return 0;
- }
- public static function getGhsProductDataByItemId($shopId, $itemId)
- {
- $where = ['shopId' => $shopId, 'itemId' => $itemId];
- $data = self::getByCondition($where);
- return $data;
- }
- //根据多个itemIds shopId 获取对应的 productId lqh 2021.1.24
- public static function getGhsProductDataByItemIds($mainId, $itemIds)
- {
- $where = ['itemId' => ['in', $itemIds], 'mainId' => $mainId];
- $data = self::getAllByCondition($where, null, "*");
- return $data;
- }
- //补全itemId (针对入库时 当前门店下无对应的花材 itemId) lqh 2021.1.24
- public static function complementProduct($sjId, $mainId, $shopId, $itemInfo)
- {
- $itemIds = array_column($itemInfo, "itemId");
- $oldProductIds = array_column($itemInfo, "productId");
- $productData = self::getGhsProductDataByItemIds($mainId, $itemIds);
- $defaultClass = ItemClassClass::getByCondition(['mainId' => $mainId, 'isDefault' => 1], true);
- $defaultClassId = $defaultClass->id ?? 0;
- if (empty($defaultClassId)) {
- util::fail('没有找到默认分类');
- }
- $shop = ShopClass::getById($shopId, true);
- if (empty($shop)) {
- util::fail('没有找到门店24');
- }
- if (count($productData) !== count($itemIds)) {
- $productDataItemIds = array_column($productData, 'itemId');
- //取差集
- $diffItemIds = array_diff($itemIds, $productDataItemIds);
- if ($diffItemIds) {
- $oldProductInfo = self::getAllByCondition(['id' => ['in', $oldProductIds]], null, '*', 'itemId');
- //新增到product表,price = itemPrice (出库时的售价), stock=0
- foreach ($diffItemIds as $v) {
- $addData = [];
- $addData['sjId'] = $sjId;
- $addData['shopId'] = $shopId;
- $addData['mainId'] = $mainId;
- $addData['itemId'] = $v;
- $addData['name'] = $oldProductInfo[$v]['name'] ?? '';
- $addData['price'] = $oldProductInfo[$v]['price'] ?? 0;
- $addData['classId'] = $defaultClassId;
- $addData['smallRatio'] = $oldProductInfo[$v]['smallRatio'] ?? 2;
- $addData['skPrice'] = $oldProductInfo[$v]['skPrice'] ?? 0;
- $addData['hjPrice'] = $oldProductInfo[$v]['hjPrice'] ?? 0;
- $addData['cost'] = $oldProductInfo[$v]['cost'] ?? 0;
- $addData['addPrice'] = $oldProductInfo[$v]['addPrice'] ?? 0;
- $addData['skAddPrice'] = $oldProductInfo[$v]['skAddPrice'] ?? 0;
- $addData['hjAddPrice'] = $oldProductInfo[$v]['hjAddPrice'] ?? 0;
- $addData['stockWarning'] = $oldProductInfo[$v]['stockWarning'] ?? 5;
- $addData['weight'] = $oldProductInfo[$v]['weight'] ?? 0;
- $addData['alias'] = $oldProductInfo[$v]['alias'] ?? '';
- $addData['itemRemark'] = $oldProductInfo[$v]['itemRemark'] ?? '';
- $addData['py'] = $oldProductInfo[$v]['py'] ?? '';
- $addData['ratio'] = $oldProductInfo[$v]['ratio'] ?? 20;
- $addData['bigUnit'] = $oldProductInfo[$v]['bigUnit'] ?? '';
- $addData['smallUnit'] = $oldProductInfo[$v]['smallUnit'] ?? '';
- $addData['bigUnitId'] = $oldProductInfo[$v]['bigUnitId'] ?? 0;
- $addData['smallUnitId'] = $oldProductInfo[$v]['smallUnitId'] ?? 0;
- $addData['status'] = 1;
- $addData['delStatus'] = 0;
- $addData['inTurn'] = 100;
- self::addProduct($addData, $shop);
- }
- }
- }
- }
- public static function check($info, $mainId)
- {
- if (empty($info)) {
- util::fail('没有花材信息');
- }
- if (isset($info->mainId) == false || $info->mainId != $mainId) {
- util::fail('无效花材');
- }
- return true;
- }
- //有效花材判断,包括id有效、同个门店等 ssh 2021.1.19
- public static function valid($list, $mainId)
- {
- $ids = array_unique(array_filter(array_column($list, 'productId')));
- $productList = self::getByIds($ids, null, 'id');
- if (!empty($productList)) {
- foreach ($productList as $product) {
- if (isset($product['mainId']) == false || $product['mainId'] != $mainId) {
- $name = $product['name'] ?? '';
- $pMainId = $product['mainId'] ?? 0;
- //noticeUtil::push("只能选择同一家的商品哦!{$name} {$pMainId} {$mainId}", '15280215347');
- util::fail($name . ' 不是一家的商品,请清空重选');
- }
- }
- if (count($productList) != count($ids)) {
- util::fail('存在无效商品');
- }
- } else {
- util::fail('商品不存在');
- }
- }
- //通过ids 批量获取花材商品的信息
- public static function getProductByIds($ids)
- {
- return self::getByIds($ids);
- }
- //修改花材商品的库存: 统一方法
- public static function updateStockById($id, $stock, $adminId = 0)
- {
- $callback = function ($productData) use ($stock, $adminId) {
- $productData->stock = $stock;
- //如果有库存需要保持上架状态
- if ($stock > 0) {
- $productData->status = 1;
- }
- if ($adminId) {
- $productData->adminId = $adminId;
- }
- return $productData->save();
- };
- return self::runStockMutation($id, $callback);
- }
- //订单退回库存
- public static function backStockByOrderItemInfo($orderItemInfo)
- {
- foreach ($orderItemInfo as $v) {
- self::addStockByItemNum($v['productId'], $v['itemNum']);
- }
- }
- //获取当前门店下商品信息 lqh 2021.1.28
- public static function getProductData($id, $mainId, $obj = false)
- {
- return self::getByCondition(['id' => $id, 'mainId' => $mainId], $obj);
- }
- //单个修改价格 lqh 2021.1.28
- public static function changeSinglePrice($shop, $ptItemId, $price, $skPrice = null, $hjPrice = null, $params = [])
- {
- $mainId = $shop->mainId ?? 0;
- $productInfo = self::getByCondition(['itemId' => $ptItemId, 'mainId' => $mainId, 'delStatus' => 0], true);
- if (empty($productInfo)) {
- return false;
- }
- if (empty($price)) {
- util::fail('没有批发价');
- }
- $discountPrice = $productInfo->discountPrice ?? 0;
- $discountPrice = floatval($discountPrice);
- $name = $productInfo->name ?? '';
- if ($discountPrice > 0) {
- if ($discountPrice >= $price) {
- //util::fail($name . " 价格应该大于特价");
- }
- }
- $productInfo->price = $price;
- if (empty($skPrice)) {
- util::fail('没有零售价');
- }
- if (empty($hjPrice)) {
- util::fail('没有会员价');
- }
- $productInfo->skPrice = $skPrice;
- $productInfo->hjPrice = $hjPrice;
- $productInfo->save();
- $sjId = $shop->sjId ?? 0;
- $itemId = $productInfo->id ?? 0;
- $ptItemId = $productInfo->itemId ?? 0;
- $name = $productInfo->name ?? '';
- $cover = $productInfo->cover ?? '';
- $staffId = $params['staffId'] ?? 0;
- $staffName = $params['staffName'] ?? '';
- $changeType = $params['changeType'] ?? 'normal';
- $targetId = $params['targetId'] ?? 0;
- $event = $params['event'] ?? '修改';
- $type = 0;
- if ($changeType == 'cg') {
- $event = '采购后修改';
- $type = 1;
- }
- $changeData = [
- 'ptStyle' => 2,
- 'sjId' => $sjId,
- 'mainId' => $mainId,
- 'itemId' => $itemId,
- 'ptItemId' => $ptItemId,
- 'price' => $price,
- 'skPrice' => $skPrice,
- 'hjPrice' => $hjPrice,
- 'staffId' => $staffId,
- 'staffName' => $staffName,
- 'name' => $name,
- 'cover' => $cover,
- 'event' => $event,
- 'type' => $type,
- 'targetId' => $targetId,
- ];
- PriceChangeClass::addData($changeData);
- return true;
- }
- //下单时计算商品的价格 lqh 2021.1.28
- public static function formatProductInfo($itemInfo, $level = 0, $live = 1, $moreParams = [])
- {
- $data = [];
- if (empty($itemInfo)) {
- util::fail('请选择花材,编号 179612');
- }
- $itemInfo = self::mergeItemInfo($itemInfo);
- $productIds = array_column($itemInfo, 'productId');
- $ghsProductData = self::getProductByIds($productIds);
- $ghsProductData = array_column($ghsProductData, NULL, 'id');
- // if ($live == 1) {
- // $hdProductData = [];
- // } else {
- // $hdIds = array_column($itemInfo, 'hdProductId');
- // $hdProductData = self::getByIds($hdIds, null, 'id');
- // }
- $totalPrice = 0;
- $totalBigNum = 0;
- $totalSmallNum = 0;
- $book = $moreParams['book'] ?? 0;
- $customShopAdminId = $moreParams['customShopAdminId'] ?? 0;
- $custom = $moreParams['custom'] ?? [];
- $skipLimitBuy = $moreParams['skipLimitBuy'] ?? false;
- //不同等级对应 price addPrice
- $priceMap = CustomClass::$levelPriceKeyMap;
- //这个参数应该是要作废的,但下面加的参数是有用的,多处要同步修改,关键词 abandon_add_price_map ,ssh 20260116
- $addPriceMap = CustomClass::$levelAddPriceKeyMap;
- //但这边加的参数是有用的,给指定客户涨价的
- $addPriceMap['risePercent'] = $custom['risePercent'] ?? 0;
- $totalItemNum = 0;
- //满减累计
- $totalReachDiscount = 0;
- $totalCost = 0;
- foreach ($itemInfo as $v) {
- $ghsProductId = $v['productId'];
- $currentGhsProduct = $ghsProductData[$ghsProductId] ?? [];
- if (empty($currentGhsProduct)) {
- noticeUtil::push("ghsProductId={$ghsProductId} 在 ghsProductData 中为空");
- continue;
- }
- $itemId = $currentGhsProduct['itemId'];
- $ratio = $currentGhsProduct['ratio'];
- $cost = $currentGhsProduct['avCost'];
- $classId = $currentGhsProduct['classId'];
- $bigNum = $v['bigNum'] ?? 0;
- $smallNum = $v['smallNum'] ?? 0;
- //大小数量合并多少扎
- $itemNum = self::mergeItemNum($bigNum, $smallNum, $ratio);
- $totalItemNum = bcadd($totalItemNum, $itemNum, 2);
- if ($live == 1) {
- //供货商开单可以传单价过来
- $changePrice = isset($v['price']) && $v['price'] > 0 ? $v['price'] : 0;
- //如果零售店自己下预订单,预付0.1元,有二个地方要同步修改,搜索关键词 pre0.1
- if ($book == 1 && $customShopAdminId > 0) {
- $itemPrice = 0.1;
- } else {
- $priceBuyNum = $skipLimitBuy ? 0 : $itemNum;
- $totalBuyNum = 0;
- if ($skipLimitBuy == false) {
- $limitKey = self::LIMIT_BUY_KEY . $ghsProductId;
- $hasBuyNum = Yii::$app->redis->executeCommand('HGET', [$limitKey, $custom['id']]);
- $totalBuyNum = $itemNum + ($hasBuyNum == null ? 0 : $hasBuyNum); // 已购买总数量
- }
- //今日特价、会员价
- $itemPrice = self::getFinalPrice($currentGhsProduct, $level, $priceMap, $addPriceMap, $changePrice, $priceBuyNum, $totalBuyNum);
- }
- $thisPrice = $itemPrice;
- $reachNum = $currentGhsProduct['reachNum'] ?? 0;
- if ($reachNum > 0) {
- if ($itemNum >= $reachNum) {
- $reachNumDiscount = $currentGhsProduct['reachNumDiscount'] ?? 0;
- $currentReachDiscount = bcmul($reachNumDiscount, $itemNum, 2);
- $totalReachDiscount = bcadd($totalReachDiscount, $currentReachDiscount, 2);
- }
- }
- } else {
- $itemPrice = $v['unitPrice'] ?? 0;
- $thisPrice = $itemPrice;
- }
- if ($smallNum > 0) {
- $price = bcmul($smallNum, $itemPrice, 2);
- } else {
- $price = bcmul($bigNum, $itemPrice, 2);
- }
- $tmp = [];
- $tmp['productId'] = $ghsProductId;
- $tmp['price'] = $price;
- $tmp['name'] = $currentGhsProduct['name'] ?? '';
- $tmp['smallUnit'] = $currentGhsProduct['smallUnit'] ?? '支';
- $tmp['bigUnit'] = $currentGhsProduct['bigUnit'] ?? '扎';
- $tmp['cover'] = $currentGhsProduct['cover'] ?? '';
- $tmp['itemId'] = $itemId;
- $tmp['rank'] = $currentGhsProduct['rank'] ?? '';
- $tmp['ratio'] = $currentGhsProduct['ratio'] ?? 1;
- $tmp['ratioType'] = $currentGhsProduct['ratioType'] ?? 0;
- $tmp['variety'] = $currentGhsProduct['variety'] ?? 0;
- $tmp['unitPrice'] = $thisPrice;
- $tmp['unitWeight'] = $currentGhsProduct['weight'] ?? 0;;
- $tmp['num'] = $itemNum;
- $tmp['bigNum'] = $v['bigNum'];
- $tmp['smallNum'] = $v['smallNum'];
- $tmp['preNum'] = $itemNum;
- $tmp['preBigNum'] = $v['bigNum'];
- $tmp['preSmallNum'] = $v['smallNum'];
- $tmp['remark'] = $v['remark'] ?? '';
- $tmp['userPrice'] = $price;
- $tmp['weight'] = $currentGhsProduct['weight'] ?? 0;
- $tmp['sjId'] = $currentGhsProduct['sjId'] ?? 0;
- $tmp['shopId'] = $currentGhsProduct['shopId'] ?? 0;
- $tmp['mainId'] = $currentGhsProduct['mainId'] ?? 0;
- $tmp['limitBuy'] = $currentGhsProduct['limitBuy'];
- $tmp['smallUnitPrice'] = $itemPrice;
- $tmp['classId'] = $classId;
- $tmp['kind'] = $currentGhsProduct['kind'] ?? 0;
- $tmp['belongCost'] = $currentGhsProduct['belongCost'] ?? 0;
- $tmp['hjDiscountPrice'] = $currentGhsProduct['hjDiscountPrice'];
- $tmp['discountPrice'] = $currentGhsProduct['discountPrice'];
- $tmp['skDiscountPrice'] = $currentGhsProduct['skDiscountPrice'];
- $totalPrice = bcadd($totalPrice, $price, 2);
- $totalBigNum += $bigNum;
- $totalSmallNum += $smallNum;
- if ($bigNum > 0) {
- $xhUnitType = dict::getDict('unitType', 'big');
- $xhNum = $bigNum;
- $xhUnitName = $tmp['bigUnit'] ?? '';
- } else {
- $xhUnitType = dict::getDict('unitType', 'small');
- $xhNum = $smallNum;
- $xhUnitName = $tmp['smallUnit'] ?? '';
- $smallCost = bcdiv($cost, $ratio, 2);
- $cost = $smallCost;
- }
- $xhPrice = bcmul($xhNum, $itemPrice, 2);
- $tmp['cost'] = $cost;
- $tmp['xhNum'] = $xhNum;
- $tmp['xhUnitName'] = $xhUnitName;
- $tmp['xhUnitType'] = $xhUnitType;
- $tmp['xhUnitPrice'] = $itemPrice;
- $tmp['xhPrice'] = $xhPrice;
- $tmp['xhPreNum'] = $xhNum;
- $tmp['xhPreUnitName'] = $xhUnitName;
- $tmp['xhPreUnitType'] = $xhUnitType;
- $tmp['xhPreUnitPrice'] = $itemPrice;
- $tmp['xhPrePrice'] = $xhPrice;
- $data[] = $tmp;
- $currentCost = bcmul($xhNum, $cost, 2);
- $totalCost = bcadd($totalCost, $currentCost, 2); // TODO 根据限购与特价进行价格计算的关键参数
- }
- return ['product' => $data, 'totalReachDiscount' => $totalReachDiscount, 'smallNum' => $totalSmallNum,
- 'bigNum' => $totalBigNum, 'price' => $totalPrice, 'totalItemNum' => $totalItemNum, 'totalCost' => $totalCost];
- }
- // //修改某个花材的成本价(采购之后要用到) lqh 2021.04.06
- public static function changeCost($productId, $cost)
- {
- return self::updateById($productId, ['cost' => $cost]);
- }
- //更新某个花材的加价 2021.04.06
- public static function changeAddPrice($productId, $addPrice)
- {
- return self::updateById($productId, ['addPrice' => $addPrice]);
- }
- //根据productId 计算花材的重量
- public static function getWeight($productId, $bigNum, $smallNum)
- {
- $productInfo = self::getById($productId);
- if (empty($productInfo)) {
- return 0;
- }
- $ratio = $productInfo['ratio'];
- $weight = $productInfo['weight'];
- $mergeNum = self::mergeItemNum($bigNum, $smallNum, $ratio);
- return bcmul($mergeNum, $weight, 2);
- }
- /**
- * 修改product
- * @param $data
- * @param $shop
- * @param $type 所属平台:ghs 或 hd
- * @throws \Exception
- */
- public static function updateProduct($data, $shop, $type)
- {
- $id = $data['id'] ?? 0;
- $adminId = $data['adminId'] ?? 0;
- $sjId = $shop->sjId ?? 0;
- $shopId = $shop->id ?? 0;
- $mainId = $shop->mainId ?? 0;
- $product = self::getLockById($id);
- if (empty($product)) {
- util::fail("该花材不存在");
- }
- if (isset($data['limitBuy']) && intval($data['limitBuy']) > 0) {
- if ($product->limitBuy == 0) {
- $type == 'ghs' ? self::clearLimitBuyCache($id) : \bizHd\product\classes\ProductClass::clearLimitBuyCache($id);
- }
- } else {
- $type == 'ghs' ? self::clearLimitBuyCache($id) : \bizHd\product\classes\ProductClass::clearLimitBuyCache($id);
- }
- //扫码收款、直接收款,不包括特价商品,不可修改,多处要同步修改 system_item
- if (getenv('YII_ENV') == 'production') {
- $systemItem = [78076, 80960];
- $adminList = [4, 1960];
- } else {
- $systemItem = [11157, 11156];
- $adminList = [919, 932];
- }
- if (in_array($product->itemId, $systemItem)) {
- if (!in_array($adminId, $adminList)) {
- util::fail('系统花材,不可修改');
- }
- }
- $name = $product->name ?? '';
- $cover = $product->cover ?? '';
- $upData = [];
- //库存可以修改
- if (isset($data['stock']) && is_numeric($data['stock'])) {
- $preStock = $product->stock ?? 0;
- if ($data['stock'] != $preStock) {
- if ($data['stock'] < 0) {
- util::fail("库存不能小于0");
- }
- if ($data['stock'] > 9999) {
- util::fail('库存数不能超过4个9');
- }
- //增加盘点记录 2021.7.27
- $ratio = $product->ratio ?? 0;
- $formNum = self::formatStock($data['stock'], $ratio);
- $ghsItemInfo = [['productId' => $product->id, 'bigNum' => $formNum['bigNum'], 'smallNum' => $formNum['smallNum'],]];
- $pdData = [];
- $pdData['itemInfo'] = $ghsItemInfo;
- $pdData['sjId'] = $sjId;
- $pdData['shopId'] = $shopId;
- $pdData['adminId'] = $data['adminId'];
- $pdData['mainId'] = $mainId;
- $pdData['staffName'] = $data['staffName'] ?? '';
- CheckOrderClass::opOrder($pdData, false, false);
- }
- unset($data['stock']);
- }
- unset($data['adminId']);
- if (isset($data['name'])) {
- if (empty($data['name'])) {
- util::fail("请输入花材名称");
- }
- $upData['name'] = $data['name'];
- }
- if (!empty($data['py'])) {
- $upData['py'] = $data['py'];
- }
- if (!empty($data['cover'])) {
- $upData['cover'] = $data['cover'];
- }
- if (!empty($data['images'])) {
- $upData['images'] = $data['images'];
- }
- if (isset($data['discountPrice']) && is_numeric($data['discountPrice'])) {
- $discountPrice = $data['discountPrice'] ?? 0;
- $currentPrice = $data['price'] ?? 0;
- if ($discountPrice >= $currentPrice) {
- util::fail('特价要小于售价');
- }
- $upData['discountPrice'] = $discountPrice;
- if ($discountPrice > 0) {
- if ($product->presell == 1) {
- util::fail('预售花材不能做特价');
- }
- }
- $hjDiscountPrice = isset($data['hjDiscountPrice']) && is_numeric($data['hjDiscountPrice']) ? $data['hjDiscountPrice'] : 0;
- $skDiscountPrice = isset($data['skDiscountPrice']) && is_numeric($data['skDiscountPrice']) ? $data['skDiscountPrice'] : 0;
- if ($hjDiscountPrice > $discountPrice) {
- util::fail('批发特价要大于会员特价');
- }
- if ($discountPrice > $skDiscountPrice) {
- util::fail('零售特价要大于批发特价');
- }
- $upData['hjDiscountPrice'] = $hjDiscountPrice;
- $upData['skDiscountPrice'] = $skDiscountPrice;
- }
- $cost = $data['cost'] ?? 0;
- $price = $data['price'] ?? 0;
- $price = floatval($price);
- $skPrice = $data['skPrice'] ?? 0;
- $skPrice = floatval($skPrice);
- $hjPrice = $data['hjPrice'] ?? 0;
- $hjPrice = floatval($hjPrice);
- if (!is_numeric($price) || $price <= 0) {
- util::fail('请填写价格');
- }
- if ($hjPrice > $price) {
- util::fail('批发价要大于会员价');
- }
- if ($price > $skPrice) {
- util::fail('零售价要大于批发价');
- }
- if (isset($data['addPrice']) && is_numeric($data['addPrice'])) {
- $upData['addPrice'] = $data['addPrice'];
- }
- if (isset($data['skMore']) && is_numeric($data['skMore'])) {
- $upData['skMore'] = $data['skMore'];
- }
- if (isset($data['hjAddPrice']) && is_numeric($data['hjAddPrice'])) {
- $upData['hjAddPrice'] = $data['hjAddPrice'];
- }
- if (floatval($price) != floatval($product->price) || floatval($skPrice) != floatval($product->skPrice) || floatval($hjPrice) != floatval($product->hjPrice)) {
- if ($shop->default == 0 && $shop->join == 0) {
- //除了小蔡鲜花的蔡总、郑总、苏南3007,其他人直营分店不能改价格,多处要同步修改,关键词 direct_price_change
- if (!in_array($adminId, [35725, 23659, 29264])) {
- util::fail('直营店不能改价哦');
- }
- }
- }
- if (isset($data['limitBuy']) && is_numeric($data['limitBuy'])) {
- $upData['limitBuy'] = $data['limitBuy'];
- //取消限购
- if ($data['limitBuy'] == 0) {
- if ($type == 'ghs') {
- self::clearLimitBuyCache($id);
- } else {
- \bizHd\product\classes\ProductClass::clearLimitBuyCache($id);
- }
- }
- }
- if (isset($data['stockWarning'])) {
- $upData['stockWarning'] = $data['stockWarning'];
- }
- //重量不可修改
- unset($data['weight']);
- if (isset($data['inTurn'])) {
- $upData['inTurn'] = $data['inTurn'];
- }
- if (array_key_exists('itemRemark', $data)) {
- $itemRemark = trim($data['itemRemark'] ?? '');
- if (mb_strlen($itemRemark) > 200) {
- util::fail('备注不能超过200字');
- }
- $upData['itemRemark'] = $itemRemark;
- }
- if (isset($data['delStatus'])) {
- if (!in_array($data['delStatus'], [0, 1])) {
- util::fail("删除错误");
- }
- $upData['delStatus'] = $data['delStatus'];
- if ($data['delStatus'] == 1) {
- $upData['discountPrice'] = 0;
- }
- }
- if (isset($data['status']) && is_numeric($data['status'])) {
- $upData['status'] = $data['status'];
- if ($data['status'] == 2) {
- $upData['discountPrice'] = 0;
- }
- }
- if (isset($data['frontHide']) && is_numeric($data['frontHide'])) {
- $upData['frontHide'] = $data['frontHide'];
- }
- if (isset($data['frontUse']) && is_numeric($data['frontUse'])) {
- $upData['frontUse'] = $data['frontUse'];
- }
- if (isset($data['variety']) && is_numeric($data['variety'])) {
- $upData['variety'] = $data['variety'];
- }
- //分类ID
- if (isset($data["classId"])) {
- $classId = $data['classId'];
- $upData['classId'] = $classId;
- if (isset($product->classId) && $product->classId != $classId) {
- //如果有修改分类,则在多个订单表中同步修改,如需修改,多个地方要同步修改,请搜索关键词item_class_modify_sync
- $itemClassKey = 'item_class_modify_sync';
- Yii::$app->redis->executeCommand('LPUSH', [$itemClassKey, $id]);
- }
- }
- if (isset($data["scanNum"]) && is_numeric($data["scanNum"])) {
- $upData['scanNum'] = $data['scanNum'];
- }
- if (isset($data["reachNum"]) && $data["reachNum"] > 0) {
- $upData['reachNum'] = $data['reachNum'];
- if (!isset($data['reachNumDiscount']) || $data['reachNumDiscount'] <= 0) {
- util::fail('请填写满减的优惠金额');
- }
- $reachNumDiscount = $data['reachNumDiscount'];
- $upData['reachNumDiscount'] = $reachNumDiscount;
- if ($reachNumDiscount >= $hjPrice) {
- util::fail('优惠金额不能大于售价');
- }
- if (isset($upData['hjDiscountPrice']) && $upData['hjDiscountPrice'] > 0) {
- if ($reachNumDiscount >= $upData['hjDiscountPrice']) {
- util::fail('优惠金额不能大于特价');
- }
- }
- if ($product->variety == 1) {
- util::fail('多颜色暂不支持满减');
- }
- } else {
- $upData['reachNum'] = 0;
- $upData['reachNumDiscount'] = 0;
- }
- if (isset($data["smallRatio"]) && is_numeric($data["smallRatio"])) {
- $upData['smallRatio'] = $data['smallRatio'];
- }
- if (isset($data['ratioType'])) {
- $upData['ratioType'] = $data['ratioType'];
- }
- if (isset($data["smallShow"]) && is_numeric($data["smallShow"])) {
- $upData['smallShow'] = $data['smallShow'];
- }
- if (isset($data["cost"]) && is_numeric($data["cost"])) {
- $upData['cost'] = $data['cost'];
- }
- if (isset($data["virtualStock"]) && is_numeric($data["virtualStock"])) {
- $upData['virtualStock'] = $data['virtualStock'];
- }
- $paramsBack = $upData;
- $ptItemId = $product->itemId ?? 0;
- $staffId = $data['staffId'] ?? 0;
- $staffName = $data['staffName'] ?? '';
- $changeParams = ['staffId' => $staffId, 'staffName' => $staffName];
- if ($price != floatval($product->price) || $skPrice != floatval($product->skPrice) || $hjPrice != floatval($product->hjPrice)) {
- self::changeSinglePrice($shop, $ptItemId, $price, $skPrice, $hjPrice, $changeParams);
- unset($upData['price']);
- unset($upData['skPrice']);
- unset($upData['hjPrice']);
- if (!empty($mainId)) {
- //提醒零售收银台界面要刷新,多处要修改,关键词 modify_price_remind_cashier
- $staffList = ShopAdminClass::getAllByCondition(['mainId' => $mainId], null, '*', null, true);
- if (!empty($staffList)) {
- foreach ($staffList as $staff) {
- $staffId = $staff->id ?? 0;
- Yii::$app->redis->executeCommand('SET', ['cashier_' . $mainId . '_' . $staffId . '_may_refresh', 'yes']);
- Yii::$app->redis->executeCommand('SET', ['ghs_cashier_' . $mainId . '_' . $staffId . '_may_refresh', 'yes']);
- }
- }
- }
- }
- if ($cost != $product->cost) {
- $changeData = [
- 'ptStyle' => 2,
- 'sjId' => $sjId,
- 'mainId' => $mainId,
- 'itemId' => $id,
- 'ptItemId' => $ptItemId,
- 'cost' => $cost,
- 'staffId' => $staffId,
- 'staffName' => $staffName,
- 'name' => $name ?? '',
- 'cover' => $cover,
- 'type' => 2,
- 'targetId' => $id ?? 0,
- 'event' => '修改',
- ];
- CostChangeClass::addData($changeData);
- }
- self::updateById($id, $upData);
- //创建限购缓存
- $limitBuy = $data['limitBuy'] ?? 0;
- if ($limitBuy > 0) {
- $limitBuyClearType = $data['limitBuyClearType'];
- $limitBuyClearLoopConfig = self::getLimitBuyClearLoopConfig($data);
- if ($limitBuyClearType == 1 && !empty($limitBuyClearLoopConfig)) {
- if ($type == 'ghs') {
- self::createRecurringLimitBuyCache($id, $limitBuyClearLoopConfig['intervalDays'], $limitBuyClearLoopConfig['clearHour']);
- } else {
- \bizHd\product\classes\ProductClass::createRecurringLimitBuyCache($id, $limitBuyClearLoopConfig['intervalDays'], $limitBuyClearLoopConfig['clearHour']);
- }
- } elseif ($limitBuyClearType == 2 && isset($data['limitBuyClearTime']) && $data['limitBuyClearTime'] != '') {
- $limitBuyClearTime = strtotime($data['limitBuyClearTime']);
- if ($limitBuyClearTime > time()) {
- if ($type == 'ghs') {
- self::createLimitBuyCache($id, $limitBuyClearTime - time());
- } else {
- \bizHd\product\classes\ProductClass::createLimitBuyCache($id, $limitBuyClearTime - time());
- }
- } else {
- util::fail('清空时间必须大于当前时间');
- }
- } else { // 没有设置清空时间,则删除缓存
- if ($type == 'ghs') {
- self::createLimitBuyCache($id, 0);
- } else {
- \bizHd\product\classes\ProductClass::createLimitBuyCache($id, 0);
- }
- }
- }
- //不影响其它直营店花材的上下架
- unset($upData['status']);
- if (isset($shop->default) && $shop->default == 1 && isset($shop->dataSync) && $shop->dataSync == 1) {
- //总店修改同步到所有门店
- $chainShopList = ShopClass::getAllByCondition(['sjId' => $sjId], null, '*', null, true);
- foreach ($chainShopList as $chainShop) {
- $chainShopId = $chainShop->id ?? 0;
- if ($chainShopId == $shop->id) {
- //前面已经添加过了
- continue;
- }
- $chainMainId = $chainShop->mainId ?? 0;
- $params = $paramsBack;
- //所有门店上下架、启用停用等不同步
- unset($params['status']);
- unset($params['delStatus']);
- unset($params['limitBuy']);
- $staff = ShopAdminClass::getByCondition(['mainId' => $chainMainId, 'adminId' => $adminId], true);
- $staffId = $staff->id ?? 0;
- $staffName = $staff->name ?? '';
- $changeParams2 = ['staffId' => $staffId, 'staffName' => $staffName];
- $chainProduct = self::getByCondition(['mainId' => $chainMainId, 'itemId' => $ptItemId], true);
- if (empty($chainProduct)) {
- continue;
- }
- //如果有同步分类则移动,没有则不移动
- if (isset($params['classId'])) {
- $masterClassId = $params['classId'];
- unset($params['classId']);
- $masterClass = ItemClassClass::getById($masterClassId, true);
- $masterClassName = $masterClass->name ?? '';
- $classList = ItemClassClass::getAllByCondition(['mainId' => $chainMainId], null, '*', null, true);
- if (!empty($classList)) {
- foreach ($classList as $currentClass) {
- if ($currentClass->name == $masterClassName) {
- $params['classId'] = $currentClass->id ?? 0;
- if (isset($chainProduct->classId) && $chainProduct->classId != $params['classId']) {
- //如果有修改分类,则在多个订单表中同步修改,如需修改,多个地方要同步修改,请搜索关键词item_class_modify_sync
- $itemClassKey = 'item_class_modify_sync';
- Yii::$app->redis->executeCommand('LPUSH', [$itemClassKey, $chainProduct->id]);
- }
- }
- }
- }
- }
- //加盟店仅同步名称等非重要参数
- if ($chainShop->join == 1) {
- unset($params['skPrice']);
- unset($params['price']);
- unset($params['hjPrice']);
- unset($params['addPrice']);
- unset($params['skMore']);
- unset($params['hjAddPrice']);
- unset($params['cost']);
- //特价的金额也不能同步,淘花里
- unset($params['hjDiscountPrice']);
- unset($params['discountPrice']);
- unset($params['skDiscountPrice']);
- //满减也不能同步,惠雅鲜花批发
- unset($params['reachNum']);
- unset($params['reachNumDiscount']);
- self::updateById($chainProduct->id, $params);
- continue;
- }
- if ($price != $chainProduct->price) {
- //批发价有变化
- self::changeSinglePrice($chainShop, $ptItemId, $price, $skPrice, $hjPrice, $changeParams2);
- unset($params['price']);
- }
- if ($cost != $chainProduct->cost) {
- $changeData = [
- 'ptStyle' => 2,
- 'sjId' => $chainShop->sjId ?? 0,
- 'mainId' => $chainShop->mainId ?? 0,
- 'itemId' => $chainProduct->id,
- 'ptItemId' => $ptItemId,
- 'cost' => $cost,
- 'staffId' => $staffId,
- 'staffName' => $staffName,
- 'name' => $chainProduct->name ?? '',
- 'cover' => $chainProduct->cover,
- 'type' => 2,
- 'targetId' => $chainProduct->id ?? 0,
- 'event' => '修改',
- ];
- CostChangeClass::addData($changeData);
- }
- //直营店同步价格等重要因素
- self::updateById($chainProduct->id, $params);
- }
- }
- }
- //变成自动改价 2021.4.14
- public static function autoPriceById($productId)
- {
- $product = self::getById($productId, true);
- if (empty($product)) {
- return false;
- }
- $price = bcadd($product->cost, $product->addPrice, 2);
- self::changePrice($product, $price, self::PRICE_LABEL_AUTO);
- }
- //获取当前门店下所有的product
- public static function getAllProduct($sjId, $shopId, $field = "*")
- {
- $where = [
- 'sjId' => $sjId,
- 'shopId' => $shopId,
- ];
- return self::getAllByCondition($where, null, $field);
- }
- //获取当前门店下所有花材的库存数量,及成本价,库存预警的花材数量 lqh 2021-04-20
- public static function getProductStockByShopId($sjId, $shopId)
- {
- $productInfo = self::getAllProduct($sjId, $shopId, "*");
- $data = [
- 'stockBigNum' => 0,
- 'stockSmallNum' => 0,
- 'stockCost' => 0,
- 'stockWarning' => 0,
- ];
- if ($productInfo) {
- foreach ($productInfo as $v) {
- $stock = self::formatStock($v['stock'], $v['ratio']);
- $data['stockBigNum'] = bcadd($data['stockBigNum'], $stock['bigNum']);
- $data['stockSmallNum'] = bcadd($data['stockSmallNum'], $stock['smallNum']);
- $data['stockCost'] = bcadd($data['stockCost'], bcmul($v['stock'], $v['cost'], 2), 2);
- if ($v['stock'] <= $v['stockWarning']) {
- $data['stockWarning']++;
- }
- }
- }
- return $data;
- }
- //补className
- public static function groupClassName($mainId, $data)
- {
- $classNameMap = ItemClassClass::getAllByCondition(['mainId' => $mainId], null, 'id,name', 'id');
- foreach ($data as $k => $v) {
- $classId = $v['classId'];
- $className = isset($classNameMap[$classId]) && isset($classNameMap[$classId]['name']) ? $classNameMap[$classId]['name'] : '';
- $v['className'] = $className;
- $data[$k] = $v;
- }
- return $data;
- }
- //供货商的productId => 零售端的productId ,不存在的补productId(放在默认分类)
- //productList [{"productId":"113","bigNum":1,"smallNum":0,"classId":"-2","itemId":1}]
- public static function toggleProductList($productList, $hdShopId, $hdSjId, $hdMainId, $ghs)
- {
- $itemIds = array_column($productList, "itemId");
- $hdProductData = self::getAllByCondition(['mainId' => $hdMainId, 'itemId' => ['in', $itemIds]], null, '*', 'itemId', true);
- $defaultClassId = ItemClassClass::getDefaultClassId($hdMainId);
- if (empty($defaultClassId)) {
- util::fail('没有找到花材的默认分类');
- }
- foreach ($productList as $k => $v) {
- $itemId = $v['itemId'] ?? 0;
- $ghsProductId = $v['productId'] ?? 0;
- if (isset($hdProductData[$itemId]) == false) {
- //不存在,则从平台新增
- $ptItem = PtItemClass::getById($itemId);
- unset($ptItem['addTime']);
- unset($ptItem['updateTime']);
- $productData = $ptItem;
- $productData['sjId'] = $hdSjId;
- $productData['shopId'] = $hdShopId;
- $productData['mainId'] = $hdMainId;
- $productData['itemId'] = $itemId;
- $productData['classId'] = $defaultClassId;
- unset($productData['id']);
- $productData['rank'] = 'A';
- //计算价格
- $cost = $v['cost'] ?? 0;
- $addPrice = $v['addPrice'] ?? 0;
- $price = bcadd($cost, $addPrice, 2);
- $userPrice = $v['userPrice'] ?? 0;
- if ($cost <= 0 && $price <= 0) {
- if ($userPrice > 0) {
- $price = $userPrice;
- $productData['cost'] = $price;
- } else {
- $price = 28;
- $productData['cost'] = 28;
- }
- $productData['skMore'] = 5;
- $productData['addPrice'] = 4;
- $productData['hjAddPrice'] = 3;
- }
- $productData['price'] = $price;
- $productData['skPrice'] = $price;
- $productData['hjPrice'] = $price;
- $productData['status'] = 2;
- //被归到默认分类,排序值要小,这样在花材列表搜索时,默认分类才不会被排在前面
- $productData['inTurn'] = -1;
- $addProduct = self::addBaseData($productData);
- $hdProductId = $addProduct->id ?? 0;
- //通知新花材需要分类
- //NotifyClass::cgGetNewProduct($addProduct, $hdMainId, $hdShopId, $ghs);
- } else {
- $current = $hdProductData[$itemId];
- $hdProductId = $current->id ?? 0;
- $current->delStatus = 0;
- $current->save();
- }
- $productList[$k]['productId'] = $hdProductId;
- $productList[$k]['ghsProductId'] = $ghsProductId;
- }
- return $productList;
- }
- //供货商、零售端新开门店时,初始化花材
- public static function newShopInitProduct($sjId, $shopId, $newShopId, $adminId)
- {
- $product = self::getAllProduct($sjId, $shopId, "name,cover,classId,itemId,rank,price,priceLabel,cost,addPrice,stockWarning,weight,alias,py,ratio,bigUnit,smallUnit,bigUnitId,smallUnitId,inTurn");
- $productData = [];
- foreach ($product as $v) {
- $tmp = $v;
- $tmp['sjId'] = $sjId;
- $tmp['shopId'] = $newShopId;
- $tmp['adminId'] = $adminId;
- $productData[] = $tmp;
- }
- self::batchAdd($productData);
- }
- //花材销量增加
- public static function updateActualSoldById($id, $itemNum)
- {
- $data['actualSold'] = $itemNum;
- $res = self::updateById($id, $data);
- return $res;
- }
- //新增花材
- public static function addProduct($data, $currentShop)
- {
- $currentMainId = $currentShop->mainId ?? 0;
- $classId = $data['classId'] ?? 0;
- $mainId = $data['mainId'] ?? 0;
- $stockWarning = $data['stockWarning'] ?? 5;
- $data['py'] = stringUtil::py($data['name']);
- $name = $data['name'] ?? '';
- $data['alias'] = $data['alias'] ?? '';
- $data['cover'] = !empty($data['cover']) ? $data['cover'] : '';
- $ratioType = $data['ratioType'] ?? 0;
- if ($ratioType == 0) {
- if (!isset($data['ratio']) || $data['ratio'] <= 0) {
- util::fail('请填写几支装');
- }
- $ratio = $data['ratio'];
- } else {
- $ratio = 10;
- $data['ratio'] = 10;
- }
- $weight = $data['weight'] ?? 0;
- $bigUnitId = $data['bigUnitId'] ?? 0;
- $smallUnitId = $data['smallUnitId'] ?? 0;
- if (empty($bigUnitId) || empty($smallUnitId)) {
- util::fail('请选择单位');
- }
- $unitList = UnitClass::getByIds([$bigUnitId, $smallUnitId], null, 'id');
- $bigUnit = $unitList[$bigUnitId]['name'] ?? '扎';
- $smallUnit = $unitList[$smallUnitId]['name'] ?? '支';
- $data['bigUnit'] = $bigUnit;
- $data['smallUnit'] = $smallUnit;
- $data['shopId'] = $data['shopId'] ?? 0;
- $currentShopId = $data['shopId'];
- $data['sjId'] = $data['sjId'] ?? 0;
- if (!$data['sjId']) {
- util::fail("参数错误");
- }
- $stock = 0;
- if (isset($data['stock']) && is_numeric($data['stock'])) {
- if ($data['stock'] < 0) {
- util::fail("库存数不能小于0");
- }
- if ($data['stock'] > 999999) {
- util::fail('库存数不能超过6个9');
- }
- $stock = $data['stock'];
- }
- //没有库存则下架
- $data['status'] = $stock == 0 ? 2 : 1;
- if (empty($classId)) {
- util::fail("请选择分类");
- }
- if (!isset($data['price']) || !is_numeric($data['price']) || $data['price'] < 0) {
- util::fail("请输入价格");
- }
- if (!isset($data['cost']) || !is_numeric($data['cost']) || $data['cost'] < 0) {
- util::fail("请输入成本价");
- }
- if (!isset($data['addPrice']) || !is_numeric($data['addPrice'])) {
- util::fail("请输入加价");
- }
- if ($stockWarning === false) {
- util::fail("请输入库存预警值");
- }
- if ($name === false) {
- util::fail("请输入花材名称");
- }
- if ($weight === false) {
- util::fail("请输入花材重量");
- }
- if (isset($data['itemRemark'])) {
- $itemRemark = trim($data['itemRemark'] ?? '');
- if (mb_strlen($itemRemark) > 200) {
- util::fail('备注不能超过200字');
- }
- $data['itemRemark'] = $itemRemark;
- }
- $cat = ItemClassClass::getById($classId, true);
- if (empty($cat)) {
- util::fail("花材分类不存在");
- }
- if ($cat->mainId != $mainId) {
- util::fail('不是您的分类');
- }
- $catName = $cat->name ?? '';
- if (isset($data['discountPrice']) && is_numeric($data['discountPrice'])) {
- $discountPrice = $data['discountPrice'];
- $currentPrice = $data['price'] ?? 0;
- if ($discountPrice >= $currentPrice) {
- util::fail('特价要小于售价');
- }
- $hjDiscountPrice = isset($data['hjDiscountPrice']) && is_numeric($data['hjDiscountPrice']) ? $data['hjDiscountPrice'] : 0;
- $skDiscountPrice = isset($data['skDiscountPrice']) && is_numeric($data['skDiscountPrice']) ? $data['skDiscountPrice'] : 0;
- if ($hjDiscountPrice > $discountPrice) {
- util::fail('批发特价要大于会员特价');
- }
- if ($discountPrice > $skDiscountPrice) {
- util::fail('零售特价要大于批发特价');
- }
- }
- $connection = Yii::$app->db;
- $transaction = $connection->beginTransaction();
- try {
- $ptItemId = $data['itemId'] ?? 0;
- $ptItemInfo = PtItemClass::getById($ptItemId, true);
- $bigUnitId = $data['bigUnitId'] ?? 0;
- $smallUnitId = $data['smallUnitId'] ?? 0;
- $changeUnit = 0;
- if ($ptItemInfo !== null && ($ptItemInfo->bigUnitId != $bigUnitId || $ptItemInfo->smallUnitId != $smallUnitId || $ptItemInfo->ratio != $ratio)) {
- //如果被修改了单位,则重新创建花材
- $changeUnit = 1;
- }
- if (empty($ptItemId) || $changeUnit == 1) {
- //添加新品种先在平台新增花材
- $defaultInfo = PtItemClassClass::getByCondition(['isDefault' => 1]);
- $defaultClassId = $defaultInfo['id'] ?? 0;
- if (empty($defaultClassId)) {
- util::fail('没有找到平台默认分类');
- }
- $itemData = $data;
- $itemData['classId'] = $defaultClassId;
- $itemData['skAddPrice'] = $itemData['skAddPrice'] ?? 3;
- $itemData['hjAddPrice'] = $itemData['hjAddPrice'] ?? 2;
- $itemData['zsAddPrice'] = $itemData['zsAddPrice'] ?? 1;
- $ptItemInfo = PtItemClass::addItem($itemData);
- $data['itemId'] = $ptItemInfo['id'];
- } else {
- //从平台导入花材
- $has = self::getByCondition(['mainId' => $mainId, 'itemId' => $data['itemId']], true);
- if (!empty($has)) {
- $hasName = $has->name ?? '';
- util::fail($hasName . '已经存在了');
- }
- }
- //小菊的结构
- $data['variety'] = $ptItemInfo->variety ?? 0;
- //批发价比进货价贵多少 2021-12-07 lqh 如果前端有传取前端的,没有则取pt
- $addPrice = $data['addPrice'] ?? $ptItemInfo->addPrice;
- $data['addPrice'] = $addPrice;
- //批发价
- $price = $data['price'] ?? 0;
- if (empty($price) || $price <= 0) {
- util::fail('请填写价格');
- }
- $skPrice = $data['skPrice'] ?? 0;
- if (empty($skPrice) || $skPrice <= 0) {
- util::fail('请填写零售价');
- }
- $hjPrice = $data['hjPrice'] ?? 0;
- if (empty($hjPrice) || $hjPrice <= 0) {
- util::fail('请填写会员价');
- }
- if ($hjPrice > $price) {
- util::fail('批发价要大于会员价');
- }
- if ($price > $skPrice) {
- util::fail('零售价要大于批发价');
- }
- $data['property'] = 1;
- $respond = self::addBaseData($data);
- if ($stock > 0) {
- //有库存数量,增加盘盈记录 2021.7.9 lqh
- //增加盘点订单
- $pdOrderSn = orderSn::getGhsCheckSn();
- $pdOrderData = [];
- $pdOrderData['orderSn'] = $pdOrderSn;
- $pdOrderData['sjId'] = $data['sjId'];
- $pdOrderData['shopId'] = $data['shopId'];
- $pdOrderData['status'] = CheckOrderClass::STATUS_COMPLETE;
- $pdOrderData['bigNum'] = $stock;
- $pdOrderData['adminId'] = $data['adminId'];
- $pdOrderData['smallNum'] = 0;
- $pdOrderData['price'] = $data['price'];
- $pdOrderData['remark'] = '初始库存';
- CheckOrderClass::add($pdOrderData);
- $pdOrderItemData = [];
- $pdOrderItemData['orderSn'] = $pdOrderSn;
- $pdOrderItemData['productId'] = $respond->id ?? 0;
- $pdOrderItemData['itemId'] = $data['itemId'];
- $pdOrderItemData['itemNum'] = $stock;
- $pdOrderItemData['itemStock'] = 0;
- $pdOrderItemData['profitLostNum'] = $stock;
- $itemInfo = [
- 'itemName' => $name,
- 'itemCover' => $data['cover'],
- 'bigNum' => $stock,
- 'smallNum' => 0,
- 'bigNumStock' => 0,
- 'smallNumStock' => 0,
- 'bigNumProfitLoss' => $stock,
- 'smallNumProfitLoss' => 0,
- 'itemUnit' => 0,
- 'ratio' => $ratio,
- 'rank' => 'A',
- 'bigUnit' => $data['bigUnit'],
- 'smallUnit' => $data['smallUnit'],
- ];
- $pdOrderItemData['itemInfo'] = json_encode($itemInfo);
- $pdOrderItemData['itemPrice'] = $data['price'];
- $pdOrderItemData['itemCost'] = $data['cost'];
- CheckOrderItemClass::add($pdOrderItemData);
- $record = [];
- $record['sjId'] = $data['sjId'];
- $record['shopId'] = $data['shopId'];
- //增加中央ID
- $record['mainId'] = $currentMainId;
- $record['orderSn'] = $pdOrderSn;
- $record['itemId'] = $data['itemId'];
- $record['productId'] = $respond->id ?? 0;
- $record['itemNum'] = $stock;//盈亏数
- $record['oldStock'] = 0;
- $record['newStock'] = $stock; //新库存直接等于盘点的数量
- $record['relateName'] = $data['staffName'] ?? '';
- StockRecordClass::addCheckOrderRecord($record);
- }
- //在首店添加,则找到父级sj下的所有直营和加盟店,都进行同步
- if (isset($currentShop->default) && $currentShop->default == 1) {
- $sjId = $currentShop->sjId ?? 0;
- $shopList = ShopClass::getAllByCondition(['sjId' => $sjId], null, '*', null, true);
- foreach ($shopList as $shop) {
- $shopId = $shop->id ?? 0;
- if ($shopId == $currentShop->id) {
- //前面已经添加过了
- continue;
- }
- $thisMainId = $shop->mainId ?? 0;
- $data['shopId'] = $shopId;
- $data['mainId'] = $thisMainId;
- //不是当前门店,库存默认为0并且是下架状态。花材分类放在同名分类下,如果没有则放默认分类
- if ($currentShopId != $shopId) {
- $data['stock'] = 0;
- $data['status'] = 2;
- $currentClassId = 0;
- $classList = ItemClassClass::getAllByCondition(['mainId' => $thisMainId], null, '*', null, true);
- if (!empty($classList)) {
- foreach ($classList as $currentClass) {
- $currentName = $currentClass->name ?? '';
- if ($currentName == $catName) {
- $currentClassId = $currentClass->id ?? 0;
- }
- }
- }
- if (empty($currentClassId)) {
- $defaultCat = ItemClassClass::getByCondition(['mainId' => $thisMainId, 'isDefault' => 1], true);
- $currentClassId = $defaultCat->id ?? 0;
- }
- if (empty($currentClassId)) {
- util::fail('直营店没有分类,也没有默认分类');
- }
- $data['classId'] = $currentClassId;
- }
- //已经有了不再添加
- $chainHas = self::getByCondition(['mainId' => $thisMainId, 'itemId' => $ptItemId], true);
- if (!empty($chainHas)) {
- continue;
- }
- self::addBaseData($data);
- }
- }
- $transaction->commit();
- } catch (\Exception $exception) {
- $transaction->rollBack();
- Yii::info('失败原因:' . $exception->getMessage());
- util::fail('添加失败');
- }
- }
- /**
- * 改变花材状态并重置特价、满减、限购
- * @param $product
- * @param $status 1上架 2下架
- * @param bool $stockEmpty 库存为空(指新设置的库存)
- * @throws \Exception
- */
- public static function changeStatusAndReset($product, $status, $stockEmpty = false)
- {
- $product->status = $status;
- // 当前库存为0
- if (intval($product->stock) == 0) {
- //库存=0时下架,特价一起去掉
- $product->discountPrice = 0;
- $product->hjDiscountPrice = 0;
- $product->skDiscountPrice = 0;
- //花材满减去掉 ssh 20260318
- $product->reachNum = 0;
- $product->reachNumDiscount = 0;
- //花材去除限购
- $product->limitBuy = 0;
- self::clearLimitBuyCache($product->id); // 清空限购记录缓存
- }
- // 新设置的库存为0
- if ($stockEmpty) {
- //库存=0时下架,特价一起去掉
- $product->discountPrice = 0;
- $product->hjDiscountPrice = 0;
- $product->skDiscountPrice = 0;
- //花材满减去掉 ssh 20260318
- $product->reachNum = 0;
- $product->reachNumDiscount = 0;
- //花材去除限购
- $product->limitBuy = 0;
- // self::clearLimitBuyCache($productId); // 此处不清空限购记录缓存,留在更新库存的地方来做清空缓存
- }
- }
- //获取当前供货商下的所有item
- public static function getGhsItemAll($sjId, $select = "*")
- {
- $where = [
- 'sjId' => $sjId
- ];
- $data = self::getAllList($select, $where);
- return $data;
- }
- //库存预警通知 ssh 20210909
- public static function stockWarningAddQueue($product, $stock)
- {
- $warningNum = $product['stockWarning'] ?? 0;
- if ($warningNum <= 0) {
- return false;
- }
- $date = date("Y-m-d");
- $productId = $product['id'] ?? 0;
- $key = 'stockWarning_' . $productId . '_' . $date;
- //当天已经放入队列通知的不再通知
- $hasWarning = Yii::$app->redis->executeCommand('GET', [$key]);
- if (isset($hasWarning) && !empty($hasWarning)) {
- return false;
- }
- if ($stock <= $warningNum) {
- Yii::$app->redis->executeCommand('SETEX', [$key, 86400, 'hasWarning']);
- $shopId = $product['shopId'] ?? 0;
- if (empty($shopId)) {
- return false;
- }
- //队列方式去处理
- $stockWarningListKey = 'stockWarningList_' . $shopId;
- Yii::$app->redis->executeCommand('LPUSH', [$stockWarningListKey, $productId]);
- }
- }
- //所有门店进行库存通知 ssh 20210909
- public static function allShopStockWarningFromQueue()
- {
- //先取消库存预警
- return true;
- $ghs = dict::getDict('ptStyle', 'ghs');
- $shopList = ShopClass::getAllByCondition(['ptStyle' => $ghs], null, '*', null, true);
- if (!empty($shopList)) {
- foreach ($shopList as $key => $shop) {
- $ids = [];
- $shopId = $shop->id ?? 0;
- $stockWarningListKey = 'stockWarningList_' . $shopId;
- while ($count = Yii::$app->redis->executeCommand('LLEN', [$stockWarningListKey])) {
- $productId = Yii::$app->redis->executeCommand('RPOP', [$stockWarningListKey]);
- if (is_numeric($productId)) {
- $ids[] = $productId;
- }
- }
- if (empty($ids)) {
- continue;
- }
- $ids = array_unique(array_filter($ids));
- $productList = self::getAllByCondition(['id' => ['in', $ids]], null, '*', null, true);
- if (!empty($productList)) {
- WxMessageClass::stockWarningInform($shop, $productList);
- }
- }
- }
- }
- //通过花材ID 获取mainId lqh 2022.03.20
- public static function getMainIdByProductId($productId)
- {
- $product = self::getById($productId, false);
- return $product['mainId'] ?? 0;
- }
- /**
- * 创建限购缓存(有过期时间)
- * @param $productId 花材ID
- * @param int $seconds 过期时间
- * @param array $options ['clearAt' => 0, 'recurring' => 0, 'intervalDays' => 0, 'clearHour' => 0] 循环清空配置
- * @return bool
- */
- public static function createLimitBuyCache($productId, $seconds = 0, $options = [])
- {
- $limitKey = self::LIMIT_BUY_KEY . $productId;
- $clearMarkKey = self::CLEAR_MARK_KEY . $productId;
- $clearLoopKey = self::CLEAR_LOOP_KEY . $productId;
- $recurring = !empty($options['recurring']);
- $has = Yii::$app->redis->executeCommand('HEXISTS', [$limitKey, 0]);
- if (!empty($has)) {
- // 获取缓存超时时间
- $expire = Yii::$app->redis->executeCommand('TTL', [$limitKey]);
- if ($expire > 0) {
- //return;
- }
- //删除缓存
- Yii::$app->redis->executeCommand('HDEL', [$limitKey, 0]);
- }
- Yii::$app->redis->executeCommand('HSET', [$limitKey, 0, 0]);
- if ($seconds > 0) {
- $clearAt = intval($options['clearAt'] ?? 0);
- if ($clearAt <= 0) {
- $clearAt = time() + intval($seconds);
- }
- Yii::$app->redis->executeCommand('EXPIRE', [$limitKey, $seconds]);
- Yii::$app->redis->executeCommand('SET', [$clearMarkKey, $clearAt]);
- if ($recurring) {
- $intervalDays = intval($options['intervalDays'] ?? 0);
- $clearHour = intval($options['clearHour'] ?? -1);
- Yii::$app->redis->executeCommand('SET', [$clearLoopKey, json_encode([
- 'intervalDays' => $intervalDays,
- 'clearHour' => $clearHour,
- ], JSON_UNESCAPED_UNICODE)]);
- } else {
- Yii::$app->redis->executeCommand('DEL', [$clearLoopKey]);
- }
- // 用 RabbitMQ 延迟消息在到期时清空订单项限购字段
- $message = [
- 'type' => 'limit_buy_clear',
- 'ptType' => 'ghs',
- 'productId' => $productId,
- 'clearAt' => $clearAt,
- ];
- if ($recurring) {
- $message['recurring'] = 1;
- $message['intervalDays'] = intval($options['intervalDays'] ?? 0);
- $message['clearHour'] = intval($options['clearHour'] ?? -1);
- }
- $message = serialize($message);
- $producer = Yii::$app->rabbitmq->getProducer('stockProducer');
- $producer->publish($message, 'limitBuyDelayExchange', 'limitBuyDelayRoute', [
- 'delivery_mode' => 2,
- 'content_type' => 'application/octet-stream',
- 'application_headers' => new AMQPTable([
- 'x-delay' => intval($seconds * 1000),
- ]),
- ]);
- Yii::info('限购延迟消息已发送: ' . json_encode([
- 'type' => 'limit_buy_clear',
- 'ptType' => 'ghs',
- 'productId' => intval($productId),
- 'clearAt' => intval($clearAt),
- 'delayMs' => intval($seconds * 1000),
- 'recurring' => $recurring ? 1 : 0,
- ], JSON_UNESCAPED_UNICODE), __METHOD__);
- } else {
- Yii::$app->redis->executeCommand('DEL', [$clearMarkKey]);
- Yii::$app->redis->executeCommand('DEL', [$clearLoopKey]);
- }
- }
- // 解析循环清空限购配置
- public static function getLimitBuyClearLoopConfig($data)
- {
- if ($data['limitBuyClearType'] == 0) {
- return [];
- }
- $hasIntervalDays = array_key_exists('limitBuyClearIntervalDays', $data) && $data['limitBuyClearIntervalDays'] !== '';
- $hasClearHour = (array_key_exists('cleartAt', $data) && $data['cleartAt'] !== '')
- || (array_key_exists('clearAt', $data) && $data['clearAt'] !== '');
- if (!$hasIntervalDays && !$hasClearHour) {
- return [];
- }
- if (!$hasIntervalDays || !$hasClearHour) {
- util::fail('请填写循环清空限购的间隔天数和执行时间');
- }
- if (!is_numeric($data['limitBuyClearIntervalDays'])) {
- util::fail('循环清空限购的间隔天数错误');
- }
- $clearHourValue = array_key_exists('cleartAt', $data) ? $data['cleartAt'] : $data['clearAt'];
- if (!is_numeric($clearHourValue)) {
- util::fail('循环清空限购的执行时间错误');
- }
- $intervalDays = intval($data['limitBuyClearIntervalDays']);
- $clearHour = intval($clearHourValue);
- if ($intervalDays <= 0) {
- util::fail('循环清空限购的间隔天数必须大于0');
- }
- if ($clearHour < 0 || $clearHour > 23) {
- util::fail('循环清空限购的执行时间必须在0点到23点之间');
- }
- return ['intervalDays' => $intervalDays, 'clearHour' => $clearHour];
- }
- /**
- * 创建循环清空限购缓存
- * @param $productId 花材ID
- * @param int $intervalDays 循环清空限购的间隔天数
- * @param int $clearHour 循环清空限购的执行时间点
- * @param int $clearAt 循环清空限购的下次清空时间
- * @return bool
- */
- public static function createRecurringLimitBuyCache($productId, $intervalDays, $clearHour, $clearAt = 0)
- {
- $productId = intval($productId);
- $intervalDays = intval($intervalDays);
- $clearHour = intval($clearHour);
- if ($productId <= 0 || $intervalDays <= 0 || $clearHour < 0 || $clearHour > 23) {
- return false;
- }
- if ($clearAt <= 0) {
- $clearAt = self::getNextLimitBuyClearAt($intervalDays, $clearHour);
- }
- $seconds = max(1, $clearAt - time());
- self::createLimitBuyCache($productId, $seconds, [
- 'recurring' => 1,
- 'intervalDays' => $intervalDays,
- 'clearHour' => $clearHour,
- 'clearAt' => $clearAt,
- ]);
- return true;
- }
- // 计算下一次循环清空时间
- public static function getNextLimitBuyClearAt($intervalDays, $clearHour, $baseTime = 0)
- {
- $baseTime = $baseTime > 0 ? intval($baseTime) : time();
- $targetDay = $baseTime + intval($intervalDays) * 86400;
- $clearAt = strtotime(date('Y-m-d', $targetDay) . ' ' . sprintf('%02d:00:00', intval($clearHour)));
- while ($clearAt <= $baseTime) {
- $clearAt = strtotime('+' . intval($intervalDays) . ' days', $clearAt);
- }
- return $clearAt;
- }
- // 获取循环清空限购配置
- public static function getLimitBuyClearLoopConfigByProductId($productId)
- {
- $productId = intval($productId);
- if ($productId <= 0) {
- return [];
- }
- $clearLoopKey = self::CLEAR_LOOP_KEY . $productId;
- $config = Yii::$app->redis->executeCommand('GET', [$clearLoopKey]);
- if (empty($config)) {
- return [];
- }
- $config = json_decode($config, true);
- return is_array($config) ? $config : [];
- }
- // 获取限购清空配置,用于商品详情回显
- public static function getLimitBuyClearInfo($productId)
- {
- $productId = intval($productId);
- $info = [
- 'limitBuyClearType' => 0, // 0不清空 1定时清空 2循环清空
- 'limitBuyClearTypeName' => '不清空',
- 'limitBuyClearAt' => 0,
- 'limitBuyClearTime' => '',
- 'limitBuyNextClearAt' => 0,
- 'limitBuyNextClearTime' => '',
- 'limitBuyClearIntervalDays' => 0,
- 'cleartAt' => '',
- ];
- if ($productId <= 0) {
- return $info;
- }
- $loopConfig = self::getLimitBuyClearLoopConfigByProductId($productId);
- if (!empty($loopConfig)) {
- $info['limitBuyClearType'] = 1;
- $info['limitBuyClearTypeName'] = '循环清空';
- $info['limitBuyClearIntervalDays'] = intval($loopConfig['intervalDays'] ?? 0);
- $info['cleartAt'] = intval($loopConfig['clearHour'] ?? 0);
- return $info;
- }
- $clearMarkKey = self::CLEAR_MARK_KEY . $productId;
- $clearAt = intval(Yii::$app->redis->executeCommand('GET', [$clearMarkKey]));
- if ($clearAt <= 0) {
- return $info;
- }
- $info['limitBuyClearType'] = 2;
- $info['limitBuyClearTypeName'] = '定时清空';
- $info['limitBuyClearAt'] = $clearAt;
- $info['limitBuyClearTime'] = date('Y-m-d H:i:s', $clearAt);
- $info['limitBuyNextClearAt'] = $clearAt;
- $info['limitBuyNextClearTime'] = $info['limitBuyClearTime'];
- return $info;
- }
- // 清理循环清空限购配置
- public static function clearLimitBuyClearLoopConfig($productId)
- {
- $productId = intval($productId);
- if ($productId <= 0) {
- return false;
- }
- $clearLoopKey = self::CLEAR_LOOP_KEY . $productId;
- Yii::$app->redis->executeCommand('DEL', [$clearLoopKey]);
- return true;
- }
- /**
- * 记录限购缓存写入前快照(同一次请求内同商品同客户只记录一次)
- *
- * @param int $productId
- * @param int $customId
- * @param bool $hasOldValue
- * @param string|int|float $oldValue
- * @return void
- */
- public static function recordLimitBuyRollbackSnapshot($productId, $customId, $hasOldValue, $oldValue = 0)
- {
- $productId = intval($productId);
- $customId = intval($customId);
- if ($productId <= 0 || $customId <= 0) {
- return;
- }
- $snapshotKey = $productId . '_' . $customId;
- if (!isset(Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY]) || !is_array(Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY])) {
- Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY] = [];
- }
- if (isset(Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY][$snapshotKey])) {
- return;
- }
- Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY][$snapshotKey] = [
- 'productId' => $productId,
- 'customId' => $customId,
- 'hasOldValue' => $hasOldValue ? 1 : 0,
- 'oldValue' => strval($oldValue),
- ];
- }
- /**
- * 清理当前请求中记录的限购回滚快照
- *
- * @return void
- */
- public static function clearLimitBuyRollbackSnapshot()
- {
- unset(Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY]);
- }
- /**
- * 回滚当前请求中已记录的限购缓存变更
- *
- * @return bool
- */
- public static function rollbackLimitBuySnapshot()
- {
- $snapshotList = Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY] ?? [];
- if (empty($snapshotList) || !is_array($snapshotList)) {
- return true;
- }
- foreach ($snapshotList as $snapshot) {
- $productId = intval($snapshot['productId'] ?? 0);
- $customId = intval($snapshot['customId'] ?? 0);
- if ($productId <= 0 || $customId <= 0) {
- continue;
- }
- $limitKey = self::LIMIT_BUY_KEY . $productId;
- $hasOldValue = intval($snapshot['hasOldValue'] ?? 0);
- if ($hasOldValue == 1) {
- $oldValue = $snapshot['oldValue'] ?? '0';
- Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $oldValue]);
- } else {
- Yii::$app->redis->executeCommand('HDEL', [$limitKey, $customId]);
- }
- }
- self::clearLimitBuyRollbackSnapshot();
- return true;
- }
- // 获取客户当前采购清单中各花材的限购情况
- public static function getLimitBuyInfoByList($list, $customId)
- {
- if (empty($list) || !is_array($list)) {
- return [];
- }
- $buyNumMap = [];
- $ids = [];
- foreach ($list as $item) {
- $productId = $item['id'] ?? 0;
- if (empty($productId)) {
- continue;
- }
- $productId = intval($productId);
- $bigNum = $item['bigCount'] ?? ($item['bigNum'] ?? 0);
- $smallNum = $item['smallCount'] ?? ($item['smallNum'] ?? 0);
- if (isset($buyNumMap[$productId]) == false) {
- $buyNumMap[$productId] = [
- 'bigNum' => 0,
- 'smallNum' => 0,
- ];
- }
- $buyNumMap[$productId]['bigNum'] = bcadd($buyNumMap[$productId]['bigNum'], $bigNum, 2);
- $buyNumMap[$productId]['smallNum'] = bcadd($buyNumMap[$productId]['smallNum'], $smallNum, 2);
- $ids[] = $productId;
- }
- $ids = array_values(array_unique($ids));
- if (empty($ids)) {
- return [];
- }
- $productData = self::getProductByIds($ids);
- $productData = array_column($productData, null, 'id');
- $respond = [];
- foreach ($ids as $productId) {
- $product = $productData[$productId] ?? [];
- if (empty($product)) {
- continue;
- }
- $limitBuy = $product['limitBuy'] ?? 0;
- $isLimit = $limitBuy > 0 ? true : false;
- $hasBuyNum = 0;
- if ($isLimit) {
- $limitKey = self::LIMIT_BUY_KEY . $productId;
- $hasBuyNum = Yii::$app->redis->executeCommand('HGET', [$limitKey, $customId]);
- $hasBuyNum = $hasBuyNum == null ? 0 : $hasBuyNum;
- }
- $buyNum = $buyNumMap[$productId] ?? [];
- $ratio = $product['ratio'] ?? 1;
- $currentBuyNum = self::mergeItemNum($buyNum['bigNum'] ?? 0, $buyNum['smallNum'] ?? 0, $ratio);
- $totalBuyNum = bcadd($hasBuyNum, $currentBuyNum, 2);
- $specialPrice = (
- ($product['hjDiscountPrice'] ?? 0) > 0
- && ($product['discountPrice'] ?? 0) > 0
- && ($product['skDiscountPrice'] ?? 0) > 0
- ) ? true : false;
- $respond[] = [
- 'id' => $productId,
- 'name' => $product['name'] ?? '',
- 'isLimit' => $isLimit, //是否限购
- 'limitBuy' => (float)$limitBuy, //限购数量
- 'specialPrice' => $specialPrice, //是否特价
- 'hasBuyNum' => $isLimit ? (float)$hasBuyNum : 0, //已购买数量
- 'currentBuyNum' => (float)$currentBuyNum, //此次购买的数量
- 'reachLimitBuyNum' => ($isLimit && $totalBuyNum > $limitBuy) ? true : false, //是否达到限购数量
- 'exceedNum' => $isLimit ? (float)bcsub($hasBuyNum, $limitBuy, 2) : 0, //超出数量, 小于等于0表示未超出
- ];
- }
- return $respond;
- }
- /**
- * 限购处理
- * @param $product
- * @param $customId
- * @param $num
- */
- public static function handleLimitBuy($product, $customId, $num)
- {
- $limitBuy = $product['limitBuy'];
- if ($limitBuy <= 0) {
- return;
- }
- $productId = $product['productId'];
- $limitKey = self::LIMIT_BUY_KEY . $productId;
- $has = Yii::$app->redis->executeCommand('HEXISTS', [$limitKey, $customId]);
- if (!empty($has)) {
- $hasNum = Yii::$app->redis->executeCommand('HGET', [$limitKey, $customId]);
- self::recordLimitBuyRollbackSnapshot($productId, $customId, true, $hasNum);
- $lastNum = bcadd($hasNum, $num);
- if ($lastNum > $limitBuy) {
- // 如果有特价,则超过的数量按原价卖;否则中断
- if ($product['hjDiscountPrice'] > 0 && $product['discountPrice'] > 0 && $product['skDiscountPrice'] > 0) {
- Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $lastNum]);
- return;
- }
- util::error(-1, '累计已超出限购数', ['productId' => $productId, 'limitBuy' => $limitBuy, 'exceed' => $lastNum - $limitBuy]);
- }
- Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $lastNum]);
- } else {
- self::recordLimitBuyRollbackSnapshot($productId, $customId, false, 0);
- if ($num > $limitBuy) {
- // 如果有特价,则超过的数量按原价卖;否则中断
- if ($product['hjDiscountPrice'] > 0 && $product['discountPrice'] > 0 && $product['skDiscountPrice'] > 0) {
- Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $num]);
- return;
- }
- util::error(-1, '超出限购数', ['productId' => $productId, 'limitBuy' => $limitBuy, 'exceed' => $num - $limitBuy]);
- }
- Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $num]);
- }
- }
- /**
- * 清空限购的缓存
- * @param int $productId
- * @param bool $clearAll
- */
- public static function clearLimitBuyCache($productId, $clearAll = true)
- {
- $limitKey = self::LIMIT_BUY_KEY . $productId;
- $arr = Yii::$app->redis->executeCommand('HKEYS', [$limitKey]);
- if (!empty($arr)) {
- foreach ($arr as $field) {
- self::baseClearLimitBuy($productId, $field);
- }
- }
- if ($clearAll === true) {
- self::clearLimitBuyClearMark($productId);
- self::clearLimitBuyClearLoopConfig($productId);
- }
- }
- // 校验清空限购消息是否是当前有效版本
- public static function checkLimitBuyClearMessage($productId, $clearAt)
- {
- $productId = intval($productId);
- $clearAt = intval($clearAt);
- if ($productId <= 0 || $clearAt <= 0) {
- return false;
- }
- $clearMarkKey = self::CLEAR_MARK_KEY . $productId;
- $currentClearAt = intval(Yii::$app->redis->executeCommand('GET', [$clearMarkKey]));
- return $currentClearAt > 0 && $currentClearAt == $clearAt;
- }
- // 清理限购清空标记
- public static function clearLimitBuyClearMark($productId)
- {
- $productId = intval($productId);
- if ($productId <= 0) {
- return false;
- }
- $clearMarkKey = self::CLEAR_MARK_KEY . $productId;
- Yii::$app->redis->executeCommand('DEL', [$clearMarkKey]);
- return true;
- }
- //$num -1 表示减全部,大于-1表示减值
- public static function baseClearLimitBuy($productId, $customId, $num = -1)
- {
- $limitKey = self::LIMIT_BUY_KEY . $productId;
- if ($num <= -1) {
- //清掉全部
- Yii::$app->redis->executeCommand('HDEL', [$limitKey, $customId]);
- } else {
- $hasNum = Yii::$app->redis->executeCommand('HGET', [$limitKey, $customId]);
- $remainNum = $hasNum > $num ? bcsub($hasNum, $num) : 0;
- $remainNum = floor($remainNum);
- if ($remainNum > 0) {
- Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $remainNum]);
- } else {
- Yii::$app->redis->executeCommand('HDEL', [$limitKey, $customId]);
- }
- }
- }
- // 只清空已购买记录,不关闭商品限购配置
- public static function clearLimitBuyRecordByProductId($productId)
- {
- $productId = intval($productId);
- if ($productId <= 0) {
- return false;
- }
- $limitKey = self::LIMIT_BUY_KEY . $productId;
- Yii::$app->redis->executeCommand('DEL', [$limitKey]);
- return true;
- }
- public static function getHasLimitBuyList($product)
- {
- $productId = $product->id;
- $limitBuy = $product->limitBuy;
- $limitKey = self::LIMIT_BUY_KEY . $productId;
- $arr = Yii::$app->redis->executeCommand('HKEYS', [$limitKey]);
- $customList = [];
- if (!empty($arr)) {
- $numMap = [];
- $ids = [];
- foreach ($arr as $customId) {
- $num = Yii::$app->redis->executeCommand('HGET', [$limitKey, $customId]);
- $numMap[$customId] = $num;
- $ids[] = $customId;
- }
- $specialPrice = ($product['hjDiscountPrice'] > 0 && $product['discountPrice'] > 0 && $product['skDiscountPrice'] > 0); // 销售花材是否开启特价
- $customList = CustomClass::getAllByCondition(['id' => ['in', $ids]], null, '*');
- foreach ($customList as $key => $val) {
- $customId = $val['id'];
- $num = $numMap[$customId] ?? 0;
- $customList[$key]['hasLimitBuyNum'] = $num;
- $customList[$key]['reachLimitBuyNum'] = $num >= $limitBuy ? 1 : 0;
- $avatar = $val['avatar'] ?? '';
- $smallAvatar = imgUtil::groupImg($avatar);
- $customList[$key]['smallAvatar'] = $smallAvatar . "?x-oss-process=image/resize,m_fill,h_80,w_80";
- $customList[$key]['specialPrice'] = $specialPrice;
- }
- }
- return $customList;
- }
- /**
- * 根据花材清空订单项限购值
- *
- * @param int $productId
- * @return bool
- */
- public static function clearLimitBuyByProductId($productId, $oldLimitBuy = 0)
- {
- $productId = intval($productId);
- if ($productId <= 0) {
- return false;
- }
- self::updateById($productId, ['limitBuy' => 0]);
- if ($oldLimitBuy > 0) {
- self::createRecoverLimitBuyCache($productId, $oldLimitBuy);
- }
- return true;
- }
- /**
- * 创建限购旧值快照缓存
- * @param $productId
- * @param $oldLimitBuy
- * @return bool
- */
- public static function createRecoverLimitBuyCache($productId, $oldLimitBuy)
- {
- $productId = intval($productId);
- if ($productId <= 0) {
- return false;
- }
-
- $limitKey = self::RECOVER_LIMIT_BUY_KEY . $productId;
- Yii::$app->redis->executeCommand('SET', [$limitKey, $oldLimitBuy]);
- //Yii::$app->redis->executeCommand('EXPIRE', [$limitKey, 1200]);// 要考虑售后退款,所以不能主动清空,而是只能被动清空
- return true;
- }
- /**
- * 删除限购旧值快照缓存
- * @param $productId
- * @return bool
- */
- public static function deleteRecoverLimitBuyCache($productId)
- {
- $productId = intval($productId);
- if ($productId <= 0) {
- return false;
- }
- $limitKey = self::RECOVER_LIMIT_BUY_KEY . $productId;
- Yii::$app->redis->executeCommand('DEL', [$limitKey]);
- return true;
- }
- /**
- * 获取限购旧值快照缓存
- * @param $productId
- * @return bool
- */
- public static function getRecoverLimitBuyCache($productId)
- {
- $productId = intval($productId);
- if ($productId <= 0) {
- return false;
- }
- $limitKey = self::RECOVER_LIMIT_BUY_KEY . $productId;
- return Yii::$app->redis->executeCommand('GET', [$limitKey]);
- }
- /**
- * 库存从 0 回滚时,尝试恢复限购数量
- * @param int $productId
- * @param mixed $oldStock
- * @return bool
- */
- public static function tryRecoverLimitBuyWhenStockRollbackFromZero($productId, $oldStock)
- {
- if (floatval($oldStock) > 0) {
- return false;
- }
- $recoverLimitBuy = self::getRecoverLimitBuyCache($productId);
- if ($recoverLimitBuy === false || $recoverLimitBuy === null || $recoverLimitBuy === '') {
- return false;
- }
- $recoverLimitBuy = intval($recoverLimitBuy);
- if ($recoverLimitBuy <= 0) {
- self::deleteRecoverLimitBuyCache($productId);
- return false;
- }
- self::updateById($productId, ['limitBuy' => $recoverLimitBuy]);
- self::deleteRecoverLimitBuyCache($productId);
- return true;
- }
- }
|