1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296 |
- <?php
- // +----------------------------------------------------------------------
- // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
- // +----------------------------------------------------------------------
- // | Author: CRMEB Team <admin@crmeb.com>
- // +----------------------------------------------------------------------
- declare (strict_types=1);
- namespace app\services\activity\promotions;
- use app\dao\activity\promotions\StorePromotionsDao;
- use app\services\activity\coupon\StoreCouponIssueServices;
- use app\services\activity\coupon\StoreCouponUserServices;
- use app\services\order\StoreOrderCreateServices;
- use app\services\order\StoreOrderComputedServices;
- use app\services\BaseServices;
- use app\services\product\brand\StoreBrandServices;
- use app\services\product\label\StoreProductLabelServices;
- use app\services\product\product\StoreProductRelationServices;
- use app\services\product\product\StoreProductServices;
- use app\services\product\branch\StoreBranchProductServices;
- use app\services\product\sku\StoreProductAttrValueServices;
- use app\services\store\SystemStoreServices;
- use app\services\user\label\UserLabelServices;
- use app\services\order\StoreOrderServices;
- use app\services\order\StoreOrderCartInfoServices;
- use app\services\order\StoreCartServices;
- use app\services\product\category\StoreProductCategoryServices;
- use crmeb\exceptions\AdminException;
- use think\exception\ValidateException;
- use \crmeb\traits\OptionTrait;
- /**
- * 促销活动
- * Class StorePromotionsServices
- * @package app\services\activity\promotions
- * @mixin StorePromotionsDao
- */
- class StorePromotionsServices extends BaseServices
- {
- use OptionTrait;
- /**
- * 活动类型
- * @var string[]
- */
- protected $promotionsType = [
- 1 => '限时折扣',
- 2 => '第N件N折',
- 3 => '满减满折',
- 4 => '满送',
- ];
- /**
- * 优惠内容数据
- * @var array
- */
- protected $promotionsData = [
- 'threshold_type' => 1,//门槛类型1:满N元2:满N件
- 'threshold' => 0,//优惠门槛
- 'discount_type' => 1,//优惠类型1:满减2:满折
- 'n_piece_n_discount' => 3,//n件n折类型:1:第二件半件2:买1送1 3:自定义
- 'discount' => 0,//优惠
- 'give_integral' => 0,//赠送积分
- 'give_coupon_id' => [],//赠送优惠券ID
- 'give_product_id' => [],//赠送商品ID
- ];
- /**
- * StorePromotionsServices constructor.
- * @param StorePromotionsDao $dao
- */
- public function __construct(StorePromotionsDao $dao)
- {
- $this->dao = $dao;
- }
- /**
- * 获取打折折扣 || 优惠折扣
- * @param $num
- * @param int $unit
- * @param int $type 1:打折折扣 2:优惠折扣
- * @return float
- */
- public function computedDiscount($num, int $unit = 100, int $type = 1)
- {
- if ((float)$num < 0) {
- $num = 0;
- } elseif ((float)$num > 100) {
- $num = 100;
- }
- $discount = bcdiv((string)$num, (string)$unit, 2);
- if ($type == 2) {//优惠折扣 打9折扣优惠就是1折
- $discount = bcsub('1', (string)$discount, 2);
- }
- return (float)$discount;
- }
- /**
- * 获取优惠活动标题,内容详情
- * @param int $type
- * @param int $promotions_cate
- * @param array $promotions
- * @return array
- */
- public function getPromotionsDesc(int $type, int $promotions_cate, array $promotions)
- {
- $title = '';
- $desc = [];
- if ($promotions) {
- switch ($type) {
- case 1:
- $title = '限时折扣';
- $base = '限时打' . $this->computedDiscount($promotions[0]['discount'] ?? 0, 10) . '折';
- if (isset($promotions['is_limit']) && isset($promotions['limit_num']) && (int)$promotions['is_limit'] && (int)$promotions['limit_num']) {
- $base .= ',每人限购' . (int)$promotions['limit_num'] . '件';
- }
- $desc[] = $base;
- break;
- case 2:
- switch ($promotions[0]['n_piece_n_discount'] ?? 3) {
- case 1:
- $title = '第二件半价';
- break;
- case 2:
- $title = '买1送1';
- break;
- case 3:
- $title = '第' . floatval($promotions[0]['threshold'] ?? 0) . '件' . $this->computedDiscount($promotions[0]['discount'] ?? 0, 10) . '折';
- break;
- }
- $desc[] = '买' . floatval($promotions[0]['threshold'] ?? 0) . '件商品,其中一件享' . $this->computedDiscount($promotions[0]['discount'] ?? 0, 10) . '折优惠';
- break;
- case 3:
- $title = '满减满折';
- foreach ($promotions as $p) {
- if ($promotions_cate == 2) {
- $give = '每满' . floatval($p['threshold'] ?? 0);
- } else {
- $give = '满' . floatval($p['threshold'] ?? 0);
- }
- $give .= $p['threshold_type'] == 1 ? '元' : '件';
- $give .= $p['discount_type'] == 1 ? ('减' . floatval($p['discount'] ?? 0) . '元') : '打' . $this->computedDiscount($p['discount'] ?? 0, 10) . '折';
- $desc[] = $give;
- }
- break;
- case 4:
- $title = '满送活动';
- foreach ($promotions as $p) {
- if ($promotions_cate == 2) {
- $base = '每满' . floatval($p['threshold'] ?? 0);
- } else {
- $base = '满' . floatval($p['threshold'] ?? 0);
- }
- $base .= $p['threshold_type'] == 1 ? '元送' : '件送';
- if ($p['give_integral']) {
- $desc[] = $base . floatval($p['give_integral'] ?? 0) . '积分';
- }
- if ($p['give_coupon_id']) {
- $desc[] = $base . '优惠券';
- }
- if ($p['give_product_id']) {
- $desc[] = $base . '赠品';
- }
- }
- break;
- default:
- break;
- }
- }
- return [$title, $desc];
- }
- /**
- * 返回目前进行中的活动ids
- * @param array $promotions_type
- * @param string $field
- * @return array
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getAllShowActivityIds(array $promotions_type = [], string $field = 'id')
- {
- $where = ['type' => 1, 'store_id' => 0, 'pid' => 0, 'is_del' => 0, 'status' => 1, 'promotionsTime' => true];
- if ($promotions_type) $where['promotions_type'] = $promotions_type;
- $promotions = $this->dao->getList($where, $field);
- $ids = [];
- if ($promotions) {
- if ($field == 'id') {
- $ids = array_column($promotions, 'id');
- } else {
- $ids = $promotions;
- }
- }
- return $ids;
- }
- /**
- * 获取商品所属活动
- * @param array $productIds
- * @param array $promotions_type
- * @param string $field
- * @param array $with
- * @param string $group
- * @return array
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getProductsPromotions(array $productIds, array $promotions_type = [], string $field = '*', array $with = [], string $group = '', int $store_id = 0)
- {
- if (!$productIds) {
- return [[], []];
- }
- $promotionsIds = $this->getAllShowActivityIds($promotions_type, 'id,promotions_type,product_partake_type,applicable_type,applicable_store_id');
- if (!$promotionsIds) {
- return [[], []];
- }
- $ids = [];
- $productArr = [];
- /** @var StoreProductRelationServices $productRelationServices */
- $productRelationServices = app()->make(StoreProductRelationServices::class);
- foreach ($productIds as $productId) {
- $productArr[$productId] = $productRelationServices->getProductRelationCache((int)$productId, [2, 3]);
- }
- /** @var StorePromotionsAuxiliaryServices $promotionsAuxiliaryServices */
- $promotionsAuxiliaryServices = app()->make(StorePromotionsAuxiliaryServices::class);
- $preType = [];
- foreach ($promotionsIds as $info) {
- $pid = (int)$info['id'];
- $applicable_store_id = is_array($info['applicable_store_id']) ? $info['applicable_store_id'] : explode(',', $info['applicable_store_id']);
- //活动不适用该门店
- if ($store_id && ($info['applicable_type'] == 0 || ($info['applicable_type'] == 2 && !in_array($store_id, $applicable_store_id)))) {
- continue;
- }
- if ($group && in_array($info['promotions_type'], $preType)) {
- continue;
- }
- if ($info['product_partake_type'] == 1) {//所有商品
- $ids[] = $pid;
- $preType[] = $info['promotions_type'];
- } else {
- $promotionsAuxiliaryData = $promotionsAuxiliaryServices->getPromotionsAuxiliaryCache($pid);
- if ($info['product_partake_type'] == 2) {
- if (array_intersect($promotionsAuxiliaryData, $productIds)) {
- $ids[] = $pid;
- $preType[] = $info['promotions_type'];
- }
- } else {
- foreach ($productArr as $productInfo) {
- $data = [];
- switch ($info['product_partake_type']) {
- case 4://品牌
- $data = $productInfo[2] ?? [];
- break;
- case 5://商品标签
- $data = $productInfo[3] ?? [];
- break;
- }
- if (array_intersect($promotionsAuxiliaryData, $data)) {//一个商品满足活动
- $ids[] = $pid;
- $preType[] = $info['promotions_type'];
- break;
- }
- }
- }
- }
- }
- $ids = array_unique($ids);
- $result = [];
- if ($ids) {
- $order = 'promotions_type asc,update_time desc';
- $promotions = $this->dao->getList(['ids' => $ids], $field, 0, 0, $with, $order);
- if ($promotions) {
- $data = $this->promotionsData;
- $data['giveCoupon'] = [];
- $data['giveProducts'] = [];
- foreach ($promotions as &$item) {
- if (!isset($item['promotions'])) {
- $item['promotions'] = [];
- }
- $first = array_merge($data, array_intersect_key($item, $data));
- array_unshift($item['promotions'], $first);
- $item['promotions'] = $this->handelPromotions($item['promotions']);
- $result[] = $item;
- }
- }
- }
- return [$result, $productArr];
- }
- /**
- * 获取商品所有优惠活动 所属活动详情
- * @param array $productIds
- * @param string $field
- * @param array $with
- * @param array $promotions_type
- * @param string $group
- * @param int $store_id
- * @return array
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getProductsPromotionsDetail(array $productIds, string $field = '*', array $with = [], array $promotions_type = [], string $group = '', int $store_id = 0)
- {
- $productDetails = [];
- $promotionsDetails = [];
- $promotions = [];
- if ($productIds) {
- /** @var StoreProductServices $productServices */
- $productServices = app()->make(StoreProductServices::class);
- $newProductIds = $productServices->getColumn([['id', 'in', $productIds]], 'id,pid,type,relation_id', 'id');
- //处理门店商品活动
- $newIds = [];
- if ($newProductIds) {
- foreach ($newProductIds as $item) {
- //门店自营商品 不参与活动
- if ($item['type'] == 1) {
- if ($item['pid']) {//平台共享到门店商品
- $newIds[] = $item['pid'];
- }
- } else {
- $newIds[] = $item['id'];
- }
- }
- }
- [$promotions, $productRelation] = $this->getProductsPromotions($newIds, $promotions_type, $field, $with, $group);
- if ($promotions) {
- /** @var StorePromotionsAuxiliaryServices $promotionsAuxiliaryServices */
- $promotionsAuxiliaryServices = app()->make(StorePromotionsAuxiliaryServices::class);
- foreach ($promotions as $info) {
- $id = (int)$info['id'];
- $promotionsAuxiliaryData = $promotionsAuxiliaryServices->getPromotionsAuxiliaryCache($id);
- $applicable_store_id = $info['applicable_store_id'] ? (is_string($info['applicable_store_id']) ? explode(',', $info['applicable_store_id']) : $info['applicable_store_id']) : [];
- foreach ($productIds as $productId) {
- $newProductId = $productId;
- $detail = $newProductIds[$productId] ?? [];
- if (!$detail) continue;
- if ($detail['type'] == 1) {//门店商品
- if ($detail['pid']) {//平台共享到门店商品
- $newProductId = $detail['pid'];
- } else {//门店自营商品 不参与活动
- continue;
- }
- $product_store_id = $detail['relation_id'];
- } else {//平台、供应商商品 存在在门店购买情况 需要验证
- $product_store_id = $store_id;
- }
- //活动不适用该门店
- if ($product_store_id && ($info['applicable_type'] == 0 || ($info['applicable_type'] == 2 && !in_array($product_store_id, $applicable_store_id)))) {
- continue;
- }
- $products = $info['products'] ?? [];
- $pIds = $products ? array_unique(array_column($products, 'product_id')) : [];
- switch ($info['product_partake_type']) {
- case 1://全部商品
- $productDetails[$productId][] = $id;
- $promotionsDetails[$id][] = $productId;
- break;
- case 2://选中商品参与
- if (in_array($newProductId, $pIds)) {
- $productDetails[$productId][] = $id;
- $promotionsDetails[$id][] = $productId;
- }
- break;
- case 3://选中商品不参与
- $products = $info['products'] ?? [];
- if ($products) $products = array_combine(array_column($products, 'product_id'), $products);
- if (!in_array($newProductId, $pIds) || (isset($products[$newProductId]['is_all']) && $products[$newProductId]['is_all'] == 0)) {
- $productDetails[$productId][] = $id;
- $promotionsDetails[$id][] = $productId;
- }
- break;
- case 4://品牌
- $data = $productRelation[$newProductId][2] ?? [];
- if (array_intersect($promotionsAuxiliaryData, $data)) {//一个商品满足活动
- $productDetails[$productId][] = $id;
- $promotionsDetails[$id][] = $productId;
- }
- break;
- case 5://商品标签
- $data = $productRelation[$newProductId][3] ?? [];
- if (array_intersect($promotionsAuxiliaryData, $data)) {//一个商品满足活动
- $productDetails[$productId][] = $id;
- $promotionsDetails[$id][] = $productId;
- }
- break;
- }
- }
- }
- }
- }
- return [$promotions, $productDetails, $promotionsDetails];
- }
- /**
- * 检测活动内容,格式数据
- * @param int $type
- * @param array $data
- * @return array
- */
- public function checkPromotions(int $type, array $data)
- {
- if (!$data) {
- throw new AdminException('请添加活动优惠内容');
- }
- $data = array_merge($this->promotionsData, array_intersect_key($data, $this->promotionsData));
- switch ($type) {
- case 1:
- case 2:
- $data['promotions_cate'] = 1;
- $data['discount_type'] = 2;
- $data['give_coupon_id'] = $data['give_product_id'] = [];
- if ($type == 2) {
- $data['threshold_type'] = 2;
- if (!$data['threshold']) {
- throw new AdminException('请输入打折门槛');
- }
- }
- if ($data['discount'] === '') {
- throw new AdminException('请添加折扣');
- }
- if ($data['discount'] < 0 || $data['discount'] > 100) {
- throw new AdminException('折扣必须为0~99数字');
- }
- break;
- case 3:
- $data['give_coupon_id'] = $data['give_product_id'] = [];
- if (!$data['threshold']) {
- throw new AdminException('请输入优惠门槛');
- }
- if ($data['discount'] === '') {
- throw new AdminException($data['discount_type'] == 1 ? '请输入优惠金额' : '请输入打折折扣');
- }
- if ($data['discount_type'] == 2 && ($data['discount'] < 0 || $data['discount'] > 100)) {
- throw new AdminException('折扣必须为0~99数字');
- }
- break;
- case 4:
- if (!$data['threshold']) {
- throw new AdminException('请输入优惠门槛');
- }
- if (!$data['give_integral'] && !$data['give_coupon_id'] && !$data['give_product_id']) {
- throw new AdminException('请至少选择一项赠送内容');
- }
- if ($data['give_coupon_id']) {
- $couponsIds = array_column($data['give_coupon_id'], 'give_coupon_id');
- $giveCoupon = array_combine($couponsIds, $data['give_coupon_id']);
- /** @var StoreCouponIssueServices $storeCouponServices */
- $storeCouponServices = app()->make(StoreCouponIssueServices::class);
- $coupons = $storeCouponServices->getValidGiveCoupons($couponsIds, 'id,is_permanent,remain_count');
- if (!$coupons || count($coupons) != count($couponsIds)) {
- throw new AdminException('优惠券已失效请重新选择');
- }
- foreach ($coupons as $coupon) {
- if (!isset($giveCoupon[$coupon['id']]['give_coupon_num']) || !$giveCoupon[$coupon['id']]['give_coupon_num']) {
- throw new AdminException('请输入赠送优惠券数量');
- }
- if ($coupon['is_permanent'] == 0 && $coupon['remain_count'] < $giveCoupon[$coupon['id']]['give_coupon_num']) {
- throw new AdminException('赠送优惠券数量不能超出优惠券限量');
- }
- }
- }
- if ($data['give_product_id']) {
- $productIds = array_column($data['give_product_id'], 'give_product_id');
- $giveProduct = array_combine($productIds, $data['give_product_id']);
- /** @var StoreProductServices $storeProductServices */
- $storeProductServices = app()->make(StoreProductServices::class);
- $products = $storeProductServices->getSearchList(['ids' => $productIds], 0, 0, ['id,stock']);
- if (!$products || count($products) != count(array_unique($productIds))) {
- throw new AdminException('商品已失效请重新选择');
- }
- foreach ($products as $product) {
- if (!isset($giveProduct[$product['id']]['give_product_num']) || !$giveProduct[$product['id']]['give_product_num']) {
- throw new AdminException('请输入赠送商品数量');
- }
- if ($product['stock'] < $giveProduct[$product['id']]['give_product_num']) {
- throw new AdminException('赠送商品数量不能超出商品库存');
- }
- }
- }
- break;
- default:
- throw new AdminException('暂不支持该类型优惠活动');
- }
- return $data;
- }
- /**获取门店适用的活动
- * @param $where
- * @param $storeId
- * @return array
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getgetPromotionListInfo($where, $storeId)
- {
- $list = $this->dao->getList($where);
- $listInfo = [];
- foreach ($list as $key => &$info) {
- if ($info['applicable_type'] == 2) {
- $store_ids = is_array($info['applicable_store_id']) ? $info['applicable_store_id'] : explode(',', $info['applicable_store_id']);
- if (!in_array($storeId, $store_ids)) continue;
- }
- if ($info['start_time'])
- $start_time = $info['promotions_type'] == 1 ? date('Y-m-d H:i', (int)$info['start_time']) : date('Y-m-d', (int)$info['start_time']);
- if ($info['stop_time'])
- $stop_time = $info['promotions_type'] == 1 ? date('Y-m-d H:i', (int)$info['stop_time']) : date('Y-m-d', (int)$info['stop_time']);
- if (isset($start_time) && isset($stop_time))
- $info['section_time'] = [$start_time, $stop_time];
- else
- $info['section_time'] = [];
- unset($info['start_time'], $info['stop_time']);
- $info['is_label'] = $info['label_id'] ? 1 : 0;
- $info['threshold'] = floatval($info['threshold']);
- $info['discount'] = floatval($info['discount']);
- $info['give_integral'] = intval($info['give_integral']);
- $info['is_overlay'] = $info['overlay'] ? 1 : 0;
- $info['promotions'] = $info['promotions'] ?? [];
- $data = $this->promotionsData;
- $first = array_merge($data, array_intersect_key($info, $data));
- array_unshift($info['promotions'], $first);
- $info['promotions'] = $this->handelPromotions($info['promotions']);
- $listInfo[] = $info;
- }
- return $listInfo;
- }
- /**
- * 获取列表
- * @param array $where
- * @return array
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function systemPage(array $where)
- {
- [$page, $limit] = $this->getPageValue();
- $list = $this->dao->getList($where, '*', $page, $limit, ['giveProducts' => function ($query) {
- $query->field('promotions_id,product_id,limit_num,surplus_num')->with(['productInfo' => function ($query) {
- $query->field('id,store_name');
- }]);
- }, 'giveCoupon' => function ($query) {
- $query->field('promotions_id,coupon_id,limit_num,surplus_num')->with(['coupon' => function ($query) {
- $query->field('id,type,coupon_type,coupon_title,coupon_price,use_min_price');
- }]);
- }, 'promotions' => function ($query) {
- $query->field('id,pid,promotions_type,promotions_cate,threshold_type,threshold,discount_type,n_piece_n_discount,discount,give_integral,give_coupon_id,give_product_id,give_product_unique')->with(['giveProducts' => function ($query) {
- $query->field('promotions_id, product_id,limit_num,surplus_num')->with(['productInfo' => function ($query) {
- $query->field('id,store_name');
- }]);
- }, 'giveCoupon' => function ($query) {
- $query->field('promotions_id, coupon_id,limit_num,surplus_num')->with(['coupon' => function ($query) {
- $query->field('id,type,coupon_type,coupon_title,coupon_price,use_min_price');
- }]);
- }]);
- }]);
- $count = 0;
- if ($list) {
- $count = $this->dao->count($where);
- $data = $this->promotionsData;
- $data['giveCoupon'] = [];
- $data['giveProducts'] = [];
- /** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
- $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
- /** @var StoreOrderServices $storeOrderServices */
- $storeOrderServices = app()->make(StoreOrderServices::class);
- /** @var StoreProductServices $storeProductServices */
- $storeProductServices = app()->make(StoreProductServices::class);
- /** @var StoreProductRelationServices $storeProductRelationServices */
- $storeProductRelationServices = app()->make(StoreProductRelationServices::class);
- /** @var StorePromotionsAuxiliaryServices $promotionsAuxiliaryServices */
- $promotionsAuxiliaryServices = app()->make(StorePromotionsAuxiliaryServices::class);
- $getPromotions = function ($cartList, $oids) {
- $promotionsPrice = 0;
- $uids = [];
- $oldUids = [];
- $ids = [];
- foreach ($cartList as $key => $cart) {
- if (!in_array($cart['oid'], $oids)) continue;
- $info = is_string($cart['cart_info']) ? json_decode($cart['cart_info'], true) : $cart['cart_info'];
- $promotionsPrice = bcadd((string)$promotionsPrice, (string)bcmul((string)($info['promotions_true_price'] ?? 0), (string)$info['cart_num'], 2), 2);
- if (!in_array($cart['oid'], $ids)) {
- $ids[] = $cart['oid'];
- if (!in_array($cart['uid'], $uids)) {
- $uids[] = $cart['uid'];
- } else {
- $oldUids[] = $cart['uid'];
- }
- }
- }
- return [$promotionsPrice, $uids, $oldUids];
- };
- foreach ($list as &$item) {
- if ($item['status']) {
- if ($item['start_time'] > time())
- $item['start_name'] = '未开始';
- else if (bcadd((string)$item['stop_time'], '86400') < time())
- $item['start_name'] = '已结束';
- else if (bcadd((string)$item['stop_time'], '86400') > time() && $item['start_time'] < time()) {
- $item['start_name'] = '进行中';
- }
- } else $item['start_name'] = '已结束';
- $end_time = $item['stop_time'] ? date('Y/m/d', (int)$item['stop_time']) : '';
- $item['_stop_time'] = $end_time;
- $item['stop_status'] = $item['stop_time'] + 86400 < time() ? 1 : 0;
- $item['sum_pay_price'] = 0.00;
- $item['sum_promotions_price'] = 0.00;
- $item['sum_order'] = 0;
- $item['sum_user'] = 0;
- $item['old_user'] = 0;
- $item['new_user'] = 0;
- $pids = array_merge([$item['id']], array_column($item['promotions'], 'id'));
- $cartInfos = $storeOrderCartInfoServices->getColumn(['promotions_id' => $pids], 'oid,uid,cart_info', 'id', true);
- if ($cartInfos) {
- $oids = $storeOrderServices->getColumn(['id' => array_unique(array_column($cartInfos, 'oid')), 'is_del' => 0, 'pid' => 0, 'is_system_del' => 0, 'refund_status' => [0, 3]], 'id', '');
- $item['sum_pay_price'] = $storeOrderServices->sum(['id' => $oids, 'is_del' => 0, 'pid' => 0, 'is_system_del' => 0, 'refund_status' => [0, 3]], 'pay_price', true);
- [$promotionsPrice, $uids, $oldUids] = $getPromotions($cartInfos, $oids);
- $item['sum_promotions_price'] = $promotionsPrice;
- $item['sum_order'] = $storeOrderServices->count(['id' => $oids, 'is_del' => 0, 'pid' => 0, 'is_system_del' => 0, 'refund_status' => [0, 3]]);
- $item['sum_user'] = count($uids);
- $item['old_user'] = count(array_unique($oldUids));
- $item['new_user'] = bcsub((string)$item['sum_user'], (string)$item['old_user'], 0);
- }
- $first = array_merge($data, array_intersect_key($item, $data));
- array_unshift($item['promotions'], $first);
- $item['promotions'] = $this->handelPromotions($item['promotions']);
- $promotionsAuxiliaryData = $promotionsAuxiliaryServices->getPromotionsAuxiliaryCache($item['id']);
- switch ($item['product_partake_type']) {
- case 1://所有商品
- $item['product_count'] = $storeProductServices->count(['is_show' => 1, 'is_del' => 0, 'type' => [0, 2], 'is_verify' => 1]);
- break;
- case 2://选中商品参与
- $product_ids = $promotionsAuxiliaryData;
- $item['product_count'] = $product_ids ? $storeProductServices->count(['is_show' => 1, 'is_del' => 0, 'id' => $product_ids, 'is_verify' => 1]) : 0;
- break;
- case 3:
- $item['product_count'] = 0;
- break;
- case 4://品牌
- $product_ids = $promotionsAuxiliaryData ? $storeProductRelationServices->getIdsByWhere(['type' => 2, 'relation_id' => $promotionsAuxiliaryData]) : [];
- $item['product_count'] = $product_ids ? $storeProductServices->count(['is_show' => 1, 'is_del' => 0, 'id' => $product_ids, 'type' => [0, 2], 'is_verify' => 1]) : 0;
- break;
- case 5://商品标签
- $product_ids = $promotionsAuxiliaryData ? $storeProductRelationServices->getIdsByWhere(['type' => 3, 'relation_id' => $promotionsAuxiliaryData]) : [];
- $item['product_count'] = $product_ids ? $storeProductServices->count(['is_show' => 1, 'is_del' => 0, 'id' => $product_ids, 'type' => [0, 2], 'is_verify' => 1]) : 0;
- break;
- }
- }
- }
- return compact('list', 'count');
- }
- /**
- * 获取信息
- * @param int $id
- * @return array|\think\Model|null
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getInfo(int $id)
- {
- $info = $this->dao->get($id, ['*'], ['products' => function ($query) {
- $query->field('promotions_id,product_id,unique')->with(['productInfo', 'attrValue']);
- }, 'brands' => function ($query) {
- $query->field('promotions_id,brand_id')->with(['brandInfo' => function ($q) {
- $q->field('id,brand_name');
- }]);
- }, 'productLabels' => function ($query) {
- $query->field('promotions_id,store_label_id')->with(['productLabelInfo' => function ($q) {
- $q->field('id,label_name');
- }]);
- }, 'giveProducts' => function ($query) {
- $query->field('type,promotions_id,product_id,limit_num,unique')->with(['productInfo' => function ($q) {
- $q->field('id,store_name');
- }, 'giveAttrValue']);
- }, 'giveCoupon' => function ($query) {
- $query->field('type,promotions_id,coupon_id,limit_num')->with(['coupon']);
- }, 'promotions' => function ($query) {
- $query->field('id,pid,promotions_type,promotions_cate,threshold_type,threshold,discount_type,n_piece_n_discount,discount,give_integral,give_coupon_id,give_product_id,give_product_unique')->with(['giveProducts' => function ($query) {
- $query->field('type,promotions_id, product_id,limit_num,unique')->with(['productInfo' => function ($q) {
- $q->field('id,store_name');
- }, 'giveAttrValue']);
- }, 'giveCoupon' => function ($query) {
- $query->field('type,promotions_id, coupon_id,limit_num')->with(['coupon']);
- }]);
- }]);
- if (!$info) {
- throw new AdminException('数据不存在');
- }
- $info = $info->toArray();
- if ($info['start_time'])
- $start_time = $info['promotions_type'] == 1 ? date('Y-m-d H:i', (int)$info['start_time']) : date('Y-m-d', (int)$info['start_time']);
- if ($info['stop_time'])
- $stop_time = $info['promotions_type'] == 1 ? date('Y-m-d H:i', (int)$info['stop_time']) : date('Y-m-d', (int)$info['stop_time']);
- if (isset($start_time) && isset($stop_time))
- $info['section_time'] = [$start_time, $stop_time];
- else
- $info['section_time'] = [];
- unset($info['start_time'], $info['stop_time']);
- $info['is_label'] = $info['label_id'] ? 1 : 0;
- if ($info['is_label']) {
- $label_id = is_array($info['label_id']) ? $info['label_id'] : explode(',', $info['label_id']);
- /** @var UserLabelServices $userLabelServices */
- $userLabelServices = app()->make(UserLabelServices::class);
- $info['label_id'] = $userLabelServices->getLabelList(['ids' => $label_id], ['id', 'label_name']);
- } else {
- $info['label_id'] = [];
- }
- $info['threshold'] = floatval($info['threshold']);
- $info['discount'] = floatval($info['discount']);
- $info['give_integral'] = intval($info['give_integral']);
- $info['is_overlay'] = $info['overlay'] ? 1 : 0;
- $info['promotions'] = $info['promotions'] ?? [];
- $info['products'] = $info['products'] ?? [];
- $info['giveCoupon'] = $info['giveCoupon'] ?? [];
- $info['giveProducts'] = $info['giveProducts'] ?? [];
- if ($info['products']) {
- /** @var StoreProductLabelServices $storeProductLabelServices */
- $storeProductLabelServices = app()->make(StoreProductLabelServices::class);
- $products = [];
- foreach ($info['products'] as &$item) {
- $product = is_object($item) ? $item->toArray() : $item;
- $product = array_merge($product, $product['productInfo'] ?? []);
- $product['store_label'] = '';
- if (isset($product['store_label_id']) && $product['store_label_id']) {
- $storeLabelList = $storeProductLabelServices->getColumn([['relation_id', '=', 0], ['type', '=', 0], ['id', 'IN', $product['store_label_id']]], 'id,label_name');
- $product['store_label'] = $storeLabelList ? implode(',', array_column($storeLabelList, 'label_name')) : '';
- }
- $unique = is_string($product['unique']) ? explode(',', $product['unique']) : $product['unique'];
- foreach ($product['attrValue'] as $key => $value) {
- if (!in_array($value['unique'], $unique)) {
- unset($product['attrValue'][$key]);
- }
- }
- $product['attrValue'] = array_merge($product['attrValue']);
- unset($product['productInfo']);
- $products[] = $product;
- }
- if ($products) {
- $cateIds = implode(',', array_column($products, 'cate_id'));
- /** @var StoreProductCategoryServices $categoryService */
- $categoryService = app()->make(StoreProductCategoryServices::class);
- $cateList = $categoryService->getCateParentAndChildName($cateIds);
- foreach ($products as $key => &$item) {
- $item['cate_name'] = '';
- if (isset($item['cate_id']) && $item['cate_id']) {
- $cate_ids = explode(',', $item['cate_id']);
- $cate_name = $categoryService->getCateName($cate_ids, $cateList);
- if ($cate_name) {
- $item['cate_name'] = is_array($cate_name) ? implode(',', $cate_name) : '';
- }
- }
- foreach ($item['attrValue'] as $key => &$value) {
- $value['store_label'] = $item['store_label'] ?? '';
- $value['cate_name'] = $item['cate_name'] ?? '';
- }
- }
- }
- unset($info['products']);
- $info['products'] = $products;
- }
- $data = $this->promotionsData;
- $data['giveCoupon'] = [];
- $data['giveProducts'] = [];
- $first = array_merge($data, array_intersect_key($info, $data));
- array_unshift($info['promotions'], $first);
- $info['promotions'] = $this->handelPromotions($info['promotions']);
- $info['brand_id'] = isset($info['brands']) && $info['brands'] ? array_column($info['brands'], 'brand_id') : [];
- $info['store_label_id'] = [];
- if (isset($info['productLabels']) && $info['productLabels']) {
- foreach ($info['productLabels'] as $label) {
- if (isset($label['productLabelInfo']) && $label['productLabelInfo']) {
- $info['store_label_id'][] = $label['productLabelInfo'];
- }
- }
- }
- //适用门店
- $info['stores'] = [];
- if (isset($info['applicable_type']) && ($info['applicable_type'] == 1 || ($info['applicable_type'] == 2 && isset($info['applicable_store_id']) && $info['applicable_store_id']))) {//查询门店信息
- $where = ['is_del' => 0];
- if ($info['applicable_type'] == 2) {
- $store_ids = is_array($info['applicable_store_id']) ? $info['applicable_store_id'] : explode(',', $info['applicable_store_id']);
- $where['id'] = $store_ids;
- }
- $field = ['id', 'cate_id', 'name', 'phone', 'address', 'detailed_address', 'image', 'is_show', 'day_time', 'day_start', 'day_end'];
- /** @var SystemStoreServices $storeServices */
- $storeServices = app()->make(SystemStoreServices::class);
- $storeData = $storeServices->getStoreList($where, $field, '', '', 0, ['categoryName']);
- $info['stores'] = $storeData['list'] ?? [];
- }
- unset($info['brands'], $info['productLabels']);
- return $info;
- }
- /**
- * 处理阶梯优惠赠送商品、优惠券
- * @param array $promotions
- * @return array
- */
- public function handelPromotions(array $promotions)
- {
- if ($promotions) {
- foreach ($promotions as &$p) {
- $p['threshold'] = (float)$p['threshold'];
- $p['discount'] = (float)$p['discount'];
- if (isset($p['giveCoupon']) && $p['giveCoupon']) {
- $coupons = [];
- foreach ($p['giveCoupon'] as &$coupon) {
- $coupon = is_object($coupon) ? $coupon->toArray() : $coupon;
- $coupon = array_merge($coupon, $coupon['coupon'] ?? []);
- unset($coupon['coupon']);
- $coupons[] = $coupon;
- }
- unset($p['giveCoupon']);
- $p['giveCoupon'] = $coupons;
- }
- if (isset($p['giveProducts']) && $p['giveProducts']) {
- $products = [];
- foreach ($p['giveProducts'] as &$product) {
- $product = is_object($product) ? $product->toArray() : $product;
- $product = array_merge($product, $product['productInfo'] ?? []);
- $product = array_merge($product, $product['giveAttrValue'] ?? []);
- unset($product['productInfo'], $product['giveAttrValue']);
- $products[] = $product;
- }
- unset($p['giveProducts']);
- $p['giveProducts'] = $products;
- }
- }
- }
- return $promotions;
- }
- /**
- * 保存促销活动
- * @param int $id
- * @param array $data
- * @return bool
- */
- public function saveData(int $id, array $data)
- {
- if (!$data['section_time'] || count($data['section_time']) != 2) {
- throw new AdminException('请选择活动时间');
- }
- [$start_time, $end_time] = $data['section_time'];
- if (strtotime($end_time) < time()) {
- throw new AdminException('活动结束时间不能小于当前时间');
- }
- if ($id) {
- $info = $this->dao->get((int)$id);
- if (!$info) {
- throw new AdminException('数据不存在');
- }
- }
- $data['start_time'] = strtotime($start_time);
- $data['stop_time'] = $data['promotions_type'] == 1 ? strtotime($end_time) : strtotime($end_time) + 86399;
- $data['label_id'] = $data['label_id'] ? implode(',', $data['label_id']) : '';
- $data['overlay'] = $data['overlay'] ? implode(',', $data['overlay']) : '';
- $promotionsAuxiliaryData = [];
- switch ($data['product_partake_type']) {
- case 1://全部
- $data['product_id'] = [];
- break;
- case 2://指定ID参与
- case 3://指定ID不参与
- $promotionsAuxiliaryData = $productData = $data['product_id'];
- $productIds = $productData ? array_column($productData, 'product_id') : [];
- $data['product_id'] = $productIds ? implode(',', $productIds) : '';
- /** @var StoreProductServices $storeProductServices */
- $storeProductServices = app()->make(StoreProductServices::class);
- $count = $storeProductServices->count(['is_show' => 1, 'is_del' => 0, 'id' => $productIds]);
- $productCount = count(array_unique($productIds));
- if ($count != $productCount) {
- throw new AdminException('选择商品中有已下架或移入回收站');
- }
- break;
- case 4://指定品牌
- $data['brand_id'] = array_unique($data['brand_id']);
- /** @var StoreBrandServices $storeBrandServices */
- $storeBrandServices = app()->make(StoreBrandServices::class);
- $brandCount = $storeBrandServices->count(['is_show' => 1, 'is_del' => 0, 'id' => $data['brand_id']]);
- if (count(array_unique($data['brand_id'])) != $brandCount) {
- throw new AdminException('选择商品品牌中有已下架或删除的');
- }
- $promotionsAuxiliaryData['brand_id'] = $data['brand_id'];
- break;
- case 5://指定商品标签
- $data['store_label_id'] = array_unique($data['store_label_id']);
- /** @var StoreProductLabelServices $storeProductLabelServices */
- $storeProductLabelServices = app()->make(StoreProductLabelServices::class);
- $labelCount = $storeProductLabelServices->count(['id' => $data['store_label_id']]);
- if (count(array_unique($data['store_label_id'])) != $labelCount) {
- throw new ValidateException('选择商品标签中有已下架或删除的');
- }
- $promotionsAuxiliaryData['store_label_id'] = $data['store_label_id'];
- break;
- default:
- throw new ValidateException('暂不支持该类型商品');
- break;
- }
- $promotions = $data['promotions'];
- $threshold = -1;
- foreach ($promotions as &$value) {
- if ($threshold != -1 && $value['threshold'] <= $threshold) {
- throw new AdminException('优惠门槛只能递增(例如二级必须大于一级优惠)');
- }
- $threshold = $value['threshold'];
- $value = $this->checkPromotions((int)$data['promotions_type'], $value);
- $value['threshold_type'] = $data['threshold_type'];
- }
- [$title, $desc] = $this->getPromotionsDesc((int)$data['promotions_type'], (int)$data['promotions_cate'], $data['promotions_type'] == 1 ? array_merge($promotions, ['is_limit' => $data['is_limit'], 'limit_num' => $data['limit_num']]) : $promotions);
- $data['title'] = $title;
- $data['desc'] = implode(',', $desc);
- $first = array_shift($promotions);
- $giveCoupon = $first['give_coupon_id'] ?? [];
- $giveProduct = $first['give_product_id'] ?? [];
- unset($first['give_coupon_id'], $first['give_product_id']);
- $first['give_coupon_id'] = $giveCoupon ? implode(',', array_unique(array_column($giveCoupon, 'give_coupon_id'))) : '';
- $first['give_product_id'] = $giveProduct ? implode(',', array_unique(array_column($giveProduct, 'give_product_id'))) : '';
- $first['give_product_unique'] = $giveProduct ? implode(',', array_unique(array_column($giveProduct, 'unique'))) : '';
- $data = array_merge($data, $first);
- unset($data['section_time'], $data['promotions']);
- $this->transaction(function () use ($id, $data, $promotions, $promotionsAuxiliaryData, $giveCoupon, $giveProduct) {
- $time = time();
- $data['update_time'] = $time;
- if ($id) {
- $this->dao->update($id, $data);
- //删除之前阶梯数据
- $this->dao->delete(['pid' => $id]);
- } else {
- $data['add_time'] = $time;
- $res = $this->dao->save($data);
- $id = $res->id;
- }
- /** @var StorePromotionsAuxiliaryServices $storePromotionsAuxiliaryServices */
- $storePromotionsAuxiliaryServices = app()->make(StorePromotionsAuxiliaryServices::class);
- $storePromotionsAuxiliaryServices->savePromotionsRelation((int)$id, (int)$data['product_partake_type'], $promotionsAuxiliaryData, $giveCoupon, $giveProduct);
- if ($promotions) {
- foreach ($promotions as $item) {
- $giveCoupon = $item['give_coupon_id'] ?? [];
- $giveProduct = $item['give_product_id'] ?? [];
- unset($item['give_coupon_id'], $item['give_product_id']);
- $item['give_coupon_id'] = $giveCoupon ? implode(',', array_unique(array_column($giveCoupon, 'give_coupon_id'))) : '';
- $item['give_product_id'] = $giveProduct ? implode(',', array_unique(array_column($giveProduct, 'give_product_id'))) : '';
- $item['give_product_unique'] = $giveProduct ? implode(',', array_unique(array_column($giveProduct, 'unique'))) : '';
- $item['pid'] = $id;
- $item['promotions_type'] = (int)$data['promotions_type'];
- $item['promotions_cate'] = (int)$data['promotions_cate'];
- $item['add_time'] = $time;
- $res = $this->dao->save($item);
- $storePromotionsAuxiliaryServices->savePromotionsRelation((int)$res->id, (int)$data['product_partake_type'], $promotionsAuxiliaryData, $giveCoupon, $giveProduct);
- }
- }
- });
- return true;
- }
- /**
- * 验证购买商品规格是否在优惠活动适用商品选择规格中
- * @param array $productIds
- * @param array $cartList
- * @param array $promotions
- * @return array
- */
- public function checkProductCanUsePromotions(array $productIds, array $cartList, array $promotions)
- {
- $ids = $uniques = [];
- if (!$productIds || !$cartList || !$promotions) return [$ids, $uniques];
- $useProducts = $promotions['products'] ?? [];
- if ($useProducts) {
- $useProducts = array_combine(array_column($useProducts, 'product_id'), $useProducts);
- }
- foreach ($cartList as $cart) {
- if (!in_array($cart['product_id'], $productIds)) continue;
- $productUnique = $cart['product_attr_unique'] ?? '';
- $productInfo = $cart['productInfo'] ?? [];
- $product_id = $cart['product_id'] ?? 0;
- $useUniques = $useProducts[$product_id]['unique'] ?? [];
- if (!$productUnique || !$productInfo) continue;
- if ($productInfo['type'] == 1 && $productInfo['pid'] > 0) {//平台共享到门店商品 查询平台商品unique
- $unique = $this->getProductUnique($productUnique, (int)$productInfo['id'], (int)$productInfo['pid']);
- $productUnique = $unique ?: $productUnique;
- $useUniques = $useProducts[$productInfo['pid']]['unique'] ?? [];
- }
- if (in_array($promotions['product_partake_type'], [2, 3])) {
- if ($promotions['product_partake_type'] == 2) {
- $uniques[$product_id] = $useUniques;
- if (!in_array($productUnique, $useUniques)) {
- continue;
- }
- } else {
- $uniques[$product_id] = $useUniques;
- if (in_array($productUnique, $useUniques)) {
- continue;
- }
- }
- }
- $ids[] = $product_id;
- }
- return [$ids, $uniques];
- }
- /**
- * 检查优惠活动限量
- * @param StoreOrderCartInfoServices $storeOrderCartInfoServices
- * @param int $uid
- * @param int $id
- * @param array $productIds
- * @param array $promotions
- * @return array
- */
- public function checkPromotionsLimit(StoreOrderCartInfoServices $storeOrderCartInfoServices, int $uid, int $id, array $productIds, array $promotions)
- {
- if (!$productIds) {
- return [];
- }
- if ($uid && $promotions['promotions_type'] == 1 && $promotions['is_limit']) {//限时折扣 存在限量
- //获取包含子级获取ids
- $ids = array_unique(array_merge([$id], array_column($promotions['promotions'] ?? [], 'id')));
- $data = [];
- foreach ($productIds as $key => $product_id) {
- if ($storeOrderCartInfoServices->count(['uid' => $uid, 'product_id' => $product_id, 'promotions_id' => $ids]) < $promotions['limit_num']) {
- $data[] = $product_id;
- }
- }
- return $data;
- }
- return $productIds;
- }
- /**
- * 计算几个商品总金额 并返回商品信息
- * @param int $promotions_type
- * @param array $productIds
- * @param array $cartList
- * @param array $uniquesArr
- * @param int $product_partake_type
- * @param bool $isGive
- * @return array
- */
- protected function getPromotionsProductInfo(int $promotions_type, array $productIds, array $cartList, array $uniquesArr = [], int $product_partake_type = 1, bool $isGive = false)
- {
- $sumPrice = $sumCount = 0;
- $p = [];
- if (!$cartList || !$productIds) {
- return [$sumPrice, $sumCount, $p];
- }
- $productComputedArr = $this->getItem('productComputedArr', []);
- $computedArr = $this->getItem('computedArr', []);
- foreach ($cartList as $product) {
- if (!in_array($product['product_id'], $productIds)) continue;
- $cart_num = $product['cart_num'] ?? 1;
- $unique = $product['product_attr_unique'] ?? '';
- $product_id = $product['product_id'];
- $productInfo = $product['productInfo'] ?? [];
- if (!$unique || !$product_id || !$productInfo) continue;
- if (!$this->checkProductUnque($unique, $productInfo, $uniquesArr[$product_id] ?? [], $product_partake_type)) {
- continue;
- }
- if ($isGive) {
- $key = 'true_price';
- } else {
- if ($promotions_type == 1) {
- $key = 'price';
- } else {
- if (isset($productComputedArr[$product_id]['typeArr']) && in_array(1, $productComputedArr[$product_id]['typeArr'])) {
- $key = 'price';
- } else {
- $key = 'true_price';
- }
- }
- }
- if ($key == 'price') {
- $price = isset($product['productInfo']['attrInfo']['price']) ? $product['productInfo']['attrInfo']['price'] : ($product['productInfo']['price'] ?? 0);
- } else {
- $price = $product['truePrice'];
- }
- $isOverlay = $productComputedArr[$product_id]['is_overlay'] ?? false;
- if ($isOverlay && $computedArr) {
- foreach ($computedArr as $key => $computedDetail) {
- if (isset($computedDetail[$unique]['promotions_true_price'])) {
- $price = bcsub((string)$price, (string)$computedDetail[$unique]['promotions_true_price'], 2);
- }
- }
- }
- $product['price'] = floatval($price) > 0 ? $price : 0;
- $sumPrice = bcadd((string)$sumPrice, (string)bcmul((string)$price, (string)$cart_num, 2), 2);
- if ($isGive && isset($product['coupon_price'])) {
- $sumPrice = bcsub((string)$sumPrice, (string)$product['coupon_price'], 2);
- }
- $sumCount = bcadd((string)$sumCount, (string)$cart_num, 0);
- $p[] = $product;
- }
- return [$sumPrice, $sumCount, $p];
- }
- /**
- * 验证是否叠加其他活动
- * @param int $promotions_type
- * @param array $overlay
- * @return bool
- */
- public function checkOverlay(int $promotions_type, array $overlay)
- {
- $data = [1, 2, 3];
- return boolval(array_intersect($overlay, array_diff($data, [$promotions_type])));
- }
- /**
- * 获取商品活动是否叠加计算
- * @param array $promotionsList
- * @param array $productDetails
- * @param array $promotionsDetail
- * @return array[]
- */
- public function getProductComputedPromotions(array $promotionsList, array $productDetails, array $promotionsDetail)
- {
- $productArr = [];
- $promotionsArr = [];
- $productComputedArr = [];
- if (!$promotionsList) {
- return [$productArr, $promotionsArr, $productComputedArr];
- }
- //验证是否能叠加使用
- foreach ($productDetails as $product_id => $promotionsIds) {
- $pIds = [];
- $overlayPIds = [];
- $unOverlayPIds = [];
- $prevType = [];
- $preOverlay = [];
- $isOverlay = true;
- foreach ($promotionsIds as $id) {
- $promotions = $promotionsList[$id] ?? [];
- if (!$promotions) continue;
- $overlay = is_string($promotions['overlay']) ? explode(',', $promotions['overlay']) : $promotions['overlay'];
- //同一个商品 同一类型活动取最新一个
- if (!in_array($promotions['promotions_type'], $prevType)) {
- if (!$prevType) {
- $overlayPIds[] = $unOverlayPIds[] = $id;
- $prevType[] = $promotions['promotions_type'];
- $preOverlay[$promotions['promotions_type']] = $overlay;
- } else {
- //有限时折扣
- if (isset($preOverlay[1]) && !$this->checkOverlay(1, $preOverlay[1])) {
- if ($promotions['promotions_type'] == 4) {
- $prevType[] = $promotions['promotions_type'];
- $preOverlay[$promotions['promotions_type']] = $overlay;
- $unOverlayPIds[] = $id;
- }
- } else {
- if ($promotions['promotions_type'] == 4) {
- $prevType[] = $promotions['promotions_type'];
- $preOverlay[$promotions['promotions_type']] = $overlay;
- $overlayPIds[] = $id;
- $unOverlayPIds[] = $id;
- } else {
- foreach ($preOverlay as $key => $value) {
- if (in_array($key, $overlay) && in_array($promotions['promotions_type'], $value)) {
- $overlayPIds[] = $id;
- } else {
- $unOverlayPIds[] = $id;
- }
- }
- }
- $prevType[] = $promotions['promotions_type'];
- $preOverlay[$promotions['promotions_type']] = $overlay;
- }
- }
- }
- }
- $overlayPIds = array_unique($overlayPIds);
- $unOverlayPIds = array_unique($unOverlayPIds);
- if (count($overlayPIds) > 1) {
- $isOverlay = true;
- $pIds = $overlayPIds;
- } else if (count($overlayPIds) == 1 && count($unOverlayPIds) == 1) {
- $isOverlay = false;
- $pIds = $overlayPIds;
- } else {
- $isOverlay = false;
- $pIds = $unOverlayPIds;
- }
- $productComputedArr[$product_id]['is_overlay'] = $pIds && $isOverlay;
- $typeArr = [];
- //重新整理商品关联ids数据
- foreach ($pIds as $id) {
- $promotions = $promotionsList[$id] ?? [];
- if ($promotions) {
- $productArr[$product_id][] = $id;
- $typeArr[] = $promotions['promotions_type'];
- }
- }
- //存在限时折扣 不叠加
- if (count($typeArr) > 1 && in_array(1, $typeArr) && !$productComputedArr[$product_id]['is_overlay']) {
- $typeArr = [];
- $productArr[$product_id] = [];
- foreach ($pIds as $id) {
- $promotions = $promotionsList[$id] ?? [];
- if ($promotions) {
- if (in_array($promotions['promotions_type'], [1, 4])) {
- $productArr[$product_id][] = $id;
- $typeArr[] = $promotions['promotions_type'];
- }
- }
- }
- }
- $productComputedArr[$product_id]['typeArr'] = $typeArr;
- }
- //重新整理活动关联商品ids数据
- foreach ($promotionsDetail as $promotions_id => $productIds) {
- foreach ($productIds as $pid) {
- $pIds = $productArr[$pid] ?? [];
- if ($pIds && in_array($promotions_id, $pIds)) {
- $promotionsArr[$promotions_id][] = $pid;
- }
- }
- }
- return [$productArr, $promotionsArr, $productComputedArr];
- }
- /**
- * 组合使用的优惠活动详情
- * @param int $uid
- * @param int $store_id
- * @param array $usePromotionsIds
- * @param array $promotionsArr
- * @param array $computedArr
- * @return array
- */
- public function getUsePromotiosnInfo(int $uid, int $store_id, array $usePromotionsIds, array $promotionsArr, array $computedArr)
- {
- $usePromotions = [];
- if (!$usePromotionsIds || !$promotionsArr || !$computedArr) {
- return $usePromotions;
- }
- $giveCoupon = $giveProduct = $giveCartList = [];
- $giveIntegral = 0;
- foreach ($usePromotionsIds as $id) {
- $promotionsInfo = $promotionsArr[$id] ?? [];
- if (!$promotionsInfo) continue;
- $details = $computedArr[$id] ?? [];
- $promotionsInfo['details'] = $details;
- $promotionsInfo = array_merge($promotionsInfo, $details['give'] ?? []);
- $promotionsInfo['is_valid'] = $details['is_valid'] ?? 0;
- $promotionsInfo['reach_threshold'] = $details['reach_threshold'] ?? 0;
- $promotionsInfo['sum_promotions_price'] = $details['sum_promotions_price'] ?? 0;
- $promotionsInfo['differ_threshold'] = $details['differ_threshold'] ?? 0;//下一级优惠差多少元|件
- $promotionsInfo['differ_price'] = $details['differ_price'] ?? 0;//下一级优惠金额
- $promotionsInfo['differ_discount'] = $details['differ_discount'] ?? 0;//下一级享受折扣
- $giveProductIds = $giveCart = [];
- if (isset($promotionsInfo['give_product']) && $promotionsInfo['give_product']) {
- $giveCart = $this->createGiveProductCart($uid, (int)$id, $promotionsInfo['give_product'], $promotionsInfo, $store_id);
- if ($giveCart) {
- $giveProductIds = array_column($giveProductIds, 'product_id');
- $giveCartList = array_merge($giveCartList, $giveCart);
- }
- }
- $promotionsInfo['product_ids'] = $promotionsDetail[$id] ?? [];
- $promotionsInfo['product_ids'] = array_merge($promotionsInfo['product_ids'], $giveProductIds);
- $promotionsInfo['give_product'] = $giveProductIds;
- $giveCoupon = array_merge($giveCoupon, $promotionsInfo['give_coupon'] ?? []);
- $giveProduct = array_merge($giveProduct, $promotionsInfo['give_product'] ?? []);
- $giveIntegral = bcadd((string)$giveIntegral, (string)($promotionsInfo['give_integral'] ?? 0), 0);
- $usePromotions[] = $promotionsInfo;
- }
- return [$usePromotions, $giveIntegral, $giveCoupon, $giveCartList];
- }
- /**
- * 根据门店|平台商品 unique 获取另一端商品unique
- * @param string $unique
- * @param int $product_id
- * @param int $type
- * @return false|string
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getProductUnique(string $unique, int $product_id, int $new_product_id, int $type = 0)
- {
- /** @var StoreProductAttrValueServices $skuValueServices */
- $skuValueServices = app()->make(StoreProductAttrValueServices::class);
- //商品sku
- $suk = $skuValueServices->value(['unique' => $unique, 'product_id' => $product_id, 'type' => $type], 'suk');
- $productUnique = $skuValueServices->value(['suk' => $suk, 'product_id' => $new_product_id, 'type' => $type], 'unique');
- return $productUnique ?: '';
- }
- /**
- * 验证购物车商品规格是否在活动中
- * @param string $unique
- * @param array $productInfo
- * @param array $uniques
- * @param int $product_partake_type
- * @return bool
- */
- public function checkProductUnque(string $unique, array $productInfo, array $uniques, int $product_partake_type = 1)
- {
- if (!$unique) {
- return false;
- }
- if ((in_array($product_partake_type, [2, 3]) && !$uniques) || !is_array($uniques)) {
- return false;
- }
- if ($productInfo['type'] == 1 && $productInfo['pid'] > 0) {//平台共享到门店商品 查询平台商品unique
- $productUnique = $this->getProductUnique($unique, (int)$productInfo['id'], (int)($productInfo['pid'] ?? 0));
- $unique = $productUnique ?: $unique;
- }
- switch ($product_partake_type) {
- case 1:
- case 4:
- case 5:
- break;
- case 2:
- if (!$uniques) {
- return true;
- }
- if (!in_array($unique, $uniques)) {
- return false;
- }
- break;
- case 3:
- if (!$uniques) {
- return true;
- }
- if (in_array($unique, $uniques)) {
- return false;
- }
- break;
- default:
- return false;
- break;
- }
- return true;
- }
- /**
- * 计算商品优惠价格
- * @param int $uid
- * @param array $cartList
- * @param int $store_id
- * @param int $couponId
- * @param bool $isCart
- * @return array
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function computedPromotions(int $uid, array $cartList, int $store_id = 0, int $couponId = 0, bool $isCart = false)
- {
- $giveIntegral = $couponPrice = 0;
- $giveCoupon = $giveCartList = $usePromotions = $useCounpon = [];
- if ($cartList) {
- $productIds = array_column($cartList, 'product_id');
- // $productArr = array_combine($productIds, $cartList);
- $with = ['products' => function ($query) {
- $query->field('promotions_id,product_id,is_all,unique');
- }, 'giveProducts' => function ($query) {
- $query->field('type,promotions_id,product_id,limit_num,surplus_num,unique')->with(['productInfo' => function ($query) {
- $query->field('id,store_name');
- }]);
- }, 'giveCoupon' => function ($query) {
- $query->field('type,promotions_id,coupon_id,limit_num,surplus_num')->with(['coupon' => function ($query) {
- $query->field('id,type,coupon_type,coupon_title,coupon_price,use_min_price,remain_count,is_permanent');
- }]);
- }, 'promotions' => function ($query) {
- $query->field('id,pid,promotions_type,promotions_cate,threshold_type,threshold,discount_type,n_piece_n_discount,discount,give_integral,give_coupon_id,give_product_id,give_product_unique')->with(['giveProducts' => function ($query) {
- $query->field('type,promotions_id,product_id,limit_num,surplus_num,unique')->with(['productInfo' => function ($query) {
- $query->field('id,store_name');
- }]);
- }, 'giveCoupon' => function ($query) {
- $query->field('type,promotions_id, coupon_id,limit_num,surplus_num')->with(['coupon' => function ($query) {
- $query->field('id,type,coupon_type,coupon_title,coupon_price,use_min_price,remain_count,is_permanent');
- }]);
- }]);
- }];
- //获取购物车商品所有活动
- [$promotionsArr, $productDetails, $promotionsDetail] = $this->getProductsPromotionsDetail($productIds, '*', $with, [1, 2, 3, 4], '', $store_id);
- $computedArr = [];
- $usePromotionsIds = [];
- if ($promotionsArr) {
- $promotionsArr = array_combine(array_column($promotionsArr, 'id'), $promotionsArr);
- //获取商品活动是否叠加计算
- [$productDetails, $promotionsDetail, $productComputedArr] = $this->getProductComputedPromotions($promotionsArr, $productDetails, $promotionsDetail);
- //计算优惠金额
- $computedArr = $this->doComputeV1($uid, $cartList, $promotionsDetail, $promotionsArr, $productComputedArr);
- foreach ($cartList as &$cart) {
- $sum_promotions_true_price = 0;
- $product_id = (int)($cart['product_id'] ?? 0);
- $unique = $cart['product_attr_unique'] ?? '';
- $productInfo = $cart['productInfo'] ?? [];
- $promotionsIds = $productDetails[$product_id] ?? [];
- $cart['promotions_id'] = [];
- if (!$promotionsIds || !$unique || !$productInfo) {
- continue;
- }
- $price = isset($cart['productInfo']['attrInfo']['price']) ? $cart['productInfo']['attrInfo']['price'] : ($cart['productInfo']['price'] ?? 0);
- //叠加
- $typeArr = $productComputedArr[$product_id]['typeArr'] ?? [];
- $isOverly = isset($productComputedArr[$product_id]['is_overlay']) && $productComputedArr[$product_id]['is_overlay'];
- foreach ($promotionsIds as $promotions_id) {
- $promotionsInfo = $promotionsArr[$promotions_id] ?? [];
- $trueDetail = $computedArr[$promotions_id] ?? [];
- if (!$promotionsInfo || !$trueDetail) continue;
- if (!$this->checkProductUnque($unique, $productInfo, $trueDetail['uniques'][$product_id] ?? [], (int)$promotionsInfo['product_partake_type'])) {
- continue;
- }
- $trueArr = $trueDetail[$unique] ?? [];
- if (!isset($trueDetail['is_valid']) || $trueDetail['is_valid'] == 0) {
- if ($isCart) {//购物车不满足也展示
- $cart['promotions_id'][] = $promotions_id;
- }
- } else {
- //活动叠加商品 单件总计优惠金额
- if ($isOverly) {
- $cart['promotions_id'][] = $promotions_id;
- $sum_promotions_true_price = bcadd((string)$sum_promotions_true_price, (string)($trueArr['promotions_true_price'] ?? 0), 2);
- } else { //不叠加取最优惠
- if ($isCart) {
- $cart['promotions_id'][] = $promotions_id;
- }
- if ($sum_promotions_true_price < ($trueArr['promotions_true_price'] ?? 0)) {
- $sum_promotions_true_price = $trueArr['promotions_true_price'] ?? 0;
- if (!$isCart) {
- $cart['promotions_id'] = [$promotions_id];
- }
- }
- }
- }
- }
- if ($sum_promotions_true_price) {
- //是否有限时折扣
- if (in_array(1, $typeArr)) {
- $true_price = (float)bcsub((string)$price, (string)$sum_promotions_true_price, 2);
- if ($true_price < 0) {
- $true_price = 0;
- }
- //比较与用户等级、svip优惠后金额
- if ($true_price && $cart['truePrice'] > $true_price) {
- $cart['truePrice'] = $true_price;
- $cart['promotions_true_price'] = $sum_promotions_true_price;
- $cart['price_type'] = 'promotions';
- $cart['vip_truePrice'] = 0;
- } else { //使用了用户等级、svip价格 去掉优惠活动关联
- $cart['promotions_id'] = [];
- }
- } else {//svip 用户等级价格上继续优惠
- $true_price = (float)bcsub((string)$cart['truePrice'], (string)$sum_promotions_true_price, 2);
- $cart['truePrice'] = $true_price > 0 ? $true_price : 0;
- $cart['promotions_true_price'] = $sum_promotions_true_price;
- $cart['price_type'] = 'promotions';
- }
- }
- $usePromotionsIds = array_unique(array_merge($usePromotionsIds, $cart['promotions_id']));
- //排出不叠加 去最优的其他优惠活动金额
- foreach ($promotionsIds as $promotions_id) {
- //使用了优惠会跳过
- if (in_array($promotions_id, $cart['promotions_id'])) continue;
- $trueDetail = $computedArr[$promotions_id] ?? [];
- $trueArr = $trueDetail[$unique] ?? [];
- if (!$trueDetail || !$trueArr) {
- continue;
- }
- $true_price = $trueArr['promotions_true_price'] ?? 0;
- $sum_promotions_price = bcsub((string)($trueDetail['sum_promotions_price'] ?? '0'), (string)bcmul((string)$true_price, (string)$cart['cart_num'], 2), 2);
- $computedArr[$promotions_id]['sum_promotions_price'] = $sum_promotions_price >= 0 ? $sum_promotions_price : 0;
- //这个商品的没有使用优惠活动
- unset($computedArr[$promotions_id][$unique]);
- }
- }
- }
- //使用优惠券
- $coupon_id = 0;
- if ($uid) {
- if ($usePromotionsIds) [$usePromotions, $giveIntegral, $giveCoupon, $giveCartList] = $this->getUsePromotiosnInfo($uid, $store_id, $usePromotionsIds, $promotionsArr, $computedArr);
- if ($couponId) {
- [$useCounpon, $couponPrice] = $this->useCoupon($couponId, $uid, $cartList, $usePromotions, $store_id);
- $coupon_id = $couponId;
- } else {
- //获取最优优惠券
- if ($isCart) {
- /** @var StoreCouponIssueServices $couponServices */
- $couponServices = app()->make(StoreCouponIssueServices::class);
- $useCounpon = $couponServices->getCanUseCoupon($uid, $cartList, $usePromotions, $store_id);
- $couponPrice = $useCounpon['true_coupon_price'] ?? 0;
- $coupon_id = $useCounpon['used']['id'] ?? 0;
- }
- }
- //计算每一件商品优惠券优惠金额
- if ($coupon_id && $useCounpon && $couponPrice) {
- /** @var StoreOrderComputedServices $computedServices */
- $computedServices = app()->make(StoreOrderComputedServices::class);
- $payPrice = $computedServices->getOrderSumPrice($cartList);
- if ($couponPrice > $payPrice) {
- $couponPrice = $payPrice;
- }
- /** @var StoreOrderCreateServices $createServices */
- $createServices = app()->make(StoreOrderCreateServices::class);
- $priceData = ['coupon_id' => $coupon_id, 'coupon_price' => $couponPrice];
- $cartList = $createServices->computeOrderProductCoupon($cartList, $priceData, $usePromotions, $store_id);
- }
- }
- //获取赠送积分、优惠券、商品
- [$cartList, $computedArr, $useGivePromotionsIds] = $this->getPromotionsGive($uid, $cartList, $computedArr, $promotionsDetail, $productDetails, $promotionsArr, $isCart);
- $usePromotionsIds = array_unique(array_merge($usePromotionsIds, $useGivePromotionsIds));
- //整合返回数据
- if ($usePromotionsIds) [$usePromotions, $giveIntegral, $giveCoupon, $giveCartList] = $this->getUsePromotiosnInfo($uid, $store_id, $usePromotionsIds, $promotionsArr, $computedArr);
- }
- return [$cartList, $couponPrice, $useCounpon, $usePromotions, $giveIntegral, $giveCoupon, $giveCartList];
- }
- /**
- * 实际计算商品优惠金额
- * @param int $uid
- * @param array $cartList
- * @param array $promotionsDetail
- * @param array $promotionsArr
- * @param array $productComputedArr
- * @return array
- */
- public function doComputeV1(int $uid, array $cartList, array $promotionsDetail, array $promotionsArr, array $productComputedArr)
- {
- $computedArr = [];
- if (!$cartList || !$promotionsDetail) {
- return $computedArr;
- }
- /** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
- $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
- foreach ($promotionsDetail as $promotions_id => $productIds) {
- $promotions = $promotionsArr[$promotions_id] ?? [];
- $productCount = count($productIds);
- if (!$promotions || !$productCount || $promotions['promotions_type'] == 4) continue;
- //验证商品规格是否满足活动
- [$productIds, $uniques] = $this->checkProductCanUsePromotions($productIds, $cartList, $promotions);
- if (!$productIds) {
- continue;
- }
- //验证限量
- if ($uid) {
- $productIds = $this->checkPromotionsLimit($storeOrderCartInfoServices, $uid, (int)$promotions_id, $productIds, $promotions);
- if (!$productIds) {
- continue;
- }
- }
- $promotions_type = (int)$promotions['promotions_type'] ?? 1;
- $this->setItem('productComputedArr', $productComputedArr)->setItem('computedArr', $computedArr);
- [$sumPrice, $sumCount, $promotionsProductArr] = $this->getPromotionsProductInfo($promotions_type, $productIds, $cartList, $uniques, (int)$promotions['product_partake_type']);
- $this->reset();
- $compute_price = $sum_promotions_true_price = $sum_promotions_price = 0;
- $data = ['is_valid' => 0, 'reach_threshold' => 0, 'differ_threshold' => 0, 'promotions_type' => $promotions['promotions_type'], 'sum_promotions_price' => 0, 'product_id' => [], 'uniques' => $uniques];
- switch ($promotions['promotions_type']) {
- case 1://限制折扣
- $p = $promotions['promotions'][0] ?? [];
- if ($p) {
- $promotionsDiscount = $this->computedDiscount($p['discount'], 100, 2);
- $sum_promotions_price = 0;
- if ($promotions['is_limit']) {//是否限量
- $limit_num = $promotions['limit_num'];
- if ($limit_num <= 0) break;
- $sumCount = 0;
- foreach ($promotionsProductArr as $product) {
- $product_id = $product['product_id'];
- $unique = $product['product_attr_unique'];
- $price = $product['price'];
- $cartNum = $newCartNum = $product['cart_num'] ?? 1;
- if ($sumCount >= $limit_num) {
- break;
- }
- if (bcadd((string)$sumCount, (string)$cartNum) > $limit_num) {//加上下一个商品数量 大于限购数量
- $newCartNum = bcsub((string)$limit_num, (string)$sumCount);
- $sumCount = $limit_num;
- }
- $promotions_true_price = (float)bcmul((string)$price, (string)$promotionsDiscount, 2);
- if ($promotions_true_price < 0.01) {//实际优惠小于0.01 就不计算优惠
- $promotions_true_price = 0;
- }
- //部分享受折扣
- if ($cartNum != $newCartNum) {
- $promotions_true_price = bcdiv((string)bcmul((string)$promotions_true_price, (string)$newCartNum, 4), (string)$cartNum, 2);
- }
- $data[$unique] = ['product_id' => $product_id, 'uniqid' => $unique, 'price' => $price, 'promotions_true_price' => $promotions_true_price];
- $sum_promotions_price = bcadd((string)$sum_promotions_price, (string)bcmul((string)$promotions_true_price, (string)$cartNum, 2), 2);
- }
- } else {
- foreach ($promotionsProductArr as $product) {
- $product_id = $product['product_id'];
- $unique = $product['product_attr_unique'];
- $price = $product['price'];
- $promotions_true_price = (float)bcmul((string)$price, (string)$promotionsDiscount, 2);
- if ($promotions_true_price < 0.01) {//实际优惠小于0.01 就不计算优惠
- $promotions_true_price = 0;
- }
- $data[$unique] = ['product_id' => $product_id, 'uniqid' => $unique, 'price' => $price, 'promotions_true_price' => $promotions_true_price];
- $sum_promotions_price = bcadd((string)$sum_promotions_price, (string)bcmul((string)$promotions_true_price, (string)($product['cart_num'] ?? 1), 2), 2);
- }
- }
- $data['is_valid'] = 1;
- $data['sum_promotions_price'] = $sum_promotions_price;
- }
- break;
- case 2://n件n折
- $p = $promotions['promotions'][0] ?? [];
- if ($p) {
- $promotionsDiscount = $this->computedDiscount($p['discount'], 100, 2);
- if ($sumCount >= $p['threshold']) {//满足
- $useProductArr = $promotionsProductArr;
- //商品价格升序
- array_multisort(array_column($promotionsProductArr, 'price'), SORT_ASC, $promotionsProductArr);
- $minPrice = $promotionsProductArr[0]['price'] ?? 0;
- //算出n件实际优惠金额
- $sum_promotions_price = (float)bcmul((string)$minPrice, (string)$promotionsDiscount, 2);
- if ($sum_promotions_price < 0.01) {
- $sum_promotions_price = 0;
- }
- if ($sum_promotions_price) {
- $useCount = $productCount;
- $useSumPrice = $sumPrice;
- $count = count($useProductArr);
- $compute_price = 0;
- array_multisort(array_column($useProductArr, 'cart_num'), SORT_DESC, $useProductArr);
- foreach ($useProductArr as $value) {
- $product_id = $value['product_id'];
- $unique = $value['product_attr_unique'];
- $price = $value['price'];
- if ($count > 1) {
- $promotions_true_price = bcmul((string)bcdiv((string)$price, (string)$useSumPrice, 4), (string)$sum_promotions_price, 2);
- $compute_price = bcadd((string)$compute_price, (string)bcmul((string)$promotions_true_price, (string)$value['cart_num'], 2), 2);
- } else {
- $one_promotions_sum_price = bcsub((string)$sum_promotions_price, (string)$compute_price, 2);
- $promotions_true_price = bcdiv((string)$one_promotions_sum_price, (string)$value['cart_num'], 2);
- }
- $data[$unique] = ['product_id' => $product_id, 'uniqid' => $unique, 'price' => $price, 'promotions_true_price' => $promotions_true_price];
- $count--;
- }
- }
- $data['is_valid'] = 1;
- $data['reach_threshold'] = $p['threshold'];
- $data['sum_promotions_price'] = $sum_promotions_price;
- } else {
- $data['differ_discount'] = $p['discount'];
- $data['differ_threshold'] = bcsub((string)$p['threshold'], (string)$sumCount, 0);
- }
- }
- break;
- case 3://满减折
- if ($promotions['promotions_cate'] == 1) {//阶梯 享受最高
- $valid = $invalid = [];
- foreach ($promotions['promotions'] as $key => $p) {
- if (($p['threshold_type'] == 1 ? $sumPrice : $sumCount) >= $p['threshold']) {
- $valid = $p;
- } else {
- $invalid = $p;
- break;
- }
- }
- if ($valid) {
- if ($valid['discount_type'] == 1) {//免减
- $sum_promotions_price = (string)$valid['discount'];
- } else {//折扣
- $promotionsDiscount = $this->computedDiscount($valid['discount'], 100, 2);
- $sum_promotions_price = 0;
- }
- array_multisort(array_column($promotionsProductArr, 'cart_num'), SORT_DESC, $promotionsProductArr);
- foreach ($promotionsProductArr as $product) {
- $product_id = $product['product_id'];
- $unique = $product['product_attr_unique'];
- $price = $product['price'];
- if ($valid['discount_type'] == 1) {
- if ($productCount > 1) {
- $promotions_true_price = bcmul((string)bcdiv((string)$price, (string)$sumPrice, 4), (string)$sum_promotions_price, 2);
- $compute_price = bcadd((string)$compute_price, (string)bcmul((string)$promotions_true_price, (string)$product['cart_num'], 2), 2);
- } else {
- $one_promotions_sum_price = bcsub((string)$sum_promotions_price, (string)$compute_price, 2);
- $promotions_true_price = bcdiv((string)$one_promotions_sum_price, (string)$product['cart_num'], 2);
- }
- } else {
- $promotions_true_price = (float)bcmul((string)$price, (string)$promotionsDiscount, 2);
- if ($promotions_true_price < 0.01) {//实际优惠小于0.01 就不计算优惠
- $promotions_true_price = 0;
- }
- $sum_promotions_price = bcadd((string)$sum_promotions_price, (string)bcmul((string)$promotions_true_price, (string)($product['cart_num'] ?? 1), 2), 2);
- }
- $data[$unique] = ['product_id' => $product_id, 'uniqid' => $unique, 'price' => $price, 'promotions_true_price' => $promotions_true_price];
- $productCount--;
- }
- $data['is_valid'] = 1;
- $data['reach_threshold'] = $valid['threshold'];
- $data['sum_promotions_price'] = $sum_promotions_price;
- }
- if ($invalid) {
- if ($valid) $data['is_valid'] = 2;
- if ($invalid['discount_type'] == 1) {//免减
- $data['differ_price'] = $invalid['discount'];
- } else {
- $data['differ_discount'] = $invalid['discount'];
- }
- $data['differ_threshold'] = bcsub((string)$invalid['threshold'], (string)($invalid['threshold_type'] == 1 ? $sumPrice : $sumCount), 0);
- }
- } else {//循环
- $p = $promotions['promotions'][0] ?? [];
- $validCount = floor(bcdiv((string)($p['threshold_type'] == 1 ? $sumPrice : $sumCount), (string)$p['threshold'], 2));
- if ($validCount) {//满足次数
- $promotionsDiscount = $this->computedDiscount($p['discount'], 100, 2);
- $sum_promotions_price = 0;
- $useProductArr = $promotionsProductArr;
- if ($p['discount_type'] == 2 && $p['threshold_type'] == 2) {//满n件 打n折
- // $suprplusDiscount = bcsub((string)$productCount, bcmul((string)$validCount, (string)$p['threshold'], 0), 0);
- //商品价格升序
- array_multisort(array_column($promotionsProductArr, 'price'), SORT_ASC, $promotionsProductArr);
- $minPrice = $promotionsProductArr[0]['price'] ?? 0;
- //算出n件实际优惠金额
- $sum_promotions_price = (float)bcmul((string)$minPrice, (string)$promotionsDiscount, 2);
- if ($sum_promotions_price < 0.01) {
- $sum_promotions_price = 0;
- }
- $sum_promotions_price = bcmul((string)$validCount, (string)$sum_promotions_price, 2);
- } else {
- if ($p['discount_type'] == 1) {//免减(n元、n件)
- $sum_promotions_price = bcmul((string)$validCount, (string)$p['discount'], 2);
- } else {//打折
- if ($p['threshold_type'] == 1) {//满n元
- $sum_promotions_price = bcmul((string)bcmul((string)$validCount, (string)$p['threshold'], 2), (string)$promotionsDiscount, 2);
- }
- }
- }
- $useCount = 0;
- array_multisort(array_column($useProductArr, 'cart_num'), SORT_DESC, $useProductArr);
- foreach ($useProductArr as $product) {
- $price = $product['price'];
- $product_id = $product['product_id'];
- $unique = $product['product_attr_unique'];
- // if ($p['discount_type'] == 2 && $p['threshold_type'] == 2) { //满n件打n折
- // if ($p['threshold'] > $useCount) {
- // $promotions_true_price = (float)bcmul((string)$price, (string)$promotionsDiscount, 2);
- // if ($promotions_true_price < 0.01) {//实际优惠小于0.01 就不计算优惠
- // $promotions_true_price = 0;
- // }
- // } else {
- // $promotions_true_price = 0;
- // }
- // $sum_promotions_price = bcadd((string)$sum_promotions_price, (string)$promotions_true_price, 2);
- // $useCount = (int)bcadd((string)$useCount, (string)$product['cart_num']);
- // } else {
- if ($productCount > 1) {
- $promotions_true_price = bcmul((string)bcdiv((string)$price, (string)$sumPrice, 4), (string)$sum_promotions_price, 2);
- $compute_price = bcadd((string)$compute_price, (string)bcmul((string)$promotions_true_price, (string)$product['cart_num'], 2), 2);
- } else {
- $one_promotions_sum_price = bcsub((string)$sum_promotions_price, (string)$compute_price, 2);
- $promotions_true_price = bcdiv((string)$one_promotions_sum_price, (string)$product['cart_num'], 2);
- }
- // }
- $data[$unique] = ['product_id' => $product_id, 'uniqid' => $unique, 'price' => $price, 'promotions_true_price' => $promotions_true_price];
- $productCount--;
- }
- $data['is_valid'] = 1;
- $data['reach_threshold'] = $p['threshold'];
- $data['sum_promotions_price'] = $sum_promotions_price;
- } else {
- if ($p['discount_type'] == 1) {//免减
- $data['differ_price'] = $p['discount'];
- } else {
- $data['differ_discount'] = $p['discount'];
- }
- $data['differ_threshold'] = bcsub((string)$p['threshold'], (string)($p['threshold_type'] == 1 ? $sumPrice : $sumCount), 0);
- }
- }
- break;
- case 4://满送
- break;
- default:
- break;
- }
- $data['give'] = ['give_integral' => 0, 'give_coupon' => [], 'give_product' => []];
- $computedArr[$promotions_id] = $data;
- }
- return $computedArr;
- }
- /**
- * 使用优惠卷
- * @param int $couponId
- * @param int $uid
- * @param array $cartInfo
- * @param array $promotions
- * @param int $store_id
- * @return array
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function useCoupon(int $couponId, int $uid, array $cartInfo, array $promotions, int $store_id = 0)
- {
- //使用优惠劵
- $couponPrice = 0;
- $couponInfo = [];
- if ($couponId && $cartInfo) {
- /** @var StoreCouponUserServices $couponServices */
- $couponServices = app()->make(StoreCouponUserServices::class);
- $couponInfo = $couponServices->getOne([['id', '=', $couponId], ['uid', '=', $uid], ['is_fail', '=', 0], ['status', '=', 0], ['start_time', '<=', time()], ['end_time', '>=', time()]], '*', ['issue']);
- if (!$couponInfo) {
- throw new ValidateException('选择的优惠劵无效!');
- }
- $type = $couponInfo['coupon_applicable_type'] ?? 0;
- $flag = false;
- $price = 0;
- $count = 0;
- $promotionsList = [];
- if ($promotions) {
- $promotionsList = array_combine(array_column($promotions, 'id'), $promotions);
- }
- //验证是否适用门店
- if ($store_id && isset($couponInfo['applicable_type']) && isset($couponInfo['applicable_store_id'])) {
- $applicable_store_id = is_array($couponInfo['applicable_store_id']) ? $couponInfo['applicable_store_id'] : explode(',', $couponInfo['applicable_store_id']);
- //活动不适用该门店
- if ($couponInfo['applicable_type'] == 0 || ($couponInfo['applicable_type'] == 2 && !in_array($store_id, $applicable_store_id))) {
- throw new ValidateException('优惠劵暂不支持该门店使用!');
- }
- }
- $isOverlay = function ($cart) use ($promotionsList) {
- $productInfo = $cart['productInfo'] ?? [];
- if (!$productInfo) {
- return false;
- }
- //门店独立商品 不使用优惠券
- $isBranchProduct = isset($productInfo['type']) && isset($productInfo['pid']) && $productInfo['type'] == 1 && !$productInfo['pid'];
- if ($isBranchProduct) {
- return false;
- }
- if (isset($cart['promotions_id']) && $cart['promotions_id']) {
- foreach ($cart['promotions_id'] as $key => $promotions_id) {
- $promotions = $promotionsList[$promotions_id] ?? [];
- if ($promotions && $promotions['promotions_type'] != 4) {
- $overlay = is_string($promotions['overlay']) ? explode(',', $promotions['overlay']) : $promotions['overlay'];
- if (!in_array(5, $overlay)) {
- return false;
- }
- }
- }
- }
- return true;
- };
- switch ($type) {
- case 0:
- foreach ($cartInfo as $cart) {
- if (!$isOverlay($cart)) continue;
- $price = bcadd((string)$price, bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2), 2);
- $count++;
- }
- break;
- case 1://品类券
- /** @var StoreProductCategoryServices $storeCategoryServices */
- $storeCategoryServices = app()->make(StoreProductCategoryServices::class);
- $cateGorys = $storeCategoryServices->getAllById((int)$couponInfo['category_id']);
- if ($cateGorys) {
- $cateIds = array_column($cateGorys, 'id');
- foreach ($cartInfo as $cart) {
- if (!$isOverlay($cart)) continue;
- if (isset($cart['productInfo']['cate_id']) && array_intersect(explode(',', $cart['productInfo']['cate_id']), $cateIds)) {
- $price = bcadd((string)$price, (string)bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2), 2);
- $count++;
- }
- }
- }
- break;
- case 2:
- foreach ($cartInfo as $cart) {
- if (!$isOverlay($cart)) continue;
- $product_id = isset($cart['productInfo']['pid']) && $cart['productInfo']['pid'] ? $cart['productInfo']['pid'] : ($cart['product_id'] ?? 0);
- if ($product_id && in_array($product_id, explode(',', $couponInfo['product_id']))) {
- $price = bcadd((string)$price, bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2), 2);
- $count++;
- }
- }
- case 3:
- /** @var StoreBrandServices $storeBrandServices */
- $storeBrandServices = app()->make(StoreBrandServices::class);
- $brands = $storeBrandServices->getAllById((int)$couponInfo['brand_id']);
- if ($brands) {
- $brandIds = array_column($brands, 'id');
- foreach ($cartInfo as $cart) {
- if (!$isOverlay($cart)) continue;
- if (isset($cart['productInfo']['brand_id']) && in_array($cart['productInfo']['brand_id'], $brandIds)) {
- $price = bcadd((string)$price, (string)bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2), 2);
- $count++;
- }
- }
- }
- break;
- }
- if ($count && $couponInfo['use_min_price'] <= $price) {
- $flag = true;
- }
- if (!$flag) {
- return [[], 0];
- // throw new ValidateException('不满足优惠劵的使用条件!');
- }
- //满减券
- if ($couponInfo['coupon_type'] == 1) {
- $couponPrice = $couponInfo['coupon_price'] > $price ? $price : $couponInfo['coupon_price'];
- } else {
- if ($couponInfo['coupon_price'] <= 0) {//0折
- $couponPrice = $price;
- } else if ($couponInfo['coupon_price'] >= 100) {
- $couponPrice = 0;
- } else {
- $truePrice = (float)bcmul((string)$price, bcdiv((string)$couponInfo['coupon_price'], '100', 2), 2);
- $couponPrice = (float)bcsub((string)$price, (string)$truePrice, 2);
- }
- }
- }
- return [$couponInfo, $couponPrice];
- }
- /**
- * 实际获取优惠活动赠送赠品
- * @param int $uid
- * @param array $cartList
- * @param array $computedArr
- * @param array $promotionsDetail
- * @param array $productDetails
- * @param array $promotionsArr
- * @param bool $isCart
- * @return array
- */
- public function getPromotionsGive(int $uid, array $cartList, array $computedArr, array $promotionsDetail, array $productDetails, array $promotionsArr, bool $isCart = false)
- {
- $usePromotionsIds = [];
- if (!$cartList || !$promotionsDetail) {
- return [$cartList, $computedArr, $usePromotionsIds];
- }
- foreach ($promotionsDetail as $promotions_id => $productIds) {
- $promotions = $promotionsArr[$promotions_id] ?? [];
- $productCount = count($productIds);
- if (!$promotions || !$productCount || $promotions['promotions_type'] != 4) continue;
- //验证商品规格是否满足活动
- [$productIds, $uniques] = $this->checkProductCanUsePromotions($productIds, $cartList, $promotions);
- if (!$productIds) {
- continue;
- }
- $promotions_type = (int)$promotions['promotions_type'] ?? 1;
- [$sumPrice, $sumCount, $promotionsProductArr] = $this->getPromotionsProductInfo($promotions_type, $productIds, $cartList, $uniques, (int)$promotions['product_partake_type'], true);
- $give_product_id = [];
- $give_coupon_ids = [];
- $give_integral = 0;
- $data = ['is_valid' => 0, 'reach_threshold' => 0, 'differ_threshold' => 0, 'promotions_type' => $promotions['promotions_type'], 'sum_promotions_price' => 0, 'product_id' => []];
- if ($promotions['promotions_cate'] == 1) {//阶梯
- $valid = $invalid = [];
- foreach ($promotions['promotions'] as $key => $p) {
- if (($p['threshold_type'] == 1 ? $sumPrice : $sumCount) >= $p['threshold']) {
- $valid = $p;
- } else {
- $invalid = $p;
- break;
- }
- }
- if ($valid) {
- if ($valid['give_integral']) {
- $give_integral = bcadd((string)$give_integral, (string)$valid['give_integral'], 0);
- }
- if ($valid['give_coupon_id']) {
- $coupon_ids = is_string($valid['give_coupon_id']) ? explode(',', $valid['give_coupon_id']) : $valid['give_coupon_id'];
- $give_coupon_ids = array_merge($give_coupon_ids, $coupon_ids);
- }
- if ($valid['giveProducts']) {
- foreach ($valid['giveProducts'] as $value) {
- if (isset($give_product_id[$value['unique']])) {
- $give_product_id[$value['unique']]['cart_num'] = $give_product_id[$value['unique']]['cart_num'] + 1;
- } else {
- $give_product_id[$value['unique']] = ['promotions_id' => $value['promotions_id'], 'unique' => $value['unique'], 'product_id' => $value['product_id'], 'cart_num' => 1];
- }
- }
- }
- $data['is_valid'] = 1;
- $data['reach_threshold'] = $valid['threshold'];
- }
- if ($invalid) {
- if ($valid) $data['is_valid'] = 2;
- $data['differ_threshold'] = bcsub((string)$invalid['threshold'], (string)($invalid['threshold_type'] == 1 ? $sumPrice : $sumCount), 0);
- }
- } else {//循环
- $p = $promotions['promotions'][0] ?? [];
- $validCount = floor(bcdiv((string)($p['threshold_type'] == 1 ? $sumPrice : $sumCount), (string)$p['threshold'], 2));
- if ($validCount) {//满足次数
- if ($p['give_integral']) {
- $give_integral = bcadd((string)$give_integral, (string)bcmul((string)$validCount, (string)$p['give_integral'], 0), 0);
- }
- if ($p['give_coupon_id']) {
- $coupon_ids = is_string($p['give_coupon_id']) ? explode(',', $p['give_coupon_id']) : $p['give_coupon_id'];
- $give_coupon_ids = array_merge($give_coupon_ids, $coupon_ids);
- }
- if ($p['giveProducts']) {
- foreach ($p['giveProducts'] as $value) {
- if (isset($give_product_id[$value['unique']])) {
- $give_product_id[$value['unique']]['cart_num'] = bcadd((string)$give_product_id[$value['unique']]['cart_num'], (string)$validCount);
- } else {
- $give_product_id[$value['unique']] = ['promotions_id' => $value['promotions_id'], 'unique' => $value['unique'], 'product_id' => $value['product_id'], 'cart_num' => $validCount];
- }
- }
- }
- $data['is_valid'] = 1;
- $data['reach_threshold'] = $p['threshold'];
- } else {
- $data['differ_threshold'] = bcsub((string)$p['threshold'], (string)($p['threshold_type'] == 1 ? $sumPrice : $sumCount), 0);
- }
- }
- $ids = [];
- //验证优惠券限量
- if ($give_coupon_ids) {
- foreach ($give_coupon_ids as $give_coupon_id) {
- foreach ($promotions['promotions'] as $value) {
- $giveCoupon = $value['giveCoupon'] ?? [];
- if ($giveCoupon) $giveCoupon = array_combine(array_column($giveCoupon, 'coupon_id'), $giveCoupon);
- if ($giveCoupon && ($giveCoupon[$give_coupon_id]['surplus_num'] ?? 0) >= 1) {
- $ids[] = $give_coupon_id;
- break;
- }
- }
- }
- }
- $data['give'] = ['give_integral' => $give_integral, 'give_coupon' => $ids, 'give_product' => $give_product_id];
- $computedArr[$promotions_id] = $data;
- if (!$isCart && $data['is_valid'] > 0) {
- $usePromotionsIds[] = $promotions_id;
- } elseif ($isCart) {
- $usePromotionsIds[] = $promotions_id;
- }
- }
- foreach ($cartList as &$cart) {
- $product_id = $cart['product_id'] ?? 0;
- $promotionsIds = $productDetails[$product_id] ?? [];
- if (!$promotionsIds) {
- continue;
- }
- $useIds = array_intersect($promotionsIds, $usePromotionsIds);
- $cart['promotions_id'] = array_unique(array_merge($cart['promotions_id'] ?? [], $useIds));
- }
- return [$cartList, $computedArr, $usePromotionsIds];
- }
- /**
- * 生成赠送商品购物车数据
- * @param int $uid
- * @param int $promotions_id
- * @param array $giveProduct
- * @param array promotions
- * @param int $store_id
- * @return array
- */
- public function createGiveProductCart(int $uid, int $promotions_id, array $giveProduct, array $promotions, int $store_id = 0)
- {
- $cart = [];
- if ($giveProduct) {
- /** @var StoreOrderCreateServices $storeOrderCreateService */
- $storeOrderCreateService = app()->make(StoreOrderCreateServices::class);
- /** @var StoreCartServices $storeCartServices */
- $storeCartServices = app()->make(StoreCartServices::class);
- $promotionsArr = $promotions['promotions'] ?? [];
- foreach ($giveProduct as $unique => $give) {
- $product_id = $give['product_id'] ?? 0;
- $cart_num = $give['cart_num'] ?? 1;
- if (!$product_id) {
- continue;
- }
- try {
- [$attrInfo, $product_attr_unique, $bargainPriceMin, $cart_num, $productInfo] = $storeCartServices->checkProductStock($uid, (int)$product_id, (int)$cart_num, $store_id, $unique, true);
- } catch (\Throwable $e) {
- continue;
- }
- $is_limit = false;
- foreach ($promotionsArr as $key => $value) {
- $giveProducts = $value['giveProducts'] ?? [];
- if ($giveProducts) $giveProducts = array_combine(array_column($giveProducts, 'product_id'), $giveProducts);
- if ($giveProducts && $cart_num <= ($giveProducts[$product_id]['surplus_num'] ?? 0)) {
- $is_limit = true;
- break;
- }
- }
- if (!$is_limit) {
- continue;
- }
- $key = $storeOrderCreateService->getNewOrderId((string)$uid);
- $info['id'] = $key;
- $info['type'] = 0;
- $info['product_type'] = $productInfo['product_type'];
- $info['promotions_id'] = [$give['promotions_id'] ?? $promotions_id];
- $info['activity_id'] = 0;
- $info['discount_product_id'] = 0;
- $info['product_id'] = $product_id;
- $info['is_gift'] = 1;
- $info['is_valid'] = 1;
- $info['product_attr_unique'] = $product_attr_unique;
- $info['cart_num'] = $cart_num;
- $info['productInfo'] = $productInfo ? $productInfo->toArray() : [];
- $info['productInfo']['express_delivery'] = false;
- $info['productInfo']['store_mention'] = false;
- $info['productInfo']['store_delivery'] = false;
- if (isset($info['productInfo']['delivery_type'])) {
- $info['productInfo']['delivery_type'] = is_string($info['productInfo']['delivery_type']) ? explode(',', $info['productInfo']['delivery_type']) : $info['productInfo']['delivery_type'];
- if (in_array(1, $info['productInfo']['delivery_type'])) {
- $info['productInfo']['express_delivery'] = true;
- }
- if (in_array(2, $info['productInfo']['delivery_type'])) {
- $info['productInfo']['store_mention'] = true;
- }
- if (in_array(3, $info['productInfo']['delivery_type'])) {
- $info['productInfo']['store_delivery'] = true;
- }
- }
- $info['productInfo']['attrInfo'] = $attrInfo->toArray();
- $info['attrStatus'] = (bool)$info['productInfo']['attrInfo'];
- $info['sum_price'] = $info['productInfo']['attrInfo']['price'] ?? $info['productInfo']['price'] ?? 0;
- $info['truePrice'] = 0;
- $info['vip_truePrice'] = 0;
- $info['trueStock'] = $info['productInfo']['attrInfo']['stock'] ?? 0;
- $info['costPrice'] = $info['productInfo']['attrInfo']['cost'] ?? 0;
- $info['limit_num'] = $giveProducts[$product_id]['limit_num'] ?? 0;
- $cart[] = $info;
- }
- }
- return $cart;
- }
- /**
- * 根据类型获取商品列表
- * @param int $type
- * @param int $uid
- * @param int $promotions_id
- * @param int $store_id
- * @param int $staff_id
- * @param int $tourist_uid
- * @return array|array[]|null
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getTypeList(int $type, int $uid, int $promotions_id = 0)
- {
- $store_id = (int)$this->getItem('store_id', 0);
- $staff_id = (int)$this->getItem('staff_id', 0);
- $tourist_uid = (int)$this->getItem('tourist_uid', 0);
- $store_name = $this->getItem('store_name', '');
- $ids = $this->getItem('ids', []);
- $not_ids = $this->getItem('not_ids', []);
- $where = [];
- $where['type'] = 1;
- $where['store_id'] = 0;
- $where['pid'] = 0;
- $where['is_del'] = 0;
- $where['status'] = 1;
- $where['promotionsTime'] = true;
- $where['promotions_type'] = $type;
- if ($promotions_id) {
- $where['id'] = $promotions_id;
- }
- $product_where = [];
- $product_where['store_name'] = $store_name;
- $product_where['pids'] = $ids;
- $product_where['not_pids'] = $not_ids;
- //门店不展示卡密商品
- $product_where['product_type'] = [0, 2, 4];
- //存在一个全部商品折扣优惠活动 直接返回商品
- if ($ids && !$this->dao->count($where + ['product_partake_type' => 1])) {
- //正选并集
- $mergeIds = function ($promotions) {
- $data = [];
- foreach ($promotions as $item) {
- $productIds = is_string($item['product_id']) ? explode(',', $item['product_id']) : $item['product_id'];
- $data = array_merge($data, $productIds);
- }
- return $data;
- };
- $promotions = $this->getList($where + ['product_partake_type' => 2], 'id,product_id');
- $product_where['pids'] = $promotions ? $mergeIds($promotions) : [];
- $notPromotions = $this->getList($where + ['product_partake_type' => 3], 'id,product_id');
- //反选交集
- /** @var StorePromotionsAuxiliaryServices $auxiliaryService */
- $auxiliaryService = app()->make(StorePromotionsAuxiliaryServices::class);
- $intersectIds = function ($promotions) use ($auxiliaryService) {
- $data = [];
- foreach ($promotions as $item) {
- $productIds = is_string($item['product_id']) ? explode(',', $item['product_id']) : $item['product_id'];
- if (!$productIds) {
- continue;
- }
- $productIds = $auxiliaryService->getColumn(['promotions_id' => $item['id'], 'type' => 1, 'is_all' => 1, 'product_id' => $productIds], 'product_id', '', true);
- if (!$productIds) {
- continue;
- }
- if ($data) {
- $data = array_intersect($data, $productIds);
- } else {
- $data = $productIds;
- }
- }
- return $data;
- };
- $product_where['not_pids'] = array_merge($product_where['not_pids'], $notPromotions ? $intersectIds($notPromotions) : []);
- }
- $list = [];
- $count = 0;
- if ($product_where['pids'] && $this->dao->count($where)) {
- $product_where['pids'] = array_merge(array_diff($product_where['pids'], $product_where['not_pids']));
- unset($product_where['not_pids']);
- /** @var StoreBranchProductServices $branchProductServices */
- $branchProductServices = app()->make(StoreBranchProductServices::class);
- return $branchProductServices->getCashierProductListV2($product_where, $store_id, $uid, $staff_id, $tourist_uid);
- }
- return compact('list', 'count');
- }
- /**
- * 获取凑单商品ids
- * @param int $promotions_id
- * @return array
- */
- public function collectOrderProduct(int $promotions_id)
- {
- $product_where = [];
- $promotions = $this->dao->get($promotions_id, ['*']);
- if ($promotions) {
- $promotions = $promotions->toArray();
- /** @var StoreProductRelationServices $storeProductRelationServices */
- $storeProductRelationServices = app()->make(StoreProductRelationServices::class);
- /** @var StorePromotionsAuxiliaryServices $promotionsAuxiliaryServices */
- $promotionsAuxiliaryServices = app()->make(StorePromotionsAuxiliaryServices::class);
- $promotionsAuxiliaryData = $promotionsAuxiliaryServices->getPromotionsAuxiliaryCache($promotions_id);
- switch ($promotions['product_partake_type']) {
- case 1://所有商品
- break;
- case 2://选中商品参与
- $product_ids = $promotionsAuxiliaryData;
- $product_where['ids'] = $product_ids;
- break;
- case 3:
- $ids = is_string($promotions['product_id']) ? explode(',', $promotions['product_id']) : $promotions['product_id'];
- if ($ids) {//商品全部规格 不参与 才不显示该商品
- /** @var StorePromotionsAuxiliaryServices $auxiliaryService */
- $auxiliaryService = app()->make(StorePromotionsAuxiliaryServices::class);
- $ids = $auxiliaryService->getColumn(['promotions_id' => $promotions['id'], 'type' => 1, 'is_all' => 1, 'product_id' => $ids], 'product_id', '', true);
- }
- $product_where['not_ids'] = $ids;
- break;
- case 4://品牌
- $product_ids = $promotionsAuxiliaryData ? $storeProductRelationServices->getIdsByWhere(['type' => 2, 'relation_id' => $promotionsAuxiliaryData]) : [];
- $product_where['ids'] = $product_ids;
- break;
- case 5://商品标签
- $product_ids = $promotionsAuxiliaryData ? $storeProductRelationServices->getIdsByWhere(['type' => 3, 'relation_id' => $promotionsAuxiliaryData]) : [];
- $product_where['ids'] = $product_ids;
- break;
- }
- }
- return $product_where;
- }
- }
|