MCart.Class.php 151 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521
  1. <?php
  2. /**
  3. * 购物车
  4. * Created by PhpStorm.
  5. * User: XiaoMing
  6. * Date: 2019/11/6
  7. * Time: 16:20
  8. */
  9. namespace JinDouYun\Model\Cart;
  10. use JinDouYun\Dao\Cashier\DCashierCustomerPrice;
  11. use JinDouYun\Dao\System\DDeliveryRule;
  12. use JinDouYun\Model\Cashier\MCashierSettings;
  13. use JinDouYun\Model\Market\MComBinPackage;
  14. use Mall\Framework\Core\ErrorCode;
  15. use Mall\Framework\Core\ResultWrapper;
  16. use Mall\Framework\Core\StatusCode;
  17. use JinDouYun\Dao\Cart\DCart;
  18. use JinDouYun\Cache\ActivityLimitCache;
  19. use JinDouYun\Controller\Common\Logger;
  20. use JinDouYun\Model\Market\MVipCard;
  21. use JinDouYun\Model\System\MBasicSetup;
  22. use JinDouYun\Model\Market\MActivity;
  23. use JinDouYun\Model\Market\MUserCoupon;
  24. use JinDouYun\Model\System\MEnterpriseBindPayment;
  25. use JinDouYun\Model\Customer\MCustomer;
  26. use JinDouYun\Model\Customer\MShippingAddress;
  27. use JinDouYun\Model\GoodsManage\MSku;
  28. use JinDouYun\Model\Price\MPrice;
  29. use JinDouYun\Model\Stock\MInventory;
  30. use JinDouYun\Model\SysAreaChina\MSysAreaChina;
  31. use JinDouYun\Model\System\MDeliverySetting;
  32. use JinDouYun\Model\Goods\MGoods;
  33. use JinDouYun\Model\Shop\MShop;
  34. use JinDouYun\Cache\CustomerCache;
  35. use JinDouYun\Cache\GoodsBasicRelevant;
  36. use JinDouYun\Dao\Customer\DCustomer;
  37. use JinDouYun\Model\Cart\MPreferentialProcess;
  38. class MCart
  39. {
  40. /**
  41. * @var DCart
  42. */
  43. private $objDCart;
  44. /**
  45. * @var int 用户id
  46. */
  47. private $onlineUserId;
  48. /**
  49. * @var int 企业id
  50. */
  51. private $onlineEnterpriseId;
  52. /**
  53. * @var MCustomer
  54. */
  55. private $objMCustomer;
  56. /**
  57. * @var ActivityLimitCache
  58. */
  59. private $objActivityLimitCache;
  60. /**
  61. * @var bool
  62. */
  63. private $isFront;//是否是前台调用此Model 前台=>true
  64. /**
  65. * @var int 客户id
  66. */
  67. private $customerId;//用户对应的客户id
  68. /**
  69. * @var MActivity
  70. */
  71. private $objMActivity;
  72. /**
  73. * @var array 失效商品集合
  74. */
  75. private $invalidData = [];
  76. /**
  77. * @var array 操作类型
  78. */
  79. private static $type = [
  80. 'single' => 1,//单个商品
  81. 'shop' => 2,//按店铺
  82. 'all' => 3,//全选
  83. ];
  84. /**
  85. * @var array 阶梯价
  86. */
  87. private static $enabledLadder = [
  88. 'open' => 1,//启用阶梯价
  89. 'close' => 0,//未启用阶梯价
  90. ];
  91. /**
  92. * @var int[] 立即购买来源业务
  93. */
  94. public static $sourceType = [
  95. 'comBin' => 1,//组合套餐
  96. 'goods' => 2, // 普通商品
  97. ];
  98. /**
  99. * @var MSku
  100. */
  101. private $objMSku;
  102. /**
  103. * @var MGoods
  104. */
  105. private $objMGoods;
  106. /**
  107. * @var MBasicSetup
  108. */
  109. private $objMBasicSetup;
  110. /**
  111. * @var int
  112. */
  113. private $onlineUserDefaultDeliveryType = null;
  114. /**
  115. * @var float
  116. */
  117. private $onlineUserAddressCode = null;
  118. /**
  119. * @var float
  120. */
  121. private $freeExpressPrice = null;
  122. /**
  123. * @var string
  124. */
  125. private $cashierUId;
  126. /**
  127. * @var DCustomer
  128. */
  129. private $objDCustomer;
  130. /**
  131. * @var MCashierSettings
  132. */
  133. private $objMCashierSettings;
  134. /**
  135. * @var DCashierCustomerPrice
  136. */
  137. private $objDCashierCustomerPrice;
  138. /**
  139. * @var boolean
  140. */
  141. private $isCashier;
  142. /**
  143. * @var float 运费金额
  144. */
  145. private $expressMoney = 0;
  146. /**
  147. * @var array 店铺运费
  148. */
  149. private $expressShopMoney = [];
  150. /**
  151. * @var array
  152. */
  153. private $selectStateMap = [];
  154. /**
  155. * @var bool
  156. */
  157. private $preSale;
  158. /**
  159. * MCart constructor.
  160. * @param $onlineUserId
  161. * @param $onlineEnterpriseId
  162. * @param bool $isFront
  163. * @param string $areaCode
  164. * @param string $cashierUId
  165. * @param boolean $isCashier
  166. * @throws \Exception
  167. */
  168. public function __construct($onlineUserId, $onlineEnterpriseId, $isFront = false, $areaCode = '', $cashierUId = '', $isCashier = false)
  169. {
  170. $this->isCashier = $isCashier;
  171. $this->cashierUId = $cashierUId;
  172. $this->isFront = $isFront;
  173. $this->onlineUserId = $onlineUserId;
  174. $this->onlineEnterpriseId = $onlineEnterpriseId;
  175. $this->objDCart = new DCart('default');
  176. $this->objDCart->setTable($this->objDCart->get_Table() . '_' . $onlineEnterpriseId);
  177. $this->objMCustomer = new MCustomer($this->onlineEnterpriseId, $this->onlineUserId);
  178. $this->objActivityLimitCache = new ActivityLimitCache($this->onlineEnterpriseId);
  179. $this->objMActivity = new MActivity($this->onlineUserId, $this->onlineEnterpriseId, $areaCode);
  180. $this->objMSku = new MSku($this->onlineUserId, $this->onlineEnterpriseId);
  181. $this->objMGoods = new MGoods($this->onlineEnterpriseId, $this->isFront, $this->onlineUserId);
  182. $this->objMBasicSetup = new MBasicSetup($this->onlineEnterpriseId);
  183. $this->objDCustomer = new DCustomer();
  184. $this->objDCustomer->setTable('qianniao_customer_' . $this->onlineEnterpriseId);
  185. $this->objMCashierSettings = new MCashierSettings($this->onlineUserId, $this->onlineEnterpriseId);
  186. $this->objDCashierCustomerPrice = new DCashierCustomerPrice();
  187. $this->objDCashierCustomerPrice->setTable('qianniao_cashier_customer_price_' . $this->onlineEnterpriseId);
  188. self::getCustomerInfo();
  189. }
  190. /**
  191. * Doc: (des="")
  192. * User: XMing
  193. * Date: 2020/12/25
  194. * Time: 11:50 上午
  195. * @return ResultWrapper
  196. */
  197. public function getPreSale(): ResultWrapper
  198. {
  199. $objMBasicSetup = new MBasicSetup($this->onlineEnterpriseId);
  200. $setResult = $objMBasicSetup->getBasicField('preSale');
  201. $this->preSale = StatusCode::$delete;
  202. if (!$setResult->isSuccess()) {
  203. return ResultWrapper::fail($setResult->getData(), $setResult->getErrorCode());
  204. }
  205. $set = (array)$setResult->getData();
  206. $this->preSale = getArrayItem($set, 'preSale', StatusCode::$delete);
  207. if (empty($this->preSale)) $this->preSale = StatusCode::$delete;
  208. return ResultWrapper::success($set);
  209. }
  210. /**
  211. * 获取客户id
  212. */
  213. private function getCustomerInfo()
  214. {
  215. if ($this->isFront === false) {
  216. $this->customerId = $this->onlineUserId;//TODO()
  217. } else {
  218. $this->customerId = $this->objMCustomer->getCustomerIdByUserCenterId($this->onlineUserId);
  219. }
  220. }
  221. /**
  222. * 根据限购数量对数据进行分组
  223. * @param $data
  224. * @return array
  225. */
  226. private function checkLimitGroup($data)
  227. {
  228. if (empty($data)) return $data;
  229. $allMapping = [];
  230. foreach ($data as &$goods) {
  231. if ($goods['isActivityPrice'] == StatusCode::$standard) {
  232. $userLimit = $this->objActivityLimitCache->getLimit($goods['activityId'], $goods['goodsId'], $goods['skuId'], $this->onlineUserId);//用户限购数量
  233. $allowNum = $goods['limitNum'] - $userLimit;//还可以购买的数量
  234. $buyNum = $goods['buyNum'];//购买数量
  235. if ($buyNum >= $allowNum) {
  236. //拆分
  237. $goods['buyNum'] = $allowNum;
  238. $allMapping[] = $goods;
  239. $newGoods = $goods;
  240. if ($buyNum - $allowNum > 0) {
  241. $newGoods['buyNum'] = $buyNum - $allowNum;
  242. $newGoods['activityId'] = 0;//将活动id重置为0
  243. $newGoods['isActivityPrice'] = StatusCode::$delete;
  244. $allMapping[] = $newGoods;
  245. }
  246. } else {
  247. //限购等于加入数量
  248. $allMapping[] = $goods;
  249. }
  250. } else {
  251. $allMapping[] = $goods;
  252. }
  253. }
  254. return $allMapping;
  255. }
  256. /**
  257. * Doc: (des="小程序端加入购物车,最新")
  258. * User: XMing
  259. * Date: 2020/8/4
  260. * Time: 2:35 下午
  261. * @param array $params
  262. * @return ResultWrapper
  263. * @throws \Exception
  264. */
  265. public function addCartApi(array $params)
  266. {
  267. if (empty( $params['goodsData'] )) {
  268. return ResultWrapper::fail('加入购物车数据为空', ErrorCode::$paramError);
  269. }
  270. foreach ( $params['goodsData'] as $key => $data ){
  271. // 从商品表查询商品信息
  272. $goodsInfoResult = $this->objMGoods->getGoodsInfo($data['goodsId']);
  273. if (!$goodsInfoResult->isSuccess()) {
  274. return ResultWrapper::fail($goodsInfoResult->getData(), $goodsInfoResult->getErrorCode());
  275. }
  276. $goodsInfo = $goodsInfoResult->getData();
  277. // 验证此商品是否有效
  278. $checkResult = self::checkGoods($goodsInfo, $data, 'add');
  279. unset($data);
  280. if (!$checkResult->isSuccess()) {
  281. return ResultWrapper::fail($checkResult->getData(), $checkResult->getErrorCode());
  282. }
  283. $data = $checkResult->getData();
  284. // 判断此商品是否是活动商品
  285. $addMap = [
  286. 'goodsBasicId' => $data['goodsBasicId'],
  287. 'goodsId' => $data['goodsId'],
  288. 'skuId' => $data['skuId'],
  289. 'buyNum' => $data['buyNum'],
  290. 'shopId' => $data['shopId'],
  291. 'source' => $data['source'],
  292. 'setNum' => $data['setNum'],
  293. 'activityId' => $data['activityId'],
  294. 'goodsCode' => $data['goodsCode'],
  295. 'warehouseId' => $data['warehouseId']
  296. ];
  297. // 将加入购物车的数据进行分组[old=>在购物车中已存在,now=>新加入购物车商品]
  298. $groupResult = self::existCartAndGroup([$addMap]);
  299. if (!$groupResult->isSuccess()) {
  300. return ResultWrapper::fail($groupResult->getData(), $groupResult->getErrorCode());
  301. }
  302. $groupData = $groupResult->getData();
  303. if (empty($groupData)) {
  304. return ResultWrapper::fail('数组分组失败', ErrorCode::$paramError);
  305. }
  306. // 在购物车中已存在的商品
  307. $updates = isset($groupData['old']) ? $groupData['old'] : [];
  308. // 新加入购物车商品
  309. $inserts = isset($groupData['now']) ? $groupData['now'] : [];
  310. // 操作数据库
  311. $this->objDCart->beginTransaction();
  312. // 需要更新的数据
  313. if (!empty($updates)) {
  314. $update = array_shift($updates);
  315. $tableName = 'qianniao_cart_' . $this->onlineEnterpriseId;
  316. $sql = 'UPDATE ' . $tableName . ' SET buyNum = buyNum+' . $update['buyNum'] . '
  317. WHERE goodsId = ' . $update['goodsId'] . ' AND
  318. skuId = ' . $update['skuId'] . ' AND
  319. userCenterId = ' . $this->onlineUserId . ' AND
  320. activityId = ' . $update['activityId'];
  321. $updateRes = $this->objDCart->query($sql);
  322. if ($updateRes === false) {
  323. $this->objDCart->rollBack();
  324. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  325. }
  326. }
  327. // 需要插入的数据
  328. if (!empty($inserts)) {
  329. $insert = array_shift($inserts);
  330. $insertMap = [
  331. 'userCenterId' => $this->onlineUserId,
  332. 'selection' => StatusCode::$standard,
  333. 'goodsBasicId' => $insert['goodsBasicId'],
  334. 'goodsId' => $insert['goodsId'],
  335. 'skuId' => $insert['skuId'],
  336. 'buyNum' => $insert['buyNum'],
  337. 'shopId' => $insert['shopId'],
  338. 'source' => $insert['source'],
  339. 'activityId' => $insert['activityId'],
  340. 'goodsCode' => $insert['goodsCode'],
  341. 'warehouseId' => $insert['warehouseId']
  342. ];//要插入的数据
  343. $insertRes = $this->objDCart->insert($insertMap);
  344. if ($insertRes === false) {
  345. $this->objDCart->rollBack();
  346. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  347. }
  348. }
  349. }
  350. $this->objDCart->commit();
  351. return ResultWrapper::success('加入成功');
  352. }
  353. /**
  354. * Doc: (des="检测商品")
  355. * User: XMing
  356. * Date: 2020/8/4
  357. * Time: 3:21 下午
  358. * @param array $goodsData
  359. * @param array $addCart
  360. * @param string $action
  361. * @return ResultWrapper
  362. */
  363. private function checkGoods(array $goodsData, array $addCart, $action = 'add')
  364. {
  365. if (empty($goodsData)) {
  366. return ResultWrapper::fail('商品信息为空', ErrorCode::$paramError);
  367. }
  368. //验证商品的状态以及库存
  369. if ($goodsData['enableStatus'] == StatusCode::$delete || $goodsData['deleteStatus'] == StatusCode::$delete) {
  370. return ResultWrapper::fail('商品已下架', ErrorCode::$paramError);
  371. }
  372. $specMultiple = $goodsData['specMultiple'];//spec数据
  373. if (empty($specMultiple)) {
  374. return ResultWrapper::fail('商品规格信息获取失败', ErrorCode::$paramError);
  375. }
  376. $specMultipleMap = [];//商品规格映射数据
  377. foreach ($specMultiple as $value) {
  378. $specMultipleMap[$value['id']] = $value;
  379. }
  380. if (!isset($specMultipleMap[$addCart['skuId']])) {
  381. return ResultWrapper::fail('规格信息不存在', ErrorCode::$paramError);
  382. }
  383. $subBuyNumResult = self::getCartBuyNumBySku($addCart['skuId'], $this->onlineUserId);
  384. if (!$subBuyNumResult->isSuccess()) {
  385. return ResultWrapper::fail($subBuyNumResult->getData(), $subBuyNumResult->getErrorCode());
  386. }
  387. $subBuyNum = floatval($subBuyNumResult->getData());
  388. //是否开启预售
  389. switch ($action){
  390. case 'add':
  391. if ($goodsData['isDistribution'] == StatusCode::$delete){
  392. if ($specMultipleMap[$addCart['skuId']]['inventory'] < $addCart['buyNum'] + $subBuyNum) {
  393. //取库存最大数
  394. $allowNum = bcsub($specMultipleMap[$addCart['skuId']]['inventory'], $subBuyNum);//最多还可以增加的数量
  395. if ($allowNum <= 0) {
  396. $addCart['buyNum'] = 0;
  397. } else {
  398. $addCart['buyNum'] = $allowNum;
  399. }
  400. //return ResultWrapper::fail('商品库存不足', ErrorCode::$paramError);
  401. }
  402. }
  403. break;
  404. case 'update':
  405. if ($goodsData['isDistribution'] == StatusCode::$delete){
  406. if ($specMultipleMap[$addCart['skuId']]['inventory'] < $addCart['buyNum']) {
  407. return ResultWrapper::success($specMultipleMap[$addCart['skuId']]['inventory']);
  408. } else {
  409. return ResultWrapper::success($addCart['buyNum']);
  410. }
  411. }else{
  412. return ResultWrapper::success($addCart['buyNum']);
  413. }
  414. break;
  415. }
  416. $addCart['isActivity'] = $specMultipleMap[$addCart['skuId']]['isActivity'];//是否是活动商品
  417. $addCart['setNum'] = $specMultipleMap[$addCart['skuId']]['setNum'];//起订数量
  418. $addCart['warehouseId'] =getArrayItem($goodsData,'warehouseId','');
  419. switch ($specMultipleMap[$addCart['skuId']]['isActivity']) {
  420. case StatusCode::$standard:
  421. $addCart['activityId'] = $specMultipleMap[$addCart['skuId']]['activity']['activityId'];
  422. $addCart['limitNum'] = $specMultipleMap[$addCart['skuId']]['activity']['limitNum'];//商品活动限购数量
  423. break;
  424. case StatusCode::$delete:
  425. $addCart['activityId'] = 0;
  426. break;
  427. }
  428. return ResultWrapper::success($addCart);
  429. }
  430. /**
  431. * app加入购物车
  432. * @param $params
  433. * @return ResultWrapper
  434. * @throws \Exception
  435. */
  436. public function addCart($params)
  437. {
  438. $this->objDCart->beginTransaction();
  439. $goodsData = $params['goodsData'];
  440. $dbResult = self::checkCart($goodsData);
  441. if (!$dbResult->isSuccess()) {
  442. return ResultWrapper::fail($dbResult->getData(), $dbResult->getErrorCode());
  443. }
  444. $checkData = $dbResult->getData();
  445. //前台验证活动商品剩余数量,和用户限购数量
  446. if ($this->isFront === true) {
  447. //将数据拆分
  448. $checkData = self::checkLimitGroup($checkData);
  449. $dbResult = self::checkLimit($checkData);
  450. if (!$dbResult->isSuccess()) {
  451. return ResultWrapper::fail($dbResult->getData(), $dbResult->getErrorCode());
  452. }
  453. $dbResult = $dbResult->getData();
  454. $mapping = $dbResult['mapping'];
  455. $checkData = $dbResult['checkData'];
  456. }
  457. unset($dbResult);
  458. $dbResult = self::existCartAndGroup($checkData);
  459. if (!$dbResult->isSuccess()) {
  460. return ResultWrapper::fail($dbResult->getData(), $dbResult->getErrorCode());
  461. }
  462. $cartData = $dbResult->getData();//分组后的数据
  463. unset($dbResult);
  464. $dbResult = true;//初始化
  465. $oldCart = $cartData['old'];//旧的数据
  466. $nowCart = $cartData['now'];//新的数据
  467. if (!empty($oldCart)) {
  468. foreach ($oldCart as $key => $val) {
  469. $sql = "UPDATE qianniao_cart_{$this->onlineEnterpriseId} SET buyNum=buyNum+{$val['buyNum']} WHERE goodsId={$val['goodsId']} AND skuId={$val['skuId']} AND userCenterId={$this->onlineUserId} AND activityId={$val['activityId']}";
  470. $dbResult = $this->objDCart->query($sql);
  471. }
  472. if ($dbResult === false) {
  473. $this->objDCart->rollBack();
  474. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  475. }
  476. }
  477. if (!empty($nowCart)) {
  478. $insert = [];
  479. foreach ($nowCart as $key => $val) {
  480. $insert[] = [
  481. 'userCenterId' => $this->onlineUserId,
  482. 'selection' => StatusCode::$standard,
  483. 'skuId' => $val['skuId'],
  484. 'goodsCode' => $val['goodsCode'],
  485. 'goodsId' => $val['goodsId'],
  486. 'shopId' => $val['shopId'],
  487. 'buyNum' => $val['buyNum'],
  488. 'source' => $val['source'],
  489. 'goodsBasicId' => $val['goodsBasicId'],
  490. 'warehouseId' => $val['warehouseId'],
  491. 'activityId' => isset($val['activityId']) ? $val['activityId'] : 0,//活动id
  492. ];
  493. }
  494. $dbResult = $this->objDCart->insert($insert, true);
  495. if ($dbResult === false) {
  496. $this->objDCart->rollBack();
  497. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  498. }
  499. }
  500. $objCustomerCache = new CustomerCache();
  501. $objCustomerCache->incrInterestCustomer($this->customerId, $this->onlineEnterpriseId);
  502. //用户限购缓存
  503. if (!empty($mapping)) {
  504. self::userLimit($mapping);
  505. }
  506. $this->objDCart->commit();
  507. return ResultWrapper::success($dbResult);
  508. }
  509. /**
  510. * 后台加入购物车
  511. * @param $params
  512. * @return ResultWrapper
  513. * @throws \Exception
  514. */
  515. public function manageAddCart($params)
  516. {
  517. $this->objDCart->beginTransaction();
  518. $goodsData = $params['goodsData'];
  519. $dbResult = self::checkCart($goodsData);
  520. if (!$dbResult->isSuccess()) {
  521. return ResultWrapper::fail($dbResult->getData(), $dbResult->getErrorCode());
  522. }
  523. $checkData = $dbResult->getData();//验证后数据
  524. $dbResult = $this->existCartAndGroup($checkData);//数据分组
  525. if (!$dbResult->isSuccess()) {
  526. return ResultWrapper::fail($dbResult->getData(), $dbResult->getErrorCode());
  527. }
  528. $cartData = $dbResult->getData();//分组后的数据
  529. unset($dbResult);
  530. $dbResult = true;//初始化
  531. $update = $cartData['old'];//旧的数据
  532. $insert = $cartData['now'];//新的数据
  533. //更新数量
  534. if (!empty($update)) {
  535. foreach ($update as $row) {
  536. $dbResult = $this->objDCart->set_inc(
  537. 'buyNum',
  538. [
  539. 'goodsId' => $row['goodsId'],
  540. 'skuId' => $row['skuId'],
  541. 'userCenterId' => $this->onlineUserId,
  542. 'activityId' => $row['activityId'],
  543. ],
  544. $row['buyNum']
  545. );
  546. if ($dbResult === false) {
  547. $this->objDCart->rollBack();
  548. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  549. }
  550. }
  551. }
  552. //insert
  553. if (!empty($insert)) {
  554. $add = [];
  555. foreach ($insert as $row) {
  556. $add[] = [
  557. 'userCenterId' => $this->onlineUserId,
  558. 'selection' => StatusCode::$standard,
  559. 'skuId' => $row['skuId'],
  560. 'goodsCode' => $row['goodsCode'],
  561. 'goodsId' => $row['goodsId'],
  562. 'shopId' => $row['shopId'],
  563. 'buyNum' => $row['buyNum'],
  564. 'source' => $row['source'],
  565. 'goodsBasicId' => $row['goodsBasicId'],
  566. 'warehouseId' => $row['warehouseId'],
  567. 'activityId' => isset($val['activityId']) ? $row['activityId'] : 0,//活动id
  568. ];
  569. }
  570. $dbResult = $this->objDCart->insert($add, true);
  571. if ($dbResult === false) {
  572. $this->objDCart->rollBack();
  573. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  574. }
  575. }
  576. $objCustomerCache = new CustomerCache();
  577. $objCustomerCache->incrInterestCustomer($this->customerId, $this->onlineEnterpriseId);
  578. $this->objDCart->commit();
  579. return ResultWrapper::success($dbResult);
  580. }
  581. /**
  582. * adj 1:+ 2:-
  583. * isUpdate true false
  584. * step 调整量
  585. * @param $checkData
  586. * @param int $adj
  587. * @param bool $isUpdate
  588. * @return ResultWrapper
  589. */
  590. private function checkLimit($checkData, $adj = 1, $isUpdate = false, $step = null)
  591. {
  592. if (empty($checkData)) return ResultWrapper::success($checkData);
  593. $mapping = [];
  594. foreach ($checkData as $key => $goods) {
  595. $skuData = $goods['specMultiple'];
  596. $skuMapping = [];
  597. foreach ($skuData as $sku) {
  598. $skuMapping[$sku['id']] = $sku;
  599. }
  600. $thisSku = $skuMapping[$goods['skuId']];//当前加入购物车规格sku详情
  601. if (
  602. $goods['isActivityPrice'] == StatusCode::$delete ||
  603. ($thisSku['isActivity'] == StatusCode::$delete && $thisSku['activityId'] == 0)) {
  604. //活动商品,已购买完,或已限购,将以原价购买
  605. continue;
  606. }
  607. $activityId = $goods['activityId'];//活动id
  608. $activityDetails = $this->objActivityLimitCache->getActivity($activityId);
  609. if (empty($activityDetails)) {
  610. return ResultWrapper::fail('活动不存在', ErrorCode::$paramError);
  611. }
  612. if ($activityDetails['startTime'] > time()) {
  613. return ResultWrapper::fail($goods['title'] . '活动尚未开始', ErrorCode::$paramError);
  614. }
  615. if ($activityDetails['endTime'] < time()) {
  616. return ResultWrapper::fail($goods['title'] . '活动已结束', ErrorCode::$paramError);
  617. }
  618. //获取活动商品剩余数量
  619. $surplusNum = $this->objActivityLimitCache->getLen($activityId, $goods['goodsId'], $goods['skuId']);
  620. if ($surplusNum == 0) {
  621. return ResultWrapper::fail($goods['title'] . '抢光了', ErrorCode::$paramError);
  622. }
  623. if ($surplusNum < $goods['buyNum']) {
  624. return ResultWrapper::fail($goods['title'] . '活动剩余数量不足', ErrorCode::$paramError);
  625. }
  626. //获取每人限购数量
  627. $userLimit = self::getLimitNum($activityDetails, $goods['goodsId'], $goods['skuId']);//用户限购数量
  628. $userSurplusNum = $this->objActivityLimitCache->getLimit($activityId, $goods['goodsId'], $goods['skuId'], $this->onlineUserId);
  629. $buyNum = 0;//初始化
  630. if ($isUpdate) {
  631. if ($adj == 1) {
  632. //加操作
  633. if ($userLimit < ($userSurplusNum + $step)) {
  634. return ResultWrapper::fail($goods['title'] . '每人限购' . $userLimit . $thisSku['unitName'], ErrorCode::$paramError);
  635. }
  636. }
  637. $buyNum = $userSurplusNum + $step;
  638. } else {
  639. //addCart
  640. if ($userLimit < ($userSurplusNum + $goods['buyNum'])) {
  641. return ResultWrapper::fail($goods['title'] . '每人限购' . $userLimit . $thisSku['unitName'], ErrorCode::$paramError);
  642. }
  643. $buyNum = $userSurplusNum + $goods['buyNum'];//
  644. }
  645. $mapping[] = [
  646. 'activityId' => $activityId,
  647. 'goodsId' => $goods['goodsId'],
  648. 'skuId' => $goods['skuId'],
  649. 'buyNum' => $buyNum,
  650. ];
  651. }
  652. $data = [
  653. 'checkData' => $checkData,
  654. 'mapping' => $mapping,
  655. ];
  656. return ResultWrapper::success($data);
  657. }
  658. /**
  659. * 缓存用户限购
  660. * @param $data
  661. * @return mixed
  662. */
  663. private function userLimit($data)
  664. {
  665. $result = false;
  666. foreach ($data as $goods) {
  667. $result = $this->objActivityLimitCache->writeLimit($goods['activityId'], $goods['goodsId'], $goods['skuId'], $this->onlineUserId, $goods['buyNum']);
  668. }
  669. return $result;
  670. }
  671. /**
  672. * 获取商品的限购数量
  673. * @param $data
  674. * @param $goodsId
  675. * @param $skuId
  676. * @return int|mixed
  677. */
  678. private function getLimitNum($data, $goodsId, $skuId)
  679. {
  680. if (empty($data)) return $data;
  681. $goodsData = $data['activityGoods'];
  682. $mapping = [];
  683. foreach ($goodsData as $goods) {
  684. $mapping[$goods['goodsId'] . $goods['skuId']] = $goods;
  685. }
  686. return isset($mapping[$goodsId . $skuId]['limitNum']) ? $mapping[$goodsId . $skuId]['limitNum'] : 0;
  687. }
  688. /**
  689. * 检测购物车商品(最新的方法)
  690. * @param $data
  691. * @return ResultWrapper
  692. * @throws \Exception
  693. */
  694. public function checkCart($data)
  695. {
  696. if (empty($data)) return ResultWrapper::fail('购物车数据为空', ErrorCode::$paramError);
  697. $objMGoods = new MGoods($this->onlineEnterpriseId, $this->isFront, $this->onlineUserId);
  698. //验证商品数据
  699. foreach ($data as $key => $val) {
  700. //获取商品详情
  701. $details = $objMGoods->getGoodsInfo($val['goodsId']);
  702. if (!$details->isSuccess()) {
  703. return ResultWrapper::fail($details->getData(), $details->getErrorCode());
  704. }
  705. $goods = $details->getData();//商品数据
  706. if (empty($details)) {
  707. return ResultWrapper::fail($val['goodsCode'] . '查询商品失败', ErrorCode::$paramError);
  708. }
  709. //验证商品状态
  710. if ($goods['enableStatus'] == StatusCode::$delete || $goods['deleteStatus'] == StatusCode::$delete) {
  711. return ResultWrapper::fail($goods['title'] . ' 已下架', ErrorCode::$paramError);
  712. }
  713. $specMultiple = $goods['specMultiple'];//spec数据
  714. $specMapping = [];//Map
  715. foreach ($specMultiple as $spec) {
  716. $specMapping[$spec['id']] = $spec;
  717. }
  718. if (!isset($specMapping[$val['skuId']])) {
  719. Logger::logs(E_USER_ERROR, '规格获取失败', __CLASS__, __LINE__, $specMapping);
  720. return ResultWrapper::fail($goods['title'] . '规格获取失败', ErrorCode::$paramError);
  721. }
  722. //验证商品库存
  723. if ($this->preSale == StatusCode::$delete) {
  724. if ($specMapping[$val['skuId']]['inventory'] < $val['buyNum']) {
  725. $specName = self::createSpecName($specMapping[$val['skuId']]);
  726. return ResultWrapper::fail($goods['title'] . $specName . ' 库存不足', ErrorCode::$paramError);
  727. }
  728. }
  729. $data[$key]['basicGoodsId'] = $val['goodsBasicId'];//为了兼容之前的代码
  730. $data[$key]['skuData'] = [];//兼容之前数据
  731. $data[$key]['specMultiple'] = $specMultiple;//spec
  732. $data[$key]['warehouseId'] = $goods['warehouseId'];//店铺所在仓库
  733. $data[$key]['title'] = $goods['title'];//商品名称
  734. $data[$key]['setNum'] = $specMapping[$val['skuId']]['setNum'];//加入购物车起订量
  735. $data[$key]['activityId'] = 0;//初始化活动id
  736. //todo(优化秒杀商品活动)
  737. if ($specMapping[$val['skuId']]['isActivity'] == StatusCode::$standard) {
  738. //商品存在活动时,没有起订量
  739. $data[$key]['setNum'] = 1;
  740. }
  741. $data[$key]['inventory'] = $specMapping[$val['skuId']]['inventory'];//加入购物车商品规格的可用库存
  742. $data[$key]['isActivityPrice'] = $specMapping[$val['skuId']]['isActivityPrice'];
  743. if ($specMapping[$val['skuId']]['isActivityPrice'] == StatusCode::$standard) {
  744. $data[$key]['activityId'] = $specMapping[$val['skuId']]['activity']['activityId'];
  745. }
  746. $data[$key]['limitNum'] = $specMapping[$val['skuId']]['limitNum'];//商品限购数量
  747. }
  748. return ResultWrapper::success($data);
  749. }
  750. /**
  751. * 生成属性名
  752. * @param $data
  753. * @return mixed|string
  754. */
  755. public static function createSpecName($data)
  756. {
  757. if (empty($data)) {
  758. return '';
  759. }
  760. $unitName = $data['unitName'];
  761. if (!empty($data['specGroup'])) {
  762. $arrSpecName = array_column($data['specGroup'], 'specValueName');
  763. $specName = rtrim(implode('_', $arrSpecName), '_');
  764. $unitName .= '_' . $specName;
  765. }
  766. return $unitName;
  767. }
  768. /**
  769. * 将加入购物车的数据进行分组[old=>在购物车中已存在,now=>新加入购物车商品]
  770. * @param $nowData [加入购物车的数据]
  771. * @return ResultWrapper
  772. */
  773. private function existCartAndGroup($nowData)
  774. {
  775. // 查询当前购物车所有商品数据
  776. $dbResult = self::getCartByUid();
  777. if (!$dbResult->isSuccess()) {
  778. return ResultWrapper::fail('获取购物车数据失败', ErrorCode::$dberror);
  779. }
  780. $oldCartData = $dbResult->getData();
  781. // 对所有商品数据生成hash值,用于判断新加入的商品是否已经存在于购物车之中了
  782. $allHash = [];
  783. foreach ($oldCartData as $key => $val) {
  784. $allHash[] = md5($val['goodsId'] . $val['shopId'] . $val['skuId'] . $val['activityId']);
  785. }
  786. $old = [];//旧的数据
  787. $now = [];//新的数据
  788. foreach ($nowData as $key => &$val) {
  789. $md5 = md5($val['goodsId'] . $val['shopId'] . $val['skuId'] . $val['activityId']);
  790. if (in_array($md5, $allHash)) {
  791. $old[] = $val;
  792. } else {
  793. //之前购物车中没有此商品,检查起订量
  794. if ($val['setNum'] != 0) {
  795. //具有起订量
  796. if ($val['buyNum'] < $val['setNum']) {
  797. $val['buyNum'] = $val['setNum'];
  798. }
  799. }
  800. $now[] = $val;
  801. }
  802. }
  803. $groupData = [
  804. 'old' => $old,
  805. 'now' => $now
  806. ];
  807. return ResultWrapper::success($groupData);
  808. }
  809. /**
  810. * Doc: (des="更新购车商品数量")
  811. * User: XMing
  812. * Date: 2020/8/6
  813. * Time: 9:43 上午
  814. * @param array $params
  815. * @return ResultWrapper
  816. * @throws \Exception
  817. */
  818. public function updateBuyNumApi(array $params)
  819. {
  820. // 如果数量改成0则删除
  821. if (bccomp($params['buyNum'], 0, 0) === 0) {
  822. $dbResult = $this->objDCart->delete(['id' => $params['cartId']]);
  823. if ($dbResult === false) {
  824. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  825. }
  826. return ResultWrapper::success('操作成功');
  827. }
  828. $cart = $this->objDCart->get($params['cartId']);
  829. if ($cart === false) {
  830. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  831. }
  832. if (empty($cart)) {
  833. return ResultWrapper::success(true);
  834. }
  835. $goodsInfoResult = $this->objMGoods->getGoodsInfo($cart['goodsId']);
  836. if (!$goodsInfoResult->isSuccess()) {
  837. return ResultWrapper::fail($goodsInfoResult->getData(), $goodsInfoResult->getErrorCode());
  838. }
  839. $goodsInfo = $goodsInfoResult->getData();
  840. $checkResult = self::checkGoods($goodsInfo, [
  841. 'skuId' => $cart['skuId'],
  842. 'buyNum' => $params['buyNum'],
  843. ], 'update');
  844. unset($data);
  845. if (!$checkResult->isSuccess()) {
  846. return ResultWrapper::fail($checkResult->getData(), $checkResult->getErrorCode());
  847. }
  848. $allBuyNum = $checkResult->getData();
  849. $params['buyNum'] = $allBuyNum;
  850. $dbResult = $this->objDCart->update(['buyNum' => $params['buyNum']], $params['cartId']);
  851. if ($dbResult === false) {
  852. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  853. }
  854. return ResultWrapper::success('操作成功');
  855. }
  856. /**
  857. * 修改购物车商品购买数量
  858. * @param $params
  859. * @return ResultWrapper
  860. * @throws \Exception
  861. */
  862. public function updateBuyNum($params)
  863. {
  864. if (bccomp($params['buyNum'], 0, 0) === 0) {
  865. $dbResult = $this->objDCart->delete(['id' => $params['cartId']]);
  866. if ($dbResult === false) {
  867. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  868. }
  869. return ResultWrapper::success('操作成功');
  870. } else {
  871. $goods = self::getCartInventory(['id' => $params['cartId']]);
  872. if (!$goods->isSuccess()) {
  873. return ResultWrapper::fail($goods->getData(), ErrorCode::$dberror);
  874. }
  875. $goods = $goods->getData();
  876. $inventoryNum = isset($goods[0]['inventory']) ? $goods[0]['inventory'] : 0;//商品剩余库存
  877. $setNum = isset($goods[0]['setNum']) ? $goods[0]['setNum'] : 0;//商品规格起订数量
  878. $title = isset($goods[0]['title']) ? $goods[0]['title'] : '';//商品名称
  879. if (bccomp($inventoryNum, $params['buyNum'], 8) === -1) {
  880. return ResultWrapper::fail('商品库存不足', ErrorCode::$paramError);
  881. }
  882. if (bccomp($params['buyNum'], $setNum, 0) === -1) {
  883. return ResultWrapper::fail($title . '最小起订数量' . $setNum, ErrorCode::$paramError);
  884. }
  885. if ($this->isFront) {
  886. $dbResult = $this->objDCart->get(['id' => $params['cartId']]);
  887. if ($dbResult === false) {
  888. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  889. }
  890. $step = bcsub($params['buyNum'], $dbResult['buyNum'], 0);//调整量
  891. //所有减操作正常进行
  892. if (bccomp($params['buyNum'], $dbResult['buyNum']) === 0) {
  893. return ResultWrapper::success('操作成功');
  894. } elseif (bccomp($params['buyNum'], $dbResult['buyNum'], 0) === -1) {
  895. $adj = 2;//减操作
  896. $result = $this->objDCart->update(['buyNum' => $params['buyNum']], ['id' => $params['cartId']]);
  897. if ($result === false) {
  898. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  899. }
  900. return ResultWrapper::success('操作成功');
  901. } elseif (bccomp($params['buyNum'], $dbResult['buyNum'], 0) === 1) {
  902. $adj = 1;//加操作
  903. $insert = [
  904. 'goodsId' => $dbResult['goodsId'],
  905. 'goodsBasicId' => $dbResult['goodsBasicId'],
  906. 'shopId' => $dbResult['shopId'],
  907. 'source' => $dbResult['source'],
  908. 'skuId' => $dbResult['skuId'],
  909. 'buyNum' => $step,
  910. 'goodsCode' => $dbResult['goodsCode']
  911. ];
  912. $result = self::addCart(['goodsData' => [$insert]]);
  913. if (!$result->isSuccess()) {
  914. return ResultWrapper::fail($result->getData(), $result->getErrorCode());
  915. }
  916. return ResultWrapper::success('操作成功');
  917. }
  918. } else {
  919. $dbResult = $this->objDCart->update(['buyNum' => $params['buyNum']], $params['cartId']);
  920. if ($dbResult === false) {
  921. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  922. }
  923. return ResultWrapper::success('操作成功');
  924. }
  925. }
  926. }
  927. /**
  928. * Doc: (des="获取用户的购物车数据")
  929. * User: XMing
  930. * Date: 2020/8/5
  931. * Time: 3:15 下午
  932. * @param integer $isZero
  933. * @param boolean $isCashier
  934. * @return ResultWrapper
  935. * @throws \Exception
  936. */
  937. public function getCartByUserCenterIdApi(): ResultWrapper
  938. {
  939. // 查询购物车数据
  940. $sql = 'SELECT id,goodsId,goodsCode,buyNum,shopId,source,goodsBasicId,selection,skuId,warehouseId,activityId,cashierUid FROM qianniao_cart_'.$this->onlineEnterpriseId.' WHERE userCenterId = '.$this->onlineUserId.' FOR UPDATE';
  941. $cartList = $this->objDCart->query($sql);
  942. if ($cartList === false){
  943. return ResultWrapper::fail($this->objDCart->error(),ErrorCode::$dberror);
  944. }
  945. if (empty($cartList)) {
  946. return ResultWrapper::success(['data' => [], 'total' => 0]);
  947. }
  948. // 提取活动ids
  949. $activityIds = [];
  950. foreach ($cartList as $item){
  951. if(!empty($item['activityId']) && !in_array($item['activityId'],$activityIds)){
  952. $activityIds[] = $item['activityId'];
  953. }
  954. }
  955. if (!empty($activityIds)){
  956. $groupResult = self::cartGroupData($cartList);
  957. if (!$groupResult->isSuccess()) {
  958. return ResultWrapper::fail($groupResult->getData(), $groupResult->getErrorCode());
  959. }
  960. $cartList = $groupResult->getData();
  961. if (empty($cartList)) {
  962. return ResultWrapper::success(['data' => [], 'total' => 0]);
  963. }
  964. }
  965. $dataResult = self::formatGoodsAndShop($cartList);
  966. if (!$dataResult->isSuccess()) {
  967. return ResultWrapper::fail($dataResult->getData(), $dataResult->getErrorCode());
  968. }
  969. $data = $dataResult->getData();
  970. $return = [
  971. 'data' => $data,
  972. 'total' => empty($data) ? 0 : count($data),
  973. ];
  974. return ResultWrapper::success($return);
  975. }
  976. /**
  977. * Doc: (des="抹零操作")
  978. * User: XMing
  979. * Date: 2020/9/12
  980. * Time: 7:08 下午
  981. * @param array $data
  982. * @param int $isZero
  983. * @return ResultWrapper
  984. */
  985. private function buildZero($data, $isZero)
  986. {
  987. //是否开启抹零
  988. $data['rem_money'] = '0.00';
  989. $settingResult = $this->objMCashierSettings->get();
  990. if (!$settingResult->isSuccess()) {
  991. return ResultWrapper::fail($settingResult->getData(), $settingResult->getErrorCode());
  992. }
  993. $setting = $settingResult->getData();
  994. if (!is_array($setting)) {
  995. //不是数组时,说明未配置
  996. return ResultWrapper::success($data);
  997. }
  998. if (!isset($setting['add_form'])) {
  999. return ResultWrapper::fail('收银台配置错误', ErrorCode::$paramError);
  1000. }
  1001. if (!isset($setting['add_form']['zero_set'])) {
  1002. return ResultWrapper::fail('收银台参数配置错误', ErrorCode::$paramError);
  1003. }
  1004. $zeroSet = $setting['add_form']['zero_set'];
  1005. if ($zeroSet['status'] == StatusCode::$delete) {
  1006. //没有开启抹零,前台需要在抹零那判断是否开启
  1007. return ResultWrapper::success($data);
  1008. }
  1009. $payMoney = $data['payMoney'];
  1010. if ($zeroSet['auto_zero'] == StatusCode::$standard) {
  1011. //开启了自动抹零
  1012. switch ($zeroSet['type']) {
  1013. case 1:
  1014. //分
  1015. $newPatMoney = bcadd($payMoney, 0, 1);
  1016. break;
  1017. case 2:
  1018. //角
  1019. $newPatMoney = bcadd($payMoney, 0, 0);
  1020. break;
  1021. case 3:
  1022. //到角
  1023. $newPatMoney = round($payMoney, 1);
  1024. break;
  1025. case 4:
  1026. //到元
  1027. $newPatMoney = round($payMoney, 0);
  1028. break;
  1029. default:
  1030. $newPatMoney = 0;
  1031. break;
  1032. }
  1033. $rem_money = bcsub($payMoney, $newPatMoney, 2);
  1034. $data['payMoney'] = $newPatMoney;
  1035. $data['rem_money'] = $rem_money;
  1036. } else {
  1037. if ($isZero == StatusCode::$standard) {
  1038. //手动抹零
  1039. switch ($zeroSet['type']) {
  1040. case 1:
  1041. //分
  1042. $newPatMoney = bcadd($payMoney, 0, 1);
  1043. break;
  1044. case 2:
  1045. //角
  1046. $newPatMoney = bcadd($payMoney, 0, 0);
  1047. break;
  1048. case 3:
  1049. //到角
  1050. $newPatMoney = round($payMoney, 1);
  1051. break;
  1052. case 4:
  1053. //到元
  1054. $newPatMoney = round($payMoney, 0);
  1055. break;
  1056. default:
  1057. $newPatMoney = 0;
  1058. break;
  1059. }
  1060. $rem_money = bcsub($payMoney, $newPatMoney, 2);
  1061. $data['payMoney'] = $newPatMoney;
  1062. $data['rem_money'] = $rem_money;
  1063. }
  1064. }
  1065. return ResultWrapper::success($data);
  1066. }
  1067. /**
  1068. * Doc: (des="将购物车的数据进行分组 活动商品的限购级别以及价格,全部都基于此方法组装的数据")
  1069. * User: XMing
  1070. * Date: 2020/8/5
  1071. * Time: 3:21 下午
  1072. * @param array $data
  1073. * @return ResultWrapper
  1074. */
  1075. private function cartGroupData(array $data)
  1076. {
  1077. if (empty($data)) {
  1078. return ResultWrapper::success([]);
  1079. }
  1080. // 获取限购级别设置项
  1081. $BasicSetupResult = $this->objMBasicSetup->getBasicField('limitLevel');
  1082. if (!$BasicSetupResult->isSuccess()) {
  1083. return ResultWrapper::fail($BasicSetupResult->getData(), $BasicSetupResult->getErrorCode());
  1084. }
  1085. $BasicSetup = $BasicSetupResult->getData();//之前的企业可鞥未设置此字段,给默认值5
  1086. $limitLevel = isset($BasicSetup['limitLevel']) ? $BasicSetup['limitLevel'] : StatusCode::$standard;//限购级别
  1087. $selectStateMap = [];
  1088. //将同sku合并到一起s
  1089. $dataMap = [];
  1090. $skuBuyMap = [];
  1091. foreach ($data as $datum) {
  1092. $selectStateMap[$datum['skuId'] . ':' . $datum['activityId']] = $datum['selection'];
  1093. $dataMap[$datum['skuId']] = [
  1094. 'id' => $datum['id'],
  1095. 'goodsId' => $datum['goodsId'],
  1096. 'goodsCode' => $datum['goodsCode'],
  1097. 'shopId' => $datum['shopId'],
  1098. 'source' => $datum['source'],
  1099. 'goodsBasicId' => $datum['goodsBasicId'],
  1100. 'selection' => $datum['selection'],
  1101. 'skuId' => $datum['skuId'],
  1102. 'warehouseId' => $datum['warehouseId'],
  1103. 'activityId' => 0,
  1104. ];
  1105. $skuBuyMap[$datum['skuId']][] = $datum['buyNum'];
  1106. }
  1107. $this->selectStateMap = $selectStateMap;
  1108. foreach ($dataMap as $skuId => $value) {
  1109. $dataMap[$skuId]['buyNum'] = array_sum($skuBuyMap[$skuId]);
  1110. }
  1111. $data = array_values($dataMap);
  1112. //获取客户信息
  1113. $customer = $this->objDCustomer->get(['userCenterId' => $this->onlineUserId], 'id,type');
  1114. if ($customer === false) {
  1115. return ResultWrapper::fail($this->objDCustomer->error(), ErrorCode::$dberror);
  1116. }
  1117. if (empty($customer)) {
  1118. $customer = [];
  1119. }
  1120. //获取商品是否是活动商品
  1121. $allSkuIds = [];
  1122. foreach ($data as $datum) {
  1123. $allSkuIds[] = $datum['skuId'];
  1124. }
  1125. $activityResult = $this->objMActivity->getActivity([
  1126. 'skuIds' => implode(',', $allSkuIds),
  1127. 'customerType' => isset($customer['type']) ? $customer['type'] : 0,
  1128. ]);
  1129. if (!$activityResult->isSuccess()) {
  1130. return ResultWrapper::fail($activityResult->getData(), $activityResult->getErrorCode());
  1131. }
  1132. $activity = $activityResult->getData();
  1133. $activityMap = [];
  1134. foreach ($activity as $item) {
  1135. $activityMap[$item['skuId']] = $item;
  1136. }
  1137. $update = [];
  1138. foreach ($data as $item) {
  1139. if (!isset($activityMap[$item['skuId']])) {
  1140. //没有活动不用处理
  1141. $update[] = self::buildData($item, $item['buyNum'], 0, $this->onlineUserId);
  1142. continue;
  1143. }
  1144. //是活动商品
  1145. //1。活动商品数量是否足够
  1146. $len = $this->objActivityLimitCache->getLen($activityMap[$item['skuId']]['activityId'], $item['goodsId'], $item['skuId']);
  1147. if ($len == 0) {
  1148. //活动商品已购买完
  1149. $update[] = self::buildData($item, $item['buyNum'], 0, $this->onlineUserId);
  1150. continue;
  1151. }
  1152. //2。剩余数量
  1153. //2.1 剩余数量足够
  1154. if ($len >= $item['buyNum']) {
  1155. //获取用户已购数量
  1156. $userLimit = $this->objActivityLimitCache->getLimit($activityMap[$item['skuId']]['activityId'], $item['goodsId'], $item['skuId'], $this->onlineUserId);
  1157. //3。用户限购
  1158. switch ($limitLevel) {
  1159. case StatusCode::$standard:
  1160. if ($activityMap[$item['skuId']]['limitNum'] == 0) {
  1161. $update[] = self::buildData($item, $item['buyNum'], 0, $this->onlineUserId);
  1162. continue 2;
  1163. }
  1164. //3。1 活动期间限购
  1165. if ($userLimit > $activityMap[$item['skuId']]['limitNum']) {
  1166. //已经购买过活动商品了,剩下的都恢复原价
  1167. $update[] = self::buildData($item, $item['buyNum'], 0, $this->onlineUserId);
  1168. continue 2;
  1169. }
  1170. $allowBuyNum = $activityMap[$item['skuId']]['limitNum'] - $userLimit;
  1171. if ($allowBuyNum == 0) {
  1172. $update[] = self::buildData($item, $item['buyNum'], 0, $this->onlineUserId);
  1173. continue 2;
  1174. }
  1175. if ($item['buyNum'] <= $allowBuyNum) {
  1176. $update[] = self::buildData($item, $item['buyNum'], $activityMap[$item['skuId']]['activityId'], $this->onlineUserId);
  1177. continue 2;
  1178. }
  1179. if ($item['buyNum'] > $allowBuyNum) {
  1180. //分解
  1181. $update[] = self::buildData($item, $allowBuyNum, $activityMap[$item['skuId']]['activityId'], $this->onlineUserId);
  1182. $update[] = self::buildData($item, $item['buyNum'] - $allowBuyNum, 0, $this->onlineUserId);//原价不参与活动
  1183. continue 2;
  1184. }
  1185. break;
  1186. case StatusCode::$delete:
  1187. //3。2 单笔订单限购买
  1188. if ($activityMap[$item['skuId']]['limitNum'] < $item['buyNum']) {
  1189. //购车中的商品大于单笔限购,分解
  1190. $update[] = self::buildData($item, $activityMap[$item['skuId']]['limitNum'], $activityMap[$item['skuId']]['activityId'], $this->onlineUserId);
  1191. $update[] = self::buildData($item, $item['buyNum'] - $activityMap[$item['skuId']]['limitNum'], 0, $this->onlineUserId);
  1192. continue 2;
  1193. }
  1194. if ($activityMap[$item['skuId']]['limitNum'] >= $item['buyNum']) {
  1195. //都是活动价格
  1196. $update[] = self::buildData($item, $item['buyNum'], $activityMap[$item['skuId']]['activityId'], $this->onlineUserId);
  1197. continue 2;
  1198. }
  1199. break;
  1200. }
  1201. } else {
  1202. //2。2 剩余数量不足
  1203. $update[] = self::buildData($item, $item['buyNum'], 0, $this->onlineUserId);
  1204. continue;
  1205. }
  1206. }
  1207. if (empty($update)) {
  1208. return ResultWrapper::fail('获取购物车数据失败', ErrorCode::$paramError);
  1209. }
  1210. $this->objDCart->beginTransaction();
  1211. $deleteRes = $this->objDCart->delete(['userCenterId' => $this->onlineUserId]);
  1212. if ($deleteRes === false) {
  1213. $this->objDCart->rollBack();
  1214. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1215. }
  1216. $insertRes = $this->objDCart->insert($update, true);
  1217. if ($insertRes === false) {
  1218. $this->objDCart->rollBack();
  1219. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1220. }
  1221. $this->objDCart->commit();
  1222. $where['userCenterId'] = $this->onlineUserId;
  1223. $cartList = $this->objDCart->select($where);
  1224. if ($cartList === false) {
  1225. $this->objDCart->rollBack();
  1226. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1227. }
  1228. return ResultWrapper::success($cartList);
  1229. }
  1230. /**
  1231. * Doc: (des="")
  1232. * User: XMing
  1233. * Date: 2020/8/5
  1234. * Time: 5:22 下午
  1235. * @param array $item
  1236. * @param int $buyNum
  1237. * @param int $activityId
  1238. * @param int $userCenterId
  1239. * @return array
  1240. */
  1241. private function buildData(array $item, int $buyNum, int $activityId, int $userCenterId)
  1242. {
  1243. $data = [
  1244. 'goodsId' => $item['goodsId'],
  1245. 'goodsCode' => $item['goodsCode'],
  1246. 'shopId' => $item['shopId'],
  1247. 'source' => $item['source'],
  1248. 'goodsBasicId' => $item['goodsBasicId'],
  1249. 'selection' => isset($this->selectStateMap[$item['skuId'] . ':' . $activityId]) ? $this->selectStateMap[$item['skuId'] . ':' . $activityId] : StatusCode::$delete,
  1250. 'skuId' => $item['skuId'],
  1251. 'warehouseId' => $item['warehouseId'],
  1252. 'activityId' => $activityId,
  1253. 'buyNum' => $buyNum,
  1254. 'userCenterId' => $userCenterId
  1255. ];
  1256. return $data;
  1257. }
  1258. /**
  1259. * app获取购物车内的数据
  1260. * @return ResultWrapper
  1261. * @throws \Exception
  1262. */
  1263. public function getCartByUserCenterId()
  1264. {
  1265. $result = $this->objDCart->select(['userCenterId' => $this->onlineUserId], 'id,goodsId,goodsCode,buyNum,shopId,source,goodsBasicId,selection,skuId,warehouseId,activityId', 'createTime DESC');
  1266. if ($result === false) {
  1267. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1268. }
  1269. $result = self::formatMerge($result);
  1270. if (!$result->isSuccess()) {
  1271. return ResultWrapper::fail($result->getData(), $result->getErrorCode());
  1272. }
  1273. $dataResult = self::formatGoodsAndShop($result->getData());
  1274. if (!$dataResult->isSuccess()) {
  1275. return ResultWrapper::fail($dataResult->getData(), $dataResult->getErrorCode());
  1276. }
  1277. $data = $dataResult->getData();
  1278. $return = [
  1279. 'data' => $data,
  1280. 'total' => empty($data) ? 0 : count($data),
  1281. ];
  1282. return ResultWrapper::success($return);
  1283. }
  1284. /**
  1285. * 后台获取购车数据
  1286. * @return ResultWrapper
  1287. * @throws \Exception
  1288. */
  1289. public function getManageCartByUserCenterId()
  1290. {
  1291. $result = $this->objDCart->select(['userCenterId' => $this->onlineUserId], 'id,goodsId,goodsCode,buyNum,shopId,goodsBasicId,selection,skuId,warehouseId,activityId', 'createTime DESC');
  1292. if ($result === false) {
  1293. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1294. }
  1295. $dataResult = self::formatGoodsAndShop($result);
  1296. if (!$dataResult->isSuccess()) {
  1297. return ResultWrapper::fail($dataResult->getData(), $dataResult->getErrorCode());
  1298. }
  1299. $data = $dataResult->getData();
  1300. $return = [
  1301. 'data' => $data,
  1302. 'total' => empty($data) ? 0 : count($data),
  1303. ];
  1304. return ResultWrapper::success($return);
  1305. }
  1306. /**
  1307. * 获取当前用户的购物车数据
  1308. */
  1309. private function getCartByUid()
  1310. {
  1311. $result = $this->objDCart->select(['userCenterId' => $this->onlineUserId], 'id,goodsId,goodsCode,buyNum,shopId,goodsBasicId,selection,skuId,warehouseId,activityId,cashierUid', 'createTime DESC');
  1312. if ($result === false) {
  1313. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1314. }
  1315. return ResultWrapper::success($result);
  1316. }
  1317. /**
  1318. * 更新选中状态
  1319. * @param $params
  1320. * @return ResultWrapper
  1321. * @throws \Exception
  1322. */
  1323. public function updateSelection($params)
  1324. {
  1325. $dbResult = false;
  1326. switch ($params['type']) {
  1327. case self::$type['single']:
  1328. if (empty($params['id'])) {
  1329. return ResultWrapper::fail('缺少cartId', ErrorCode::$paramError);
  1330. }
  1331. $dbResult = $this->objDCart->update(['selection' => $params['selection']], $params['id']);
  1332. break;
  1333. case self::$type['shop']:
  1334. if (empty($params['shopId'])) {
  1335. return ResultWrapper::fail('缺少shopId', ErrorCode::$paramError);
  1336. }
  1337. $dbResult = $this->objDCart->update(['selection' => $params['selection']], ['shopId' => $params['shopId'], 'userCenterId' => $this->onlineUserId]);
  1338. break;
  1339. case self::$type['all']:
  1340. $dbResult = $this->objDCart->update(['selection' => $params['selection']], ['userCenterId' => $this->onlineUserId]);
  1341. break;
  1342. }
  1343. if ($dbResult === false) {
  1344. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1345. }
  1346. return ResultWrapper::success($dbResult);
  1347. }
  1348. /**
  1349. * 删除购物车中商品(可批量)
  1350. * @param $ids
  1351. * @param boolean $order 是否是来自订单
  1352. * @return ResultWrapper
  1353. */
  1354. public function delCart($ids, $order = false)
  1355. {
  1356. $dbResult = $this->objDCart->select($ids, 'id,goodsId,buyNum,skuId,activityId');
  1357. if ($dbResult === false) {
  1358. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1359. }
  1360. //限购减对应数据
  1361. if ($order === true) {
  1362. foreach ($dbResult as $goods) {
  1363. if ($goods['activityId'] != 0) {
  1364. $userSurplusNum = $this->objActivityLimitCache->getLimit($goods['activityId'], $goods['goodsId'], $goods['skuId'], $this->onlineUserId);
  1365. $mapping[] = [
  1366. 'activityId' => $goods['activityId'],
  1367. 'goodsId' => $goods['goodsId'],
  1368. 'skuId' => $goods['skuId'],
  1369. 'buyNum' => $userSurplusNum + $goods['buyNum'],
  1370. ];
  1371. self::userLimit($mapping);
  1372. }
  1373. }
  1374. }
  1375. $dbResult = $this->objDCart->delete($ids);
  1376. if ($dbResult === false) {
  1377. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1378. }
  1379. return ResultWrapper::success($dbResult);
  1380. }
  1381. /**
  1382. * Doc: (des="判断字符串是否是一个整数")
  1383. * User: XMing
  1384. * Date: 2020/10/12
  1385. * Time: 10:29 上午
  1386. * @param $num
  1387. * @return bool
  1388. */
  1389. private static function isInteger($num)
  1390. {
  1391. if ($num - floor($num) != 0) {
  1392. return false;
  1393. }
  1394. return true;
  1395. }
  1396. /**
  1397. * 拼装购物车数据(商铺->商品->规格->库存->价格->分组)
  1398. * 此方法正在修改,勿动
  1399. * @param $data
  1400. * @return ResultWrapper
  1401. * @throws \Exception
  1402. */
  1403. private function formatGoodsAndShop($data, $userCouponId = null, $vipCardId = null)
  1404. {
  1405. foreach ($data as &$value) {
  1406. $value['buyNum'] = self::isInteger($value['buyNum']) ? (int)$value['buyNum'] : $value['buyNum'];
  1407. }
  1408. unset($value);
  1409. $result = self::formatShop($data);//格式化店铺数据
  1410. $result = self::formatGoods($result);//格式化商品数据
  1411. if ($this->isFront === true) {
  1412. $result = self::calExpress($result);
  1413. if (!$result->isSuccess()) {
  1414. return ResultWrapper::fail($result->getData(), $result->getErrorCode());
  1415. }
  1416. $result = $result->getData();
  1417. }
  1418. // 价格处理
  1419. $priceResult = self::formatPrice($result);
  1420. if (!$priceResult->isSuccess()) {
  1421. return ResultWrapper::fail($priceResult->getData(), $priceResult->getErrorCode());
  1422. }
  1423. $result = $priceResult->getData();
  1424. $inventoryResult = self::formatSkuInventory($result);//处理库存
  1425. if (!$inventoryResult->isSuccess()){
  1426. return ResultWrapper::fail($inventoryResult->getData(),$inventoryResult->getErrorCode());
  1427. }
  1428. $result = $inventoryResult->getData();
  1429. $result = self::formatGroup($result, $userCouponId, $vipCardId);
  1430. if(!$result->isSuccess()){
  1431. return ResultWrapper::fail($result->getData(), $result->getErrorCode());
  1432. }
  1433. return ResultWrapper::success($result->getData());
  1434. }
  1435. /**
  1436. * @param $data
  1437. * @return ResultWrapper
  1438. */
  1439. private function formatMerge($data)
  1440. {
  1441. if (empty($data)) return ResultWrapper::success($data);
  1442. foreach ($data as $goods) {
  1443. if ($goods['activityId'] == 0) {
  1444. continue;
  1445. }
  1446. //获取活动详情
  1447. $activity = $this->objActivityLimitCache->getActivity($goods['activityId']);
  1448. if ($activity['enableStatus'] == StatusCode::$delete
  1449. || time() < $activity['startTime']
  1450. || time() > $activity['endTime']) {
  1451. //活动被下架,将此条数据合并到普通商品
  1452. $cartResult = $this->objDCart->get(['goodsId' => $goods['goodsId'], 'shopId' => $goods['shopId'], 'skuId' => $goods['skuId'], 'activityId' => 0, 'userCenterId' => $this->onlineUserId]);
  1453. if (empty($cartResult)) {
  1454. //addCart
  1455. $insert = [
  1456. 'userCenterId' => $this->onlineUserId,
  1457. 'selection' => StatusCode::$standard,
  1458. 'skuId' => $goods['skuId'],
  1459. 'goodsCode' => $goods['goodsCode'],
  1460. 'goodsId' => $goods['goodsId'],
  1461. 'shopId' => $goods['shopId'],
  1462. 'buyNum' => $goods['buyNum'],//购买数量
  1463. 'source' => $goods['source'],
  1464. 'goodsBasicId' => $goods['goodsBasicId'],
  1465. 'warehouseId' => $goods['warehouseId'],
  1466. 'activityId' => 0,//活动id
  1467. ];
  1468. $dbResult = $this->objDCart->insert($insert);
  1469. } else {
  1470. //update
  1471. $dbResult = $this->objDCart->set_inc('buyNum', ['id' => $cartResult['id']], $goods['buyNum']);
  1472. }
  1473. $delResult = $this->objDCart->delete(['id' => $goods['id']]);
  1474. //获取用户限购数量
  1475. $userLimit = $this->objActivityLimitCache->getLimit($goods['activityId'], $goods['goodsId'], $goods['skuId'], $this->onlineUserId);
  1476. $this->objActivityLimitCache->writeLimit($goods['activityId'], $goods['goodsId'], $goods['skuId'], $this->onlineUserId, $userLimit - $goods['buyNum']);
  1477. if ($delResult === false) {
  1478. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1479. }
  1480. if ($dbResult === false) {
  1481. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1482. }
  1483. }
  1484. }
  1485. $result = $this->objDCart->select(['userCenterId' => $this->onlineUserId], 'id,goodsId,goodsCode,buyNum,shopId,goodsBasicId,selection,skuId,warehouseId,activityId', 'createTime DESC');
  1486. if ($result === false) {
  1487. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  1488. }
  1489. return ResultWrapper::success($result);
  1490. }
  1491. /**
  1492. * 获取店铺信息
  1493. * (原数据上+店铺名称+店铺logo)
  1494. * @param $data
  1495. * @return mixed
  1496. * @throws \Exception
  1497. */
  1498. private function formatShop($data)
  1499. {
  1500. if (empty($data)) return $data;
  1501. $objMGoods = new MShop($this->onlineEnterpriseId, $this->onlineUserId);
  1502. $shopData = $objMGoods->getShopName(array_unique(array_column($data, 'shopId')));
  1503. if (!empty($shopData)) {
  1504. foreach ($data as &$shop) {
  1505. $shop['shopName'] = isset($shopData[$shop['shopId']]['name']) ? $shopData[$shop['shopId']]['name'] : '';
  1506. $shop['shopLogo'] = isset($shopData[$shop['shopId']]['logo']) ? $shopData[$shop['shopId']]['logo'] : '';
  1507. $shop['cartId'] =getArrayItem($shop,'id',0);
  1508. }
  1509. }
  1510. return $data;
  1511. }
  1512. /**
  1513. * 商品信息
  1514. * (原数据基础上+商品名称+商品图片)商品的状态 下架商品计入失效
  1515. * @param $data
  1516. * @return mixed
  1517. * @throws \Exception
  1518. */
  1519. private function formatGoods($data)
  1520. {
  1521. if (empty($data)) return $data;
  1522. $objGoodsBasicRelevantCache = new GoodsBasicRelevant($this->onlineEnterpriseId);
  1523. $objMGoods = new MGoods($this->onlineEnterpriseId, false, $this->onlineUserId);
  1524. $goodsData = $objMGoods->getGoodsNames(array_unique(array_column($data, 'goodsId')));
  1525. if (!empty($goodsData)) {
  1526. $dbResult = $objMGoods->getNameByGoodsIds(array_values(array_unique(array_column($goodsData, 'basicGoodsId'))));
  1527. if ($dbResult->isSuccess()) {
  1528. $basicData = $dbResult->getData();
  1529. foreach ($goodsData as &$goods) {
  1530. $goods['goodsName'] = isset($basicData[$goods['basicGoodsId']]['title']) ? $basicData[$goods['basicGoodsId']]['title'] : '';
  1531. $goods['describe'] = isset($basicData[$goods['basicGoodsId']]['describe']) ? $basicData[$goods['basicGoodsId']]['describe'] : '';
  1532. $goods['categoryId'] = isset($basicData[$goods['basicGoodsId']]['categoryId']) ? $basicData[$goods['basicGoodsId']]['categoryId'] : '';
  1533. $goods['brandId'] = isset($basicData[$goods['basicGoodsId']]['brandId']) ? $basicData[$goods['basicGoodsId']]['brandId'] : '';
  1534. $goods['categoryPath'] = isset($basicData[$goods['basicGoodsId']]['categoryPath']) ? $basicData[$goods['basicGoodsId']]['categoryPath'] : '';
  1535. $goods['specType'] = isset($basicData[$goods['basicGoodsId']]['specType']) ? $basicData[$goods['basicGoodsId']]['specType'] : StatusCode::$specType['single'];
  1536. $goods['storageCode'] = isset($basicData[$goods['basicGoodsId']]['storageCode']) ? $basicData[$goods['basicGoodsId']]['storageCode'] : '';
  1537. $goods['categoryName'] = empty($goods['categoryId']) ? '' : $objGoodsBasicRelevantCache->getNameByCategoryId($goods['categoryId']);
  1538. $goods['brandName'] = empty($goods['brandId']) ? '' : $objGoodsBasicRelevantCache->getNameByBrandId($goods['brandId']);
  1539. $goods['images'] = isset($basicData[$goods['basicGoodsId']]['images']) ? $basicData[$goods['basicGoodsId']]['images'] : [];
  1540. $goods['isEq'] = isset($basicData[$goods['basicGoodsId']]['isEq']) ? $basicData[$goods['basicGoodsId']]['isEq'] : StatusCode::$delete;
  1541. }
  1542. }
  1543. }
  1544. $objMSku = new MSku($this->onlineUserId, $this->onlineEnterpriseId);
  1545. $specNameMapping = $objMSku->getSpecNameBySkuId(array_column($data, 'skuId'));
  1546. if (!$specNameMapping->isSuccess()) {
  1547. $specNameMapping = [];
  1548. } else {
  1549. $specNameMapping = $specNameMapping->getData();
  1550. }
  1551. foreach ($data as $key => &$val) {
  1552. $val['goodsCode'] = createCode(StatusCode::$code['goodsBasic']['prefix'], $val['goodsBasicId'], StatusCode::$code['goodsBasic']['length']);
  1553. $val['brandName'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['brandName'] : '';
  1554. $val['categoryName'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['categoryName'] : '';
  1555. $val['barCode'] = isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['barCode'] : '';
  1556. $val['storageCode'] = isset($goodsData[$val['goodsId']]['storageCode']) ? $goodsData[$val['goodsId']]['storageCode'] : '';
  1557. $val['goodsName'] = isset($goodsData[$val['goodsId']]['goodsName']) ? $goodsData[$val['goodsId']]['goodsName'] : '';
  1558. $images = isset($goodsData[$val['goodsId']]['images']) ? $goodsData[$val['goodsId']]['images'] : [];
  1559. $val['goodsImages'] = empty($images) ? '' : $images[0];
  1560. $val['isInvalid'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['enableStatus'] : StatusCode::$delete;//4=>失效商品
  1561. $val['describe'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['describe'] : '';
  1562. $val['categoryId'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['categoryId'] : '';
  1563. $val['brandId'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['brandId'] : '';
  1564. $val['categoryPath'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['categoryPath'] : '';
  1565. $val['isActivity'] = empty($val['activityId']) ? StatusCode::$delete : StatusCode::$standard;//是否是活动商品
  1566. $val['specType'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['specType'] : StatusCode::$specType['single'];
  1567. $val['unitName'] = isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['unitName'] : '';
  1568. $val['specGroup'] = isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['specGroup'] : [];
  1569. $val['notExpress'] = StatusCode::$standard;
  1570. $val['supplierId'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['supplierId'] : 0;
  1571. $val['supplierName'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['supplierName'] : '';
  1572. $val['isEq'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['isEq'] : StatusCode::$delete;
  1573. $val['isDistribution'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['isDistribution'] : StatusCode::$delete;
  1574. $val['express'] = [
  1575. 'weight' => isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['weight'] : 0,
  1576. 'expressType' => isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['expressType'] : 0,
  1577. 'ruleId' => isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['ruleId'] : 0,
  1578. 'expressFee' => isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['expressFee'] : 0,
  1579. ];
  1580. if ($val['isEq'] == StatusCode::$standard){
  1581. $isMaster = isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['isMaster'] : StatusCode::$delete;
  1582. //超码商品
  1583. if ($isMaster == StatusCode::$delete){
  1584. $masterSkuResult = $this->objMSku->getMasterById($val['goodsBasicId']);
  1585. if ($masterSkuResult->isSuccess()){
  1586. $masterSku = $masterSkuResult->getData();
  1587. $conversion = isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['conversion'] : 0;
  1588. $u = isset($masterSku['unitName']) ? $masterSku['unitName'] : '';
  1589. $u_1 = $val['unitName'];
  1590. $val['extends'] = ['uId' => $masterSku['id'], 'uId_1' => $val['skuId'], 'u' => $u, 'u_1' => $u_1, 'u_1_buy'=> $val['buyNum'],'conversion' => $conversion];
  1591. }
  1592. }
  1593. }
  1594. if (isset($goodsData[$val['goodsId']]) && ($goodsData[$val['goodsId']]['enableStatus'] == StatusCode::$delete || $goodsData[$val['goodsId']]['deleteStatus'] == StatusCode::$delete)) {
  1595. $val['invalidMsg'] = '此商品已下架';
  1596. $this->invalidData[] = $val;//失效商品集合
  1597. unset($data[$key]);
  1598. }
  1599. }
  1600. return $data;
  1601. }
  1602. /**
  1603. * 获取规格信息
  1604. * (原数据+skuData+unitName)
  1605. * @param $data
  1606. * @return mixed
  1607. * @throws \Exception
  1608. */
  1609. private function formatSku($data)
  1610. {
  1611. if (empty($data)) return $data;
  1612. $objMSku = new MSku($this->onlineUserId, $this->onlineEnterpriseId);
  1613. $skuData = $objMSku->getSku(array_unique(array_column($data, 'skuId')));
  1614. if (!empty($skuData)) {
  1615. foreach ($data as &$goods) {
  1616. $goods['skuData'][] = isset($skuData[$goods['skuId']]) ? $skuData[$goods['skuId']] : [];
  1617. $goods['unitName'] = isset($skuData[$goods['skuId']]['unitName']) ? $skuData[$goods['skuId']]['unitName'] : '';
  1618. $goods['conversion'] = isset($skuData[$goods['skuId']]['conversion']) ? $skuData[$goods['skuId']]['conversion'] : '';
  1619. }
  1620. }
  1621. return $data;
  1622. }
  1623. /**
  1624. * 查询库存以及成本(*goodsBasicId *warehouseId) 库存不足的商品计入失效
  1625. * (原数据+costPrice+inventoryNum)
  1626. * @param $data
  1627. * @return mixed
  1628. * @throws \Exception
  1629. */
  1630. private function formatSkuInventory($data): ResultWrapper
  1631. {
  1632. $inventorySelectParams = [];
  1633. $skuIds = [];
  1634. foreach ($data as &$goods) {
  1635. $skuIds[] = $goods['skuId'];
  1636. $goods['inventory'] = 0;
  1637. $inventorySelectParams[$goods['shopId']][] = $goods['skuId'];
  1638. }
  1639. unset($goods);
  1640. $objMInventory = new MInventory($this->onlineEnterpriseId, $this->onlineUserId);
  1641. $inventoryMap = [];
  1642. foreach ($inventorySelectParams as $shopId => $skuIds){
  1643. $inventoryResult = $objMInventory->getInventoryByShopIdAndSkuIds($shopId,$skuIds);
  1644. if (!$inventoryResult->isSuccess()) {
  1645. return ResultWrapper::fail($inventoryResult->getData(),$inventoryResult->getErrorCode());
  1646. }
  1647. $inventoryMap[$shopId] = $inventoryResult->getData();
  1648. }
  1649. var_dump($skuIds) ;
  1650. echo "----------------";
  1651. //获取当前skuIds的主单位,及换算比例
  1652. $skuConversionResult = $this->objMSku->getConversion($skuIds);
  1653. if (!$skuConversionResult->isSuccess()) {
  1654. return ResultWrapper::fail($skuConversionResult->getData(),$skuConversionResult->getErrorCode());
  1655. }
  1656. $skuConversionMapping = $skuConversionResult->getData();
  1657. var_dump($skuConversionMapping);
  1658. echo "----------------";
  1659. var_dump($data);
  1660. exit();
  1661. foreach ($data as $key => &$goods) {
  1662. $thisSku = $skuConversionMapping[$goods['skuId']];
  1663. if (!isset($inventoryMap[$goods['shopId']])){
  1664. return ResultWrapper::fail('未获取到库存信息',ErrorCode::$paramError);
  1665. }
  1666. $row = $inventoryMap[$goods['shopId']];
  1667. $goods['inventoryNum'] = isset($row[$goods['skuId']]['num']) ? $row[$goods['skuId']]['num'] : 0;
  1668. $goods['costPrice'] = 0;
  1669. $goods['conversion'] = $thisSku['conversion'];//换算比例
  1670. //判断是否开启预售
  1671. if ($goods['isDistribution'] == StatusCode::$delete) {
  1672. //没有开启需要检测库存
  1673. if ($goods['inventoryNum'] < $goods['buyNum']) {
  1674. $goods['isInvalid'] = StatusCode::$delete;
  1675. $goods['invalidMsg'] = '商品库存不足';
  1676. $this->invalidData[] = $goods;
  1677. unset($data[$key]);
  1678. }
  1679. }
  1680. }
  1681. return ResultWrapper::success($data);
  1682. }
  1683. /**
  1684. * Doc: (des="计算运费")
  1685. * User: XMing
  1686. * Date: 2020/9/8
  1687. * Time: 10:10 上午
  1688. * @param array $data
  1689. * @return ResultWrapper
  1690. * @throws \Exception
  1691. */
  1692. private function calExpress(array $data)
  1693. {
  1694. if (empty($data)) return ResultWrapper::success($data);
  1695. if (empty($this->onlineUserDefaultDeliveryType)) {
  1696. return ResultWrapper::success($data);
  1697. }
  1698. //判断选择是否是快递配送方式
  1699. if ($this->onlineUserDefaultDeliveryType != StatusCode::$deliveryType['goodsDelivery']) {
  1700. return ResultWrapper::success($data);
  1701. }
  1702. $map = [];
  1703. foreach ($data as $val) {
  1704. $map[$val['shopId']][] = $val;
  1705. }
  1706. unset($data);
  1707. //收货地址为空,按全国计算
  1708. $data = [];
  1709. foreach ($map as $shopId => $item) {
  1710. $buildDataResult = self::buildExpressData($item, $shopId, $this->onlineUserAddressCode);
  1711. if (!$buildDataResult->isSuccess()) {
  1712. return ResultWrapper::fail($buildDataResult->getData(), $buildDataResult->getErrorCode());
  1713. }
  1714. $data = array_merge($data, $buildDataResult->getData());
  1715. }
  1716. return ResultWrapper::success($data);
  1717. }
  1718. /**
  1719. * Doc: (des="运费计算规则")
  1720. * User: XMing
  1721. * Date: 2020/9/8
  1722. * Time: 11:36 上午
  1723. * @example https://www.xiaokeduo.com/help/11584.html
  1724. * 1.按商品累加运费
  1725. * 规则:分别计算出来商品使用模板的运费,和统一运费的最大值,再进行累加。
  1726. * 1)不同或相同的商品,设置同一运费模板:按该模板设置的规则计算
  1727. * 更新:不足续件数目的时候,仍然按照续件数目进行计算。
  1728. * 例如商品A,B都是用模板M(首件10块,续2件5块),如果购买商品A和B,各一件,则一共购买两件,运费=10+5=15元。
  1729. * @param array $data
  1730. * @param string $code
  1731. * @param int $shopId
  1732. * @throws \Exception
  1733. * @return ResultWrapper
  1734. */
  1735. private function buildExpressData(array $data, int $shopId, $code = null)
  1736. {
  1737. //提取设置了运费模版的模版规则id
  1738. $allRuleIds = [];
  1739. foreach ($data as $item) {
  1740. if ($item['express']['expressType'] == StatusCode::$expressType['rule']) {
  1741. $allRuleIds[] = $item['express']['ruleId'];
  1742. continue;
  1743. }
  1744. }
  1745. $allRuleIds = array_values(array_unique($allRuleIds));
  1746. $roleMap = [];
  1747. $objDDeliveryRule = new DDeliveryRule();
  1748. $objDDeliveryRule->setTable('qianniao_delivery_rule_' . $this->onlineEnterpriseId);
  1749. if (!empty($allRuleIds)) {
  1750. $ruleLists = $objDDeliveryRule->select(['id' => $allRuleIds]);
  1751. if ($ruleLists === false) {
  1752. return ResultWrapper::fail($objDDeliveryRule->error(), ErrorCode::$dberror);
  1753. }
  1754. foreach ($ruleLists as $item) {
  1755. $roleMap[$item['id']] = empty($item['setData']) ? [] : json_decode($item['setData'], true);
  1756. }
  1757. }
  1758. // 查询基础设置-商品设置运费规则
  1759. $objMBasicSetup = new MBasicSetup($this->onlineEnterpriseId);
  1760. $BasicSetupResult = $objMBasicSetup->getBasicField('calculateExpressType');
  1761. if (!$BasicSetupResult->isSuccess()) {
  1762. return ResultWrapper::fail($BasicSetupResult->getData(), $BasicSetupResult->getErrorCode());
  1763. }
  1764. $BasicSetup = $BasicSetupResult->getData();
  1765. $calculateExpressType = isset($BasicSetup['calculateExpressType']) ? $BasicSetup['calculateExpressType'] : StatusCode::$standard;
  1766. switch ($calculateExpressType) {
  1767. case StatusCode::$delete: // 累加运费规则
  1768. $calResult = self::ruleAdd($data, $roleMap, $code, $shopId);
  1769. break;
  1770. case StatusCode::$standard: // 组合运费规则
  1771. $calResult = self::ruleGroup($data, $roleMap, $code, $shopId);
  1772. break;
  1773. default: // 默认使用组合运费规则
  1774. $calResult = self::ruleGroup($data, $roleMap, $code, $shopId);
  1775. break;
  1776. }
  1777. if (!$calResult->isSuccess()) {
  1778. return ResultWrapper::fail($calResult->getData(), $calResult->getErrorCode());
  1779. }
  1780. $data = $calResult->getData();
  1781. return ResultWrapper::success($data);
  1782. }
  1783. /**
  1784. * Doc: (des="(规则一)按商品累加运费")
  1785. * User: XMing
  1786. * Date: 2020/9/25
  1787. * Time: 9:14 上午
  1788. * @param array $data
  1789. * @param array $roleMap
  1790. * @param string $code
  1791. * @return ResultWrapper
  1792. * @example https://www.xiaokeduo.com/help/11584.html
  1793. * 1)不同或相同的商品,设置同一运费模板:按该模板设置的规则计算
  1794. * 更新:不足续件数目的时候,仍然按照续件数目进行计算。
  1795. * 例如商品A,B都是用模板M(首件10块,续2件5块),如果购买商品A和B,各一件,则一共购买两件,运费=10+5=15元。
  1796. * 2)多种商品,分别设置不同金额的统一运费:以最高运费金额收取。
  1797. * 更新:例如 商品A,B,C的统一运费分别为1元,2元和3元,一期购买这三个商品,则运费为3元。
  1798. * 3)不同的商品,设置不同的运费模板:分别计算每个运费模板规则应收运费,再累加计算合计运费;
  1799. * 例如: 例如商品A使用用模板M(首件,10块,续1件,5块),商品B使用模板N(首件,12块,续3件,5块),如果购买商品A和B,各2件,则运费=模板M的运费+模板N的运费=(10+5)+(12+5)=32元。
  1800. * 4)统一运费商品,和运费模板商品一同结算:单独计算统一运费商品应收运费,再累加运费模板应收运费;
  1801. * 例如:商品A和B使用统一运费,分别为2元和10元,商品C使用模板M(首1件,10块,续2件,5块),商品D使用模板N(首件,12块,续3件,5块),购买A,B,C和D各两件。
  1802. * 此时统一运费(商品A和B)=10元;运费模板运费(商品C和D)=模板M的运费+模板N的运费=(10+5)+(12+5)=32元。
  1803. * 则总运费=统一运费+运费模板运费=(10)+(32)=42元。
  1804. */
  1805. private function ruleAdd($data, $roleMap, $code, $shopId)
  1806. {
  1807. //初始化所有运费
  1808. $freeExpressMoney = 0;//免邮费
  1809. $ruleExpressMoney = 0;//模版规则运费
  1810. $unifyExpressMoney = 0;//统一运费
  1811. $ruleIdRelGoodsMap = [];//模版=>[商品数量,商品重量]
  1812. foreach ($data as &$item) {
  1813. //判断运费设置
  1814. switch ($item['express']['expressType']) {
  1815. case StatusCode::$expressType['free']:
  1816. //免邮费
  1817. $freeExpressMoney = bcadd($freeExpressMoney, 0, 2);
  1818. break;
  1819. case StatusCode::$expressType['rule']:
  1820. $ruleId = $item['express']['ruleId'];
  1821. //运费模版
  1822. if (!isset($roleMap[$ruleId])) {
  1823. //运费模版规则不存在,不计算运费
  1824. continue 2;
  1825. }
  1826. if (!empty($code)) {
  1827. //地区
  1828. //先判断商品是否在配送区域
  1829. $notDispatchAreas = $roleMap[$ruleId]['not_dispatch_areas'];
  1830. $isExist = self::searchInArray($code, $notDispatchAreas);
  1831. if ($isExist === true) {
  1832. $item['notExpress'] = StatusCode::$delete;
  1833. continue 2;
  1834. }
  1835. }
  1836. $ruleIdRelGoodsMap[$ruleId]['num'] = (isset($ruleIdRelGoodsMap[$ruleId]['num']) ? $ruleIdRelGoodsMap[$ruleId]['num'] : 0) + $item['buyNum'];
  1837. $ruleIdRelGoodsMap[$ruleId]['weight'] = (isset($ruleIdRelGoodsMap[$ruleId]['weight']) ? $ruleIdRelGoodsMap[$ruleId]['weight'] : 0) + bcmul($item['express']['weight'], $item['buyNum'], 2);
  1838. break;
  1839. case StatusCode::$expressType['unify']:
  1840. //统一运费,求其中最大值
  1841. if ($item['express']['expressFee'] > $unifyExpressMoney) {
  1842. //如果当前值大于目前的最大值,则使用当前的值覆盖
  1843. $unifyExpressMoney = $item['express']['expressFee'];
  1844. }
  1845. break;
  1846. default:
  1847. //没有设置默认不计算运费
  1848. break;
  1849. }
  1850. }
  1851. if (!empty($ruleIdRelGoodsMap)) {
  1852. //计算模版运费
  1853. foreach ($ruleIdRelGoodsMap as $ruleId => $value) {
  1854. $type = $roleMap[$ruleId]['type'];//4:按件 5:按重量
  1855. if (empty($code)) {
  1856. //没有地区code,使用全国统一运费的规则进行计算
  1857. $uniform = $roleMap[$ruleId]['uniform'];
  1858. $expressMoney = self::calculateExpress($type, $uniform, $value);
  1859. $ruleExpressMoney = bcadd($ruleExpressMoney, $expressMoney, 2);
  1860. } else {
  1861. //匹配模版
  1862. $dispatchAreas = $roleMap[$ruleId]['areas'];
  1863. $searchRow = self::searchRowByCode($code, $dispatchAreas);
  1864. if ($searchRow === false) {
  1865. //当前地区没有匹配到,使用全国统一计算
  1866. $uniform = $roleMap[$ruleId]['uniform'];
  1867. $expressMoney = self::calculateExpress($type, $uniform, $value);
  1868. $ruleExpressMoney = bcadd($ruleExpressMoney, $expressMoney, 2);
  1869. } else {
  1870. //匹配到了规则
  1871. $rule = [
  1872. 'first_num' => $searchRow['first_num'],
  1873. 'first_price' => $searchRow['first_price'],
  1874. 'second_num' => $searchRow['second_num'],
  1875. 'second_price' => $searchRow['second_price']
  1876. ];
  1877. $expressMoney = self::calculateExpress($type, $rule, $value);
  1878. $ruleExpressMoney = bcadd($ruleExpressMoney, $expressMoney, 2);
  1879. }
  1880. }
  1881. }
  1882. }
  1883. $this->expressShopMoney[$shopId] = bcadd($ruleExpressMoney, $unifyExpressMoney, 2);
  1884. $this->expressMoney = bcadd($this->expressMoney, $this->expressShopMoney[$shopId], 2);
  1885. return ResultWrapper::success($data);
  1886. }
  1887. /**
  1888. * Doc: (des=" (规则二) 组合运费")
  1889. * User: XMing
  1890. * Date: 2020/9/25
  1891. * Time: 12:03 下午
  1892. * @param array $data
  1893. * @param array $roleMap
  1894. * @param string $code
  1895. * @return ResultWrapper
  1896. * @example https://www.xiaokeduo.com/help/11584.html
  1897. * 规则:先将使用统一运费和运费模板的商品分开计算,再取二者较大的值,作为最终运费。
  1898. * 1)计算使用运费模板的运费价格x:取所有商品中,首件金额最大的运费模板,计算使用该模板的所有商品运费;
  1899. * 使用其他模板的所有商品都按照该商品所试用的续件金额来计算;
  1900. * 最后再求和。
  1901. * 2)计算使用统一运费的商品运费y:取最大的统一运费。
  1902. * 3)比较x和y,运费=x和y的较大值。
  1903. * 例如:
  1904. * 1)不同或相同的商品,设置同一运费模板:同按商品累加运费的计算方式,按该模板设置的规则计算。
  1905. * 例如商品A,B都是用模板M(首件10块,续2件5块),如果购买商品A和B,各一件,则一共购买两件,运费=10+5=15元。
  1906. * 2)多种商品,分别设置不同金额的统一运费:同按商品累加运费的计算方式,以最高运费金额收取。
  1907. * 例如 商品A,B,C的统一运费分别为1元,2元和3元,一起购买这三个商品,则运费为3元。
  1908. * 3)不同的商品,设置不同的运费模板:不同于按照商品累加的计算方式。
  1909. * 例如: 例如商品A(1件)使用用模板M(首1件,10块,续1件,5块),商品B(1件)使用模板N(首2件,12块,续1件,5块),如果购买商品A和B,各2件,则运费=模板N的运费(首费为12,大于模板M的10)+模板M的运费(按照续费计算)=(12)+(5*2)=22元。
  1910. * 如果按商品累加计费,则运费=模板M的运费+模板N的运费=(10+5)+(12)=27元。
  1911. * 4)统一运费商品,和运费模板商品一同结算:单独计算统一运费和运费模板,再取较大的数值作为最终运费;
  1912. * 例如:商品A和B使用统一运费,分别为2元和10元,商品C使用模板M(首1件,10块,续2件,5块),商品D(1件)使用模板N(首2件,12块,续1件,5块),购买A,B,C和D各两件。
  1913. * 此时统一运费(商品A和B)=10元;运费模板运费(商品C和D)=模板N的运费(首费为12,大于模板M的10)+模板M的运费(按照续费计算)=(12)+(5*2)=22元。总运费=统一运费和运费模板运费的较大值=22元。
  1914. * 如果按商品累加计费,运费按照之前的计算=统一运费+运费模板运费=(10)+(27)=37元。
  1915. */
  1916. private function ruleGroup($data, $roleMap, $code, $shopId)
  1917. {
  1918. //初始化所有运费
  1919. $freeExpressMoney = 0;//免邮费
  1920. $ruleExpressMoney = 0;//模版规则运费
  1921. $unifyExpressMoney = 0;//统一运费
  1922. $ruleIdRelGoodsMap = [];//模版=>[商品数量,商品重量]
  1923. foreach ($data as &$item) {
  1924. //判断运费设置
  1925. switch ($item['express']['expressType']) {
  1926. case StatusCode::$expressType['free']:
  1927. //免邮费
  1928. $freeExpressMoney = bcadd($freeExpressMoney, 0, 2);
  1929. break;
  1930. case StatusCode::$expressType['rule']:
  1931. $ruleId = $item['express']['ruleId'];
  1932. //运费模版
  1933. if (!isset($roleMap[$ruleId])) {
  1934. //运费模版规则不存在,不计算运费
  1935. continue 2;
  1936. }
  1937. if (!empty($code)) {
  1938. //地区
  1939. //先判断商品是否在配送区域
  1940. $notDispatchAreas = $roleMap[$ruleId]['not_dispatch_areas'];
  1941. $isExist = self::searchInArray($code, $notDispatchAreas);
  1942. if ($isExist === true) {
  1943. $item['notExpress'] = StatusCode::$delete;
  1944. continue 2;
  1945. }
  1946. }
  1947. $ruleIdRelGoodsMap[$ruleId]['num'] = (isset($ruleIdRelGoodsMap[$ruleId]['num']) ? $ruleIdRelGoodsMap[$ruleId]['num'] : 0) + $item['buyNum'];
  1948. $ruleIdRelGoodsMap[$ruleId]['weight'] = (isset($ruleIdRelGoodsMap[$ruleId]['weight']) ? $ruleIdRelGoodsMap[$ruleId]['weight'] : 0) + bcmul($item['express']['weight'], $item['buyNum'], 2);
  1949. break;
  1950. case StatusCode::$expressType['unify']:
  1951. //统一运费,求其中最大值
  1952. if ($item['express']['expressFee'] > $unifyExpressMoney) {
  1953. //如果当前值大于目前的最大值,则使用当前的值覆盖
  1954. $unifyExpressMoney = $item['express']['expressFee'];
  1955. }
  1956. break;
  1957. default:
  1958. //没有设置默认不计算运费
  1959. break;
  1960. }
  1961. }
  1962. //选获取模版规则中首件的最高价格,然后减去首件的都按续件处理
  1963. //唯一的区别,多个运费模版首费只算一次
  1964. if (!empty($ruleIdRelGoodsMap)) {
  1965. //计算模版运费
  1966. foreach ($ruleIdRelGoodsMap as $ruleId => &$value) {
  1967. $value['type'] = $roleMap[$ruleId]['type'];//4:按件 5:按重量
  1968. if (empty($code)) {
  1969. //没有地区code,使用全国统一运费的规则进行计算
  1970. $uniform = $roleMap[$ruleId]['uniform'];
  1971. $value['rule'] = $uniform;
  1972. } else {
  1973. //匹配模版
  1974. $dispatchAreas = $roleMap[$ruleId]['areas'];
  1975. $searchRow = self::searchRowByCode($code, $dispatchAreas);
  1976. if ($searchRow === false) {
  1977. //当前地区没有匹配到,使用全国统一计算
  1978. $uniform = $roleMap[$ruleId]['uniform'];
  1979. $value['rule'] = $uniform;
  1980. } else {
  1981. //匹配到了规则
  1982. $rule = [
  1983. 'first_num' => $searchRow['first_num'],
  1984. 'first_price' => $searchRow['first_price'],
  1985. 'second_num' => $searchRow['second_num'],
  1986. 'second_price' => $searchRow['second_price']
  1987. ];
  1988. $value['rule'] = $rule;
  1989. }
  1990. }
  1991. }
  1992. //使用组合运费计算规则,计算运费
  1993. $ruleExpressMoney = self::calculateExpressGroup($ruleIdRelGoodsMap);
  1994. }
  1995. $this->expressShopMoney[$shopId] = bcadd($ruleExpressMoney, $unifyExpressMoney, 2);
  1996. $this->expressMoney = bcadd($this->expressMoney, $this->expressShopMoney[$shopId], 2);
  1997. return ResultWrapper::success($data);
  1998. }
  1999. /**
  2000. * Doc: (des="以组合运费方式计算快递费用")
  2001. * User: XMing
  2002. * Date: 2020/9/25
  2003. * Time: 2:44 下午
  2004. * @param array $data
  2005. * @return float
  2006. */
  2007. private static function calculateExpressGroup($data)
  2008. {
  2009. $ruleExpressMoney = 0;
  2010. $max_first_price = 0;
  2011. $max_rule_id = 0;
  2012. foreach ($data as $ruleId => $item) {
  2013. //获取首费用最高的
  2014. if ($item['rule']['first_price'] > $max_first_price) {
  2015. $max_first_price = $item['rule']['first_price'];
  2016. $max_rule_id = $ruleId;
  2017. }
  2018. }
  2019. unset($item);
  2020. foreach ($data as $ruleId => &$item) {
  2021. if ($ruleId != $max_rule_id) {
  2022. continue;
  2023. }
  2024. //减去首重的件/重量
  2025. switch ($item['type']) {
  2026. case StatusCode::$delete:
  2027. //剩余续件的
  2028. $num = bcsub($item['num'], $item['rule']['first_num'], 2);
  2029. $item['num'] = ($num < 0) ? 0 : $num;
  2030. break;
  2031. case StatusCode::$standard:
  2032. //剩余续重的
  2033. $weight = bcsub($item['weight'], $item['rule']['first_num'], 2);
  2034. $item['weight'] = ($weight < 0) ? 0 : $weight;
  2035. break;
  2036. }
  2037. }
  2038. unset($item);
  2039. //剩下的都是续
  2040. foreach ($data as $ruleId => $item) {
  2041. switch ($item['type']) {
  2042. case StatusCode::$delete:
  2043. $mod = ($item['rule']['second_num'] == 0) ? 0 : ceil($item['num'] / $item['rule']['second_num']);
  2044. $expressMoney = bcmul($mod, $item['rule']['second_price'], 2);
  2045. $ruleExpressMoney = bcadd($ruleExpressMoney, $expressMoney, 2);
  2046. break;
  2047. case StatusCode::$standard:
  2048. $mod = ($item['rule']['second_num'] == 0) ? 0 : ceil($item['weight'] / $item['rule']['second_num']);
  2049. $expressMoney = bcmul($mod, $item['rule']['second_price'], 2);
  2050. $ruleExpressMoney = bcadd($ruleExpressMoney, $expressMoney, 2);
  2051. break;
  2052. }
  2053. unset($expressMoney);
  2054. unset($mod);
  2055. }
  2056. //最高首费用 + 各自模版续运费
  2057. return bcadd($max_first_price, $ruleExpressMoney, 2);
  2058. }
  2059. /**
  2060. * Doc: (des="根据模版规则,去计算运费")
  2061. * User: XMing
  2062. * Date: 2020/9/25
  2063. * Time: 9:42 上午
  2064. * @param int $type
  2065. * @param array $rule
  2066. * @param array $item
  2067. * @return float
  2068. */
  2069. private static function calculateExpress($type, $rule, $item)
  2070. {
  2071. switch ($type) {
  2072. case StatusCode::$delete:
  2073. //按件
  2074. //1.按件
  2075. if ($item['num'] <= $rule['first_num']) return $rule['first_price'];
  2076. $mod = ($rule['second_num'] == 0) ? 0 : ceil(($item['num'] - $rule['first_num']) / $rule['second_num']);
  2077. return bcadd($rule['first_price'], bcmul($mod, $rule['second_price'], 2), 2);
  2078. break;
  2079. case StatusCode::$standard:
  2080. //按重量
  2081. $thisWeight = bcmul($item['weight'], $item['num'], 2);
  2082. if ($thisWeight <= $rule['first_num']) return $rule['first_price'];
  2083. $mod = ($rule['second_num'] == 0) ? 0 : ceil(($thisWeight - $rule['first_num']) / $rule['second_num']);
  2084. return bcadd($rule['first_price'], bcmul($mod, $rule['second_price'], 2), 2);
  2085. break;
  2086. default:
  2087. break;
  2088. }
  2089. }
  2090. /**
  2091. * Doc: (des="")
  2092. * User: XMing
  2093. * Date: 2020/9/8
  2094. * Time: 3:29 下午
  2095. * @param array $data
  2096. * @param string $code
  2097. * @return array|boolean
  2098. */
  2099. public function searchRowByCode($code, $data)
  2100. {
  2101. $arr = explode('-', $code);
  2102. $provinceCode = isset($arr[0]) ? $arr[0] : 0;
  2103. $cityCode = isset($arr[1]) ? $arr[1] : 0;
  2104. $areaCode = isset($arr[2]) ? $arr[2] : 0;
  2105. foreach ($data as $item) {
  2106. $allProvinces = isset($item['provinces']) ? $item['provinces'] : [];
  2107. $allCitys = isset($item['citys']) ? $item['citys'] : [];
  2108. $allAreas = isset($item['areas']) ? $item['areas'] : [];
  2109. //查看当前省是否存在,如果省不存在市肯定不存在
  2110. if (!in_array($provinceCode, $allProvinces)) {
  2111. continue;
  2112. }
  2113. //查看市是否存在,如果市不存在区肯定不存在
  2114. if (!in_array($cityCode, $allCitys)) {
  2115. continue;
  2116. }
  2117. if (!in_array($areaCode, $allAreas)) {
  2118. continue;
  2119. }
  2120. //存在返回此条数据
  2121. return $item;
  2122. }
  2123. return false;
  2124. }
  2125. /**
  2126. * Doc: (des="查询某只是否在数组中")
  2127. * User: XMing
  2128. * Date: 2020/9/8
  2129. * Time: 3:06 下午
  2130. * @param array $data
  2131. * @param string $code
  2132. * @return boolean 不存在返回false 存在返回true
  2133. */
  2134. public function searchInArray($code, $data)
  2135. {
  2136. $arr = explode('-', $code);
  2137. $provinceCode = isset($arr[0]) ? $arr[0] : 0;
  2138. $cityCode = isset($arr[1]) ? $arr[1] : 0;
  2139. $areaCode = isset($arr[2]) ? $arr[2] : 0;
  2140. $allProvinces = isset($data['provinces']) ? $data['provinces'] : [];
  2141. $allCitys = isset($data['citys']) ? $data['citys'] : [];
  2142. $allAreas = isset($data['areas']) ? $data['areas'] : [];
  2143. //查看当前省是否存在,如果省不存在市肯定不存在
  2144. if (!in_array($provinceCode, $allProvinces)) {
  2145. return false;
  2146. }
  2147. //查看市是否存在,如果市不存在区肯定不存在
  2148. if (!in_array($cityCode, $allCitys)) {
  2149. return false;
  2150. }
  2151. if (!in_array($areaCode, $allAreas)) {
  2152. return false;
  2153. }
  2154. return true;
  2155. }
  2156. /**
  2157. * 获取商品价格,及计算价格 ,(有促销活动的用促销价)
  2158. * (原数据+price+originPrice+preferential+totalMoney)
  2159. * @param $data
  2160. * @return ResultWrapper
  2161. * @throws \Exception
  2162. */
  2163. private function formatPrice($data)
  2164. {
  2165. if (empty($data)) return ResultWrapper::success($data);
  2166. $objMPrice = new MPrice($this->onlineUserId, $this->onlineEnterpriseId);
  2167. $objMActivity = new MActivity($this->onlineUserId, $this->onlineEnterpriseId);
  2168. $objMCustomer = new MCustomer($this->onlineEnterpriseId, $this->onlineUserId);
  2169. $selectParam['material'] = [];
  2170. $allGoodsId = [];
  2171. foreach ($data as &$goods) {
  2172. $allGoodsId[] = $goods['goodsId'];
  2173. $selectParam['material'][$goods['shopId']][] = $goods['goodsId'];
  2174. $goods['originPrice'] = 0;//原价
  2175. $goods['price'] = 0;//单价
  2176. $goods['preferential'] = 0;//优惠差价
  2177. $goods['totalMoney'] = 0;//小计(unitPrice*buyNum)
  2178. $goods['activityMoney'] = 0;//互斥活动商品总金额
  2179. $goods['isMutex'] = StatusCode::$delete;//初始化互斥状态
  2180. }
  2181. unset($goods);
  2182. // 查询价格
  2183. $selectParam['customerId'] = $this->customerId;
  2184. $dbResult = $objMPrice->getPrice($selectParam);
  2185. if (!$dbResult->isSuccess()) {
  2186. return ResultWrapper::fail($dbResult->getData(), $dbResult->getErrorCode());
  2187. }
  2188. $priceResult = $dbResult->getData();
  2189. unset($dbResult);
  2190. $customerResult = $objMCustomer->getCustomerInfoByUserCenterId($this->onlineUserId);
  2191. $activityArr = [];
  2192. if ($customerResult->isSuccess()) {
  2193. $customer = $customerResult->getData();
  2194. //获取促销活动价格
  2195. $dbResult = $objMActivity->getActivity([
  2196. 'goodsId' => implode(',', $allGoodsId),
  2197. 'customerType' => isset($customer['type']) ? $customer['type'] : 0,
  2198. ]);//TODO
  2199. $activityResult = $dbResult->getData();
  2200. unset($dbResult);
  2201. foreach ($activityResult as $activity) {
  2202. $activityArr[$activity['goodsId'] . $activity['skuId']] = $activity;
  2203. }
  2204. }
  2205. //商品价格信息
  2206. $goodsArr = [];
  2207. foreach ($priceResult as $shopPriceArr) {
  2208. foreach ($shopPriceArr as $goodsId => $goodsSkuArr) {
  2209. $goodsArr[$goodsId] = $goodsSkuArr;
  2210. }
  2211. }
  2212. // 查询当前用户是否购买过vip会员卡
  2213. $enableMemberPrice = false;
  2214. $objMVipCard = new MVipCard($this->onlineEnterpriseId, $this->onlineUserId, true);
  2215. $dbResult = $objMVipCard->getAllVipCardByCustomerId($this->customerId);
  2216. if (!$dbResult->isSuccess()) {
  2217. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  2218. }
  2219. $vipCard = $dbResult->getData();
  2220. if (!empty($vipCard)){
  2221. foreach ($vipCard as $key => $value){
  2222. if($value['memberSpecialPrice'] == StatusCode::$standard){
  2223. $enableMemberPrice = true;
  2224. }
  2225. }
  2226. }
  2227. foreach ($data as &$goods) {
  2228. //此商品存在促销价
  2229. if (isset($activityArr[$goods['goodsId'] . $goods['skuId']])) {
  2230. $price = $goodsArr[$goods['goodsId']][$goods['skuId']]['salePrice'];//商品正常销售价格
  2231. //从缓存中获取活动详情
  2232. if (isset($goods['activityId']) && !empty($goods['activityId'])) {
  2233. $price = $activityArr[$goods['goodsId'] . $goods['skuId']]['price'];//商品活动价格
  2234. $activityDetail = $this->objActivityLimitCache->getActivity($goods['activityId']);
  2235. if (!empty($activityDetail) && $activityDetail['isMutex'] == StatusCode::$standard) {
  2236. //开启互斥商品的总金额
  2237. $goods['activityMoney'] = bcmul($price, $goods['buyNum'], 2);
  2238. $goods['isMutex'] = StatusCode::$standard;
  2239. }
  2240. }
  2241. } else {
  2242. if (isset($goodsArr[$goods['goodsId']][$goods['skuId']])) {
  2243. $priceInfo = $goodsArr[$goods['goodsId']][$goods['skuId']];//此商品规格的价格信息
  2244. $price = isset($priceInfo['salePrice']) ? $priceInfo['salePrice'] : 0;
  2245. // 会员价 启用会员价不生效阶梯价了
  2246. $memberPrice = getArrayItem($priceInfo, 'memberPrice', 0);
  2247. if($enableMemberPrice && $memberPrice){
  2248. $price = $memberPrice;
  2249. }else{
  2250. // 开启阶梯价
  2251. if ($priceInfo['enabledLadder']) {
  2252. foreach ($priceInfo['ladderPrice'] as $ladder) {
  2253. $ladder['to'] = empty($ladder['to']) ? 9999 : $ladder['to'];
  2254. if ($goods['buyNum'] >= $ladder['from'] && $goods['buyNum'] <= $ladder['to']) {
  2255. $price = isset($ladder['price']) ? $ladder['price'] : 0;
  2256. continue;
  2257. }
  2258. }
  2259. }
  2260. }
  2261. }
  2262. }
  2263. if (!isset($price)) $price = 0;
  2264. $price = floatval($price);
  2265. $goods['price'] = sprintf("%.2f", $price);
  2266. $goods['originPrice'] = sprintf("%.2f", $price);//没有优惠活动暂时原价=销售价
  2267. $goods['preferential'] = 0;//优惠券优惠金额
  2268. $goods['totalMoney'] = bcmul($price, $goods['buyNum'], 2);//商品小计金额
  2269. $goods['vipDiscount'] = 0;//会员卡优惠金额
  2270. $goods['setNum'] = isset( $goodsArr[$goods['goodsId']][$goods['skuId']]['setNum'] ) ? $goodsArr[$goods['goodsId']][$goods['skuId']]['setNum'] : 0;//起定数量
  2271. if (empty($goods['totalMoney'])) {
  2272. return ResultWrapper::fail('计算商品价格时出现异常', ErrorCode::$paramError);
  2273. }
  2274. }
  2275. return ResultWrapper::success($data);
  2276. }
  2277. /**
  2278. * 数据分组
  2279. *
  2280. * @param $data
  2281. * @param null $userCouponId
  2282. * @param null $vipCardId
  2283. * @return ResultWrapper
  2284. */
  2285. private function formatGroup($data, $userCouponId = null, $vipCardId = null)
  2286. {
  2287. static $checkNum = 0;//购物车中选中商品数量
  2288. static $totalMoney = 0;//原总额
  2289. static $payMoney = 0;//实际支付金额
  2290. static $preferential = 0;//优惠券优惠
  2291. static $cartNum = 0;
  2292. static $goodsNum = 0;//购物车商品数量
  2293. static $vipDiscount = 0;//会员卡优惠金额
  2294. static $vipDoubleDiscount = 0;//会员卡折上折优惠金额
  2295. static $activityMoney = 0;//互斥活动商品总金额
  2296. static $expressMoney = 0;//运费
  2297. $goodsData = [];
  2298. foreach ($data as $key => $val) {
  2299. if (!isset($val['expressMoney'])) {
  2300. $val['expressMoney'] = '0.00';
  2301. }
  2302. $shopGoodsData[$val['shopId']][] = $val;
  2303. if (!isset($goodsData[$val['shopId']]['totalMoney'])) {
  2304. $goodsData[$val['shopId']]['totalMoney'] = '0.00';
  2305. }
  2306. if (!isset($goodsData[$val['shopId']]['preferential'])) {
  2307. $goodsData[$val['shopId']]['preferential'] = '0.00';
  2308. }
  2309. if (!isset($goodsData[$val['shopId']]['expressMoney'])) {
  2310. $goodsData[$val['shopId']]['expressMoney'] = '0.00';
  2311. }
  2312. $goodsData[$val['shopId']] = [
  2313. 'shopId' => $val['shopId'],
  2314. 'shopName' => $val['shopName'],
  2315. 'shopLogo' => $val['shopLogo'],
  2316. 'expressMoney' => isset($this->expressShopMoney[$val['shopId']]) ? $this->expressShopMoney[$val['shopId']] : 0,
  2317. 'totalMoney' => bcadd($goodsData[$val['shopId']]['totalMoney'], $val['totalMoney'], 2),//(购物车总金额)
  2318. 'preferential' => bcadd($goodsData[$val['shopId']]['preferential'], bcmul($val['preferential'], $val['buyNum']), 2),//店铺总优惠金额
  2319. 'payMoney' => bcadd((isset($this->expressShopMoney[$val['shopId']]) ? $this->expressShopMoney[$val['shopId']] : 0), bcsub(bcadd($goodsData[$val['shopId']]['totalMoney'], $val['totalMoney']), bcadd($goodsData[$val['shopId']]['preferential'], bcmul($val['preferential'], $val['buyNum'])), 2), 2),//(购物实付金额)
  2320. 'shopGoodsData' => $shopGoodsData[$val['shopId']],//商品数据
  2321. ];
  2322. //统计选中商品总数
  2323. if ($val['selection'] == StatusCode::$standard) {
  2324. $checkNum = bcadd($checkNum, 1);
  2325. $totalMoney = bcadd($totalMoney, $val['totalMoney'], 2);
  2326. $payMoney = bcadd(0, bcadd($payMoney, bcsub($val['totalMoney'], bcmul($val['buyNum'], $val['preferential'])), 2), 2);
  2327. $preferential = bcadd($preferential, bcmul($val['buyNum'], $val['preferential']), 2);
  2328. $activityMoney = bcadd($activityMoney, $val['activityMoney'], 2);//互斥商品总金额
  2329. }
  2330. $cartNum = bcadd($cartNum, 1);
  2331. $goodsNum = bcadd($goodsNum, $val['buyNum']);
  2332. }
  2333. $result = [
  2334. 'totalMoney' => $totalMoney,
  2335. 'payMoney' => $payMoney,
  2336. 'preferential' => $preferential,
  2337. 'vipDiscount' => $vipDiscount,
  2338. 'vipDoubleDiscount' => $vipDoubleDiscount,
  2339. 'activityMoney' => $activityMoney,
  2340. 'expressMoney' => $this->expressMoney,
  2341. 'checkNum' => (int)$checkNum,
  2342. 'cartNum' => (int)$cartNum,
  2343. 'goodsNum' => (int)$goodsNum,
  2344. 'goodsData' => array_values($goodsData),
  2345. 'invalidData' => array_values($this->invalidData)
  2346. ];
  2347. $objMPreferentialProcess = new MPreferentialProcess($this->onlineUserId, $this->onlineEnterpriseId);
  2348. $result = $objMPreferentialProcess->Preferential($result, $vipCardId, $userCouponId);
  2349. if(!$result->isSuccess()){
  2350. return ResultWrapper::fail($result->getData(), $result->getErrorCode());
  2351. }
  2352. $result = $result->getData();
  2353. if (
  2354. (!empty($vipCardId) && $vipCardId != 0)
  2355. || (!empty($userCouponId) && $userCouponId != 0)
  2356. ) {
  2357. //优惠券优惠,会员卡优惠分摊到商品
  2358. $result = self::calAvg($result);
  2359. }
  2360. //处理运费
  2361. $result = self::freeExpressPrice($result);
  2362. $result['expressMoney'] != 0 && $result['payMoney'] = bcadd($result['payMoney'], $result['expressMoney'], 2);
  2363. return ResultWrapper::success($result);
  2364. }
  2365. /**
  2366. * Doc: (des="")
  2367. * User: XMing
  2368. * Date: 2020/9/18
  2369. * Time: 2:56 下午
  2370. * @param $result
  2371. * @return mixed
  2372. */
  2373. private function freeExpressPrice($result)
  2374. {
  2375. $expressMoney = $result['expressMoney'];
  2376. $payMoney = $result['payMoney'];
  2377. $goodsData = $result['goodsData'];
  2378. if ($expressMoney != 0 && $this->freeExpressPrice <= $payMoney && $this->freeExpressPrice != 0) {
  2379. foreach ($goodsData as &$datum) {
  2380. $shopExpressMoney = $datum['expressMoney'];
  2381. $datum['expressMoney'] = '0.00';
  2382. $datum['payMoney'] = bcsub($datum['payMoney'], $shopExpressMoney, 2);
  2383. }
  2384. $expressMoney = '0.00';
  2385. }
  2386. $result['goodsData'] = $goodsData;
  2387. $result['expressMoney'] = $expressMoney;
  2388. return $result;
  2389. }
  2390. /**
  2391. *
  2392. * 优惠计算分摊规则
  2393. * A商品 100元
  2394. * B商品 300元
  2395. * 商品总价 400元
  2396. *
  2397. * A商品享受的优惠 = 优惠券金额*(A商品原价/商品总价)
  2398. * B商品享受的优惠 = 优惠券金额*(B商品原价/商品总价)
  2399. *
  2400. * 优惠券(满100减20) -20
  2401. * 共 -220
  2402. * 实际付款 180
  2403. * A总(220*(100/400)=55) 优惠券(20*(100/400)=5)
  2404. * B总(220*(300/400)=165) 优惠券(20*(300/400)=15)
  2405. * @param $data
  2406. * @return mixed
  2407. */
  2408. private function calAvg($data)
  2409. {
  2410. $account = 0; // 优惠劵优惠金额
  2411. foreach ($data['goodsData'] as &$shops) {
  2412. $count = count($shops['shopGoodsData']);
  2413. foreach ($shops['shopGoodsData'] as $key => &$goods) {
  2414. // 是否为互斥商品
  2415. if ($goods['isMutex'] == StatusCode::$delete) {
  2416. //活动商品不分摊
  2417. if ($data['preferential'] != 0) {
  2418. //有优惠券优惠,分摊金额
  2419. if ($key + 1 != $count) {
  2420. $goods['preferential'] = bcmul($data['preferential'], bcdiv($goods['totalMoney'], $data['totalMoney'], 2), 2);
  2421. $account = bcadd($account, $goods['preferential'], 2);
  2422. } else {
  2423. //最后一个商品分摊金额=总优惠-其他均摊
  2424. $goods['preferential'] = bcsub($data['preferential'], $account, 2);
  2425. }
  2426. }
  2427. }
  2428. if ($data['vipDiscount'] != 0) {
  2429. /**
  2430. * A商品 10 B商品 20 合计30元 折扣1折 A打折9 B打折18 总折扣27
  2431. * A商品折扣金额 = 10 - (10 X (30 - 27)) / 30
  2432. */
  2433. // 会员卡总优惠金额 = 会员卡优惠后的总金额 = 订单实际支付金额
  2434. $vipCardEndDiscountMoney = bcsub($data['totalMoney'],$data['vipDiscount'], 2);
  2435. // 当前商品优惠后的金额 = 当前商品价格 * 会员卡优惠后总金额 / 订单实际支付金额
  2436. $goodsVipCardEndDiscountMoney = bcdiv(bcmul($goods['totalMoney'],$vipCardEndDiscountMoney,2), $data['totalMoney'],2);
  2437. // 当前商品优惠金额 = 当前商品价格 - 当前商品优惠后的金额
  2438. $goods['vipDiscount'] = bcsub($goods['totalMoney'], $goodsVipCardEndDiscountMoney, 2);
  2439. }
  2440. }
  2441. }
  2442. return $data;
  2443. }
  2444. /**
  2445. * 后台--清空用户购物车
  2446. */
  2447. public function clearCart()
  2448. {
  2449. $where['userCenterId'] = $this->onlineUserId;
  2450. $dbResult = $this->objDCart->delete($where);
  2451. if ($dbResult === false) {
  2452. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  2453. }
  2454. return ResultWrapper::success($dbResult);
  2455. }
  2456. /**
  2457. * 批量删除购物车商品
  2458. * @param $params
  2459. * @return ResultWrapper
  2460. */
  2461. public function clearCartByGoodsId($params)
  2462. {
  2463. $where['userCenterId'] = $this->onlineUserId;
  2464. $where['goodsId'] = $params['goodsId'];
  2465. $dbResult = $this->objDCart->delete($where);
  2466. if ($dbResult === false) {
  2467. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  2468. }
  2469. return ResultWrapper::success($dbResult);
  2470. }
  2471. /**
  2472. * 确认订单
  2473. *
  2474. * @param int $userCouponId 优惠券id
  2475. * @param string $vipCardId 会员卡id
  2476. * @param string $addressId
  2477. * @param string $deliveryId
  2478. * @return ResultWrapper
  2479. * @throws \Exception
  2480. */
  2481. public function confirmationOfOrder($userCouponId = '', $vipCardId = '', $addressId = '', $deliveryId = '')
  2482. {
  2483. // 获取客户信息
  2484. $objMCustomer = new MCustomer($this->onlineEnterpriseId, $this->onlineUserId);
  2485. $result = $objMCustomer->getCustomerData(['userCenterId'=>$this->onlineUserId],'*', true);
  2486. if(!$result->isSuccess()){
  2487. return ResultWrapper::fail($result->getData(), $result->getErrorCode());
  2488. }
  2489. $customerData = $result->getData();
  2490. if (empty($customerData)) {
  2491. return ResultWrapper::fail('未找到客户信息', ErrorCode::$paramError);
  2492. }
  2493. $customerId = $customerData['id'];
  2494. // 获取客户的默认收货地址
  2495. $objMShippingAddress = new MShippingAddress($this->onlineEnterpriseId);
  2496. $selectParams = [
  2497. 'deleteStatus' => StatusCode::$standard,
  2498. 'defaultStatus' => StatusCode::$standard,
  2499. 'customerId' => $customerId
  2500. ];
  2501. $dbResult = $objMShippingAddress->getShippingAddressInfo($selectParams);
  2502. if (!$dbResult->isSuccess()) {
  2503. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  2504. }
  2505. $addRessData = $dbResult->getData();
  2506. unset($dbResult);
  2507. // 获取自提点
  2508. $objMDeliverySetting = new MDeliverySetting($this->onlineUserId, $this->onlineEnterpriseId);
  2509. $selfExpressRuleResult = $objMDeliverySetting->getAllSelfExpressRule();
  2510. if (!$selfExpressRuleResult->isSuccess()) {
  2511. return ResultWrapper::fail($selfExpressRuleResult->getData(), $selfExpressRuleResult->getErrorCode());
  2512. }
  2513. $selfExpressRule = $selfExpressRuleResult->getData();
  2514. //支付方式
  2515. $objMEnterpriseBindPayment = new MEnterpriseBindPayment($this->onlineUserId, $this->onlineEnterpriseId);
  2516. $paymentData = $objMEnterpriseBindPayment->getPaymentType();
  2517. if (!$paymentData->isSuccess()) {
  2518. $paymentData = [];
  2519. } else {
  2520. $paymentData = $paymentData->getData();
  2521. }
  2522. //配送方式
  2523. $objMDeliverySetting = new MDeliverySetting($this->onlineUserId, $this->onlineEnterpriseId);
  2524. $DeliveryData = $objMDeliverySetting->allDelivery();
  2525. if (!$DeliveryData->isSuccess()) {
  2526. $DeliveryData = [];
  2527. } else {
  2528. $DeliveryData = array_values($DeliveryData->getData()['data']);
  2529. }
  2530. //当前用户选择的配送方式
  2531. if (!empty($deliveryId)) {
  2532. $this->onlineUserDefaultDeliveryType = $deliveryId;
  2533. } else {
  2534. if (!empty($DeliveryData)) {
  2535. foreach ($DeliveryData as $value) {
  2536. if ($value['defaultStatus'] == StatusCode::$standard) {
  2537. $this->onlineUserDefaultDeliveryType = $value['deliveryType'];
  2538. break;
  2539. }
  2540. }
  2541. }
  2542. }
  2543. //当前用户的收货地址code 省-市-区
  2544. if (!empty($addressId)) {
  2545. $addressResult = $objMShippingAddress->getShippingAddressInfo(['id' => $addressId]);
  2546. if (!$addressResult->isSuccess()) {
  2547. return ResultWrapper::fail($addressResult->getData(), ErrorCode::$dberror);
  2548. }
  2549. $addressInfo = $addressResult->getData();
  2550. if (!empty($addressInfo)) {
  2551. $this->onlineUserAddressCode = $addressInfo['provinceCode'] . '-' . $addressInfo['cityCode'] . '-' . $addressInfo['districtCode'];
  2552. }
  2553. } else {
  2554. if (!empty($addRessData)) {
  2555. $this->onlineUserAddressCode = $addRessData['provinceCode'] . '-' . $addRessData['cityCode'] . '-' . $addRessData['districtCode'];
  2556. }
  2557. }
  2558. //获取当前企业设置的包邮价格
  2559. $objMBasicSetup = new MBasicSetup($this->onlineEnterpriseId);
  2560. $freeExpressPriceResult = $objMBasicSetup->getBasicField('freeExpressPrice');
  2561. if (!$freeExpressPriceResult->isSuccess()) {
  2562. return ResultWrapper::fail($freeExpressPriceResult->getData(), $freeExpressPriceResult->getData());
  2563. }
  2564. $freeExpressPrice = $freeExpressPriceResult->getData();
  2565. $this->freeExpressPrice = (isset($freeExpressPrice['freeExpressPrice']) && !empty($freeExpressPrice['freeExpressPrice'])) ? $freeExpressPrice['freeExpressPrice'] : 0;
  2566. //获取购物车选中的数据
  2567. $dbResult = $this->objDCart->select(['selection' => StatusCode::$standard, 'userCenterId' => $this->onlineUserId], 'id,goodsId,goodsCode,buyNum,shopId,goodsBasicId,selection,skuId,warehouseId,activityId', 'createTime DESC');
  2568. if ($dbResult === false) {
  2569. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  2570. }
  2571. if (empty($dbResult)) {
  2572. return ResultWrapper::fail('购物车中没有选定的商品', ErrorCode::$paramError);
  2573. }
  2574. //所有结算商品id
  2575. $goodsIds = array_values(array_column($dbResult, 'goodsId'));
  2576. $cartDataResult = self::formatGoodsAndShop($dbResult, $userCouponId, $vipCardId);
  2577. if (!$cartDataResult->isSuccess()) {
  2578. return ResultWrapper::fail($cartDataResult->getData(), $cartDataResult->getErrorCode());
  2579. }
  2580. $cartData = $cartDataResult->getData();
  2581. if (empty($cartData['goodsData'])) {
  2582. return ResultWrapper::fail('购物车中商品已失效,不能进行结算', ErrorCode::$paramError);
  2583. }
  2584. if (empty($addRessData)) {
  2585. $cartData['address'] = (object)[];
  2586. } else {
  2587. $objMSysAreaChina = new MSysAreaChina();
  2588. $areaName = $objMSysAreaChina->getNameByCode([
  2589. $addRessData['provinceCode'],
  2590. $addRessData['cityCode'],
  2591. $addRessData['districtCode']
  2592. ]);
  2593. $cartData['address'] = [
  2594. 'name' => isset($addRessData['name']) ? $addRessData['name'] : '',
  2595. 'mobile' => isset($addRessData['mobile']) ? $addRessData['mobile'] : '',
  2596. 'address' => isset($addRessData['address']) ? $addRessData['address'] : '',
  2597. 'id' => isset($addRessData['id']) ? $addRessData['id'] : '',
  2598. 'provinceName' => isset($areaName[$addRessData['provinceCode']]) ? $areaName[$addRessData['provinceCode']] : '',
  2599. 'cityName' => isset($areaName[$addRessData['cityCode']]) ? $areaName[$addRessData['cityCode']] : '',
  2600. 'districtName' => isset($areaName[$addRessData['districtCode']]) ? $areaName[$addRessData['districtCode']] : '',
  2601. ];
  2602. }
  2603. //订单使用的优惠券
  2604. $userCouponInfo = [];
  2605. if (!empty($userCouponId)) {
  2606. $objMUserCoupon = new MUserCoupon($this->onlineUserId, $this->onlineEnterpriseId);
  2607. $dbResult = $objMUserCoupon->getUserCoupon(['id' => $userCouponId]);
  2608. if ($dbResult->isSuccess()) $userCouponInfo = $dbResult->getData();
  2609. $userCouponInfo = isset($userCouponInfo[0]) ? $userCouponInfo[0] : [];
  2610. }
  2611. $cartData['useCoupon'] = $userCouponInfo;
  2612. // 订单金额小于银行打款设置的启用金额,不支持银行打款
  2613. if(!empty($paymentData)){
  2614. foreach ($paymentData as $key => $value){
  2615. if($value['id'] == StatusCode::$payType['bankLoans'] && $cartData['payMoney'] < $value['limit']){
  2616. unset($paymentData[$key]);
  2617. }
  2618. }
  2619. }
  2620. $cartData['payment'] = array_values($paymentData);
  2621. $cartData['delivery'] = $DeliveryData;
  2622. $cartData['selfExpressRule'] = $selfExpressRule;
  2623. //优惠券数据
  2624. $cartData = self::findCoupon($cartData);
  2625. //获取订单会员卡
  2626. $vipCard = self::getVipCard($goodsIds);
  2627. if ($vipCard->isSuccess()) {
  2628. $vipCard = $vipCard->getData();
  2629. } else {
  2630. $vipCard = [];
  2631. }
  2632. $cartData['vipCard'][] = $vipCard;
  2633. // 客户余额
  2634. $cartData['balance'] = $customerData['money'];
  2635. // 会员余额
  2636. $cartData['memberBalance'] = $customerData['memberBalance'];
  2637. return ResultWrapper::success($cartData);
  2638. }
  2639. /**
  2640. * @param $goodsIds
  2641. * @return array|ResultWrapper
  2642. */
  2643. public function getVipCard($goodsIds)
  2644. {
  2645. $objMVipCard = new MVipCard($this->onlineEnterpriseId, $this->onlineUserId, true);
  2646. $pageParams = pageToOffset(1, 10);
  2647. $selectParams['limit'] = $pageParams['limit'];
  2648. $selectParams['offset'] = $pageParams['offset'];
  2649. $dbResult = $objMVipCard->getMyVipCards($selectParams);
  2650. if (!$dbResult->isSuccess()) {
  2651. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  2652. }
  2653. $vipCard = $dbResult->getData()['data'];
  2654. if (empty($vipCard)) return ResultWrapper::success([]);
  2655. if (!empty($goodsIds)) {
  2656. foreach ($vipCard as $key => $card) {
  2657. if ($card['mode'] == StatusCode::$delete) {
  2658. $cardGoodsArr = explode(',', $card['goodsIds']);
  2659. foreach ($goodsIds as $goodsId) {
  2660. if (!in_array($goodsId, $cardGoodsArr)) {
  2661. unset($vipCard[$key]);
  2662. }
  2663. }
  2664. }
  2665. }
  2666. }
  2667. $vipCard = empty($vipCard) ? [] : array_shift($vipCard);
  2668. return ResultWrapper::success($vipCard);
  2669. }
  2670. /**
  2671. * 判断在使用范围的店铺,指定商品是否满足最小金额
  2672. * 查询可用的优惠券
  2673. * @param $data
  2674. * @return mixed
  2675. * @throws \Exception
  2676. */
  2677. private function findCoupon($data)
  2678. {
  2679. $objMUserCoupon = new MUserCoupon($this->onlineUserId, $this->onlineEnterpriseId);
  2680. $objGoodsBasicRelevant = new GoodsBasicRelevant($this->onlineEnterpriseId);
  2681. $payAmount = $data['payMoney'];
  2682. if ($data['activityMoney'] != 0) {
  2683. $payAmount = bcsub($payAmount, $data['activityMoney'], 2);
  2684. }
  2685. $dbResult = $objMUserCoupon->availableCoupon([
  2686. 'payAmount' => $payAmount
  2687. ]);
  2688. if (!$dbResult->isSuccess()) {
  2689. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  2690. }
  2691. $coupon = $dbResult->getData();
  2692. foreach ($coupon as $key => $val) {
  2693. $useShop = explode(',', $val['useShop']);//此优惠券可以使用的店铺
  2694. $applyRange = $val['applyRange'];//优惠券使用范围
  2695. $cart[$val['id']]['money'] = 0;
  2696. foreach ($data['goodsData'] as $shopGoodsData) {
  2697. foreach ($shopGoodsData['shopGoodsData'] as $goodsDetail) {
  2698. $categoryId = $objGoodsBasicRelevant->getNameByBasicId($goodsDetail['goodsBasicId'], 'categoryId');
  2699. $brandId = $objGoodsBasicRelevant->getNameByBasicId($goodsDetail['goodsBasicId'], 'brandId');
  2700. if (in_array($shopGoodsData['shopId'], $useShop) &&
  2701. ($applyRange == StatusCode::$applyRange['allGoods'] ||
  2702. in_array($categoryId, explode(',', $val['categoryCollect'])) ||
  2703. in_array($goodsDetail['goodsId'], explode(',', $val['goodsCollect'])) ||
  2704. in_array($brandId, explode(',', $val['brandCollect'])))
  2705. ) {
  2706. $cart[$val['id']]['money'] = bcadd($cart[$val['id']]['money'], $goodsDetail['totalMoney']);//规定范围内的商品总金额
  2707. }
  2708. }
  2709. }
  2710. if ($val['minPrice'] != 0 && $cart[$val['id']]['money'] < $val['minPrice']) {
  2711. unset($coupon[$key]);//不符合要求
  2712. }
  2713. }
  2714. $data['coupon'] = array_values($coupon);
  2715. return $data;
  2716. }
  2717. /**
  2718. * 获取商品,规格 购物车数量
  2719. * @param $goodsIds
  2720. * @return array
  2721. */
  2722. public function getCartNumByGoodsId($goodsIds)
  2723. {
  2724. $cartData = $this->objDCart->select(['goodsId' => $goodsIds, 'userCenterId' => $this->onlineUserId], 'buyNum,goodsId,skuId');
  2725. if ($cartData === false) {
  2726. return [];
  2727. }
  2728. $return = [];
  2729. foreach ($cartData as $key => $val) {
  2730. $return[$val['goodsId']][$val['skuId']] = $val['buyNum'];
  2731. }
  2732. return $return;
  2733. }
  2734. /**
  2735. * 商品列表页调整购买数量
  2736. * @param $params
  2737. * @return ResultWrapper
  2738. * @throws \Exception
  2739. */
  2740. public function updateCartNum($params)
  2741. {
  2742. if ($params['buyNum'] == 0) {
  2743. $dbResult = $this->objDCart->delete([
  2744. 'goodsId' => $params['goodsId'],
  2745. 'skuId' => $params['skuId'],
  2746. 'userCenterId' => $this->onlineUserId
  2747. ]);
  2748. } else {
  2749. $goods = self::getCartInventory([
  2750. 'goodsId' => $params['goodsId'],
  2751. 'skuId' => $params['skuId'],
  2752. 'userCenterId' => $this->onlineUserId
  2753. ]);
  2754. if (!$goods->isSuccess()) {
  2755. return ResultWrapper::fail($goods->getData(), ErrorCode::$dberror);
  2756. }
  2757. $goods = $goods->getData();
  2758. $inventoryNum = isset($goods[0]['inventory']) ? $goods[0]['inventory'] : 0;//商品剩余库存
  2759. $setNum = isset($goods[0]['setNum']) ? $goods[0]['setNum'] : 0;//商品规格起订数量
  2760. $title = isset($goods[0]['title']) ? $goods[0]['title'] : '';//商品名称
  2761. if ($inventoryNum < $params['buyNum']) {
  2762. return ResultWrapper::fail('商品库存不足', ErrorCode::$paramError);
  2763. }
  2764. if ($params['buyNum'] < $setNum) {
  2765. return ResultWrapper::fail($title . '最小起订数量' . $setNum, ErrorCode::$paramError);
  2766. }
  2767. $dbResult = $this->objDCart->update(
  2768. [
  2769. 'buyNum' => $params['buyNum']
  2770. ],
  2771. [
  2772. 'goodsId' => $params['goodsId'],
  2773. 'skuId' => $params['skuId'],
  2774. 'userCenterId' => $this->onlineUserId
  2775. ]
  2776. );
  2777. }
  2778. if ($dbResult === false) {
  2779. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  2780. }
  2781. return ResultWrapper::success($dbResult);
  2782. }
  2783. /**
  2784. * 验证购物车内商品规格的库存
  2785. * @param $selectParams
  2786. * @return int|ResultWrapper
  2787. * @throws \Exception
  2788. */
  2789. private function getCartInventory($selectParams)
  2790. {
  2791. $dbResult = $this->objDCart->get($selectParams);
  2792. if ($dbResult === false) {
  2793. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  2794. }
  2795. if (empty($dbResult)) {
  2796. return ResultWrapper::success([]);
  2797. }
  2798. $result = self::checkCart([$dbResult]);
  2799. if (!$result->isSuccess()) {
  2800. return ResultWrapper::fail($result->getData(), $result->getErrorCode());
  2801. }
  2802. return ResultWrapper::success($result->getData());
  2803. }
  2804. /**
  2805. * Doc: (des="")
  2806. * User: XMing
  2807. * Date: 2021/1/8
  2808. * Time: 10:30 上午
  2809. * @param int $skuId
  2810. * @param int $userId
  2811. * @return ResultWrapper
  2812. */
  2813. public function getCartBuyNumBySku(int $skuId, int $userId): ResultWrapper
  2814. {
  2815. $sql = 'SELECT SUM(`buyNum`) AS subBuyNum FROM qianniao_cart_' . $this->onlineEnterpriseId . ' WHERE skuId = ' . $skuId . ' AND userCenterId = ' . $userId;
  2816. $sum = $this->objDCart->query($sql);
  2817. if ($sum === false) {
  2818. return ResultWrapper::fail($this->objDCart->error(), ErrorCode::$dberror);
  2819. }
  2820. $subBuyNum = isset($sum[0]['subBuyNum']) ? $sum[0]['subBuyNum'] : 0;
  2821. return ResultWrapper::success($subBuyNum);
  2822. }
  2823. /**
  2824. * Doc: (des="组团立即购买")
  2825. * User: XMing
  2826. * Date: 2021/1/22
  2827. * Time: 4:18 下午
  2828. * @param array $lists
  2829. * @param array $data
  2830. * @return ResultWrapper
  2831. * @throws \Exception
  2832. */
  2833. public function buyNow(array $lists, array $data): ResultWrapper
  2834. {
  2835. switch ($data['sourceType']) {
  2836. case self::$sourceType['comBin']:
  2837. $buyResult = self::buyComBin($lists, $data);
  2838. break;
  2839. }
  2840. if (!$buyResult->isSuccess()) {
  2841. return ResultWrapper::fail($buyResult->getData(), $buyResult->getErrorCode());
  2842. }
  2843. return ResultWrapper::success($buyResult->getData());
  2844. }
  2845. /**
  2846. * 普通商品立即购买
  2847. */
  2848. public function goodsBuyNow(array $goods, array $data)
  2849. {
  2850. //获取当前用户的客户id
  2851. $objMCustomer = new MCustomer($this->onlineEnterpriseId, $this->onlineUserId);
  2852. $result = $objMCustomer->getCustomerData(['userCenterId'=>$this->onlineUserId],'*', true);
  2853. if(!$result->isSuccess()){
  2854. return ResultWrapper::fail($result->getData(), $result->getErrorCode());
  2855. }
  2856. $customerData = $result->getData();
  2857. if (empty($customerData)) {
  2858. return ResultWrapper::fail('未找到客户信息', ErrorCode::$paramError);
  2859. }
  2860. $customerId = $customerData['id'];
  2861. //获取客户的默认收货地址
  2862. $objMShippingAddress = new MShippingAddress($this->onlineEnterpriseId);
  2863. $selectParams = [
  2864. 'deleteStatus' => StatusCode::$standard,
  2865. 'defaultStatus' => StatusCode::$standard,
  2866. 'customerId' => $customerId
  2867. ];
  2868. $dbResult = $objMShippingAddress->getShippingAddressInfo($selectParams);
  2869. if (!$dbResult->isSuccess()) {
  2870. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  2871. }
  2872. $addRessData = $dbResult->getData();
  2873. unset($dbResult);
  2874. //获取自提点
  2875. $objMDeliverySetting = new MDeliverySetting($this->onlineUserId, $this->onlineEnterpriseId);
  2876. $selfExpressRuleResult = $objMDeliverySetting->getAllSelfExpressRule();
  2877. if (!$selfExpressRuleResult->isSuccess()) {
  2878. return ResultWrapper::fail($selfExpressRuleResult->getData(), $selfExpressRuleResult->getErrorCode());
  2879. }
  2880. $selfExpressRule = $selfExpressRuleResult->getData();
  2881. //支付方式
  2882. $objMEnterpriseBindPayment = new MEnterpriseBindPayment($this->onlineUserId, $this->onlineEnterpriseId);
  2883. $paymentData = $objMEnterpriseBindPayment->getPaymentType();
  2884. if (!$paymentData->isSuccess()) {
  2885. $paymentData = [];
  2886. } else {
  2887. $paymentData = $paymentData->getData();
  2888. }
  2889. //配送方式
  2890. $objMDeliverySetting = new MDeliverySetting($this->onlineUserId, $this->onlineEnterpriseId);
  2891. $DeliveryData = $objMDeliverySetting->allDelivery();
  2892. if (!$DeliveryData->isSuccess()) {
  2893. $DeliveryData = [];
  2894. } else {
  2895. $DeliveryData = array_values($DeliveryData->getData()['data']);
  2896. }
  2897. //当前用户选择的配送方式
  2898. if (!empty($data['deliveryId'])) {
  2899. $this->onlineUserDefaultDeliveryType = $data['deliveryId'];
  2900. } else {
  2901. if (!empty($DeliveryData)) {
  2902. foreach ($DeliveryData as $value) {
  2903. if ($value['defaultStatus'] == StatusCode::$standard) {
  2904. $this->onlineUserDefaultDeliveryType = $value['deliveryType'];
  2905. break;
  2906. }
  2907. }
  2908. }
  2909. }
  2910. //当前用户的收货地址code 省-市-区
  2911. if (!empty($addressId)) {
  2912. $addressResult = $objMShippingAddress->getShippingAddressInfo(['id' => $data['addressId']]);
  2913. if (!$addressResult->isSuccess()) {
  2914. return ResultWrapper::fail($addressResult->getData(), ErrorCode::$dberror);
  2915. }
  2916. $addressInfo = $addressResult->getData();
  2917. if (!empty($addressInfo)) {
  2918. $this->onlineUserAddressCode = $addressInfo['provinceCode'] . '-' . $addressInfo['cityCode'] . '-' . $addressInfo['districtCode'];
  2919. }
  2920. } else {
  2921. if (!empty($addRessData)) {
  2922. $this->onlineUserAddressCode = $addRessData['provinceCode'] . '-' . $addRessData['cityCode'] . '-' . $addRessData['districtCode'];
  2923. }
  2924. }
  2925. //获取当前企业设置的包邮价格
  2926. $objMBasicSetup = new MBasicSetup($this->onlineEnterpriseId);
  2927. $freeExpressPriceResult = $objMBasicSetup->getBasicField('freeExpressPrice');
  2928. if (!$freeExpressPriceResult->isSuccess()) {
  2929. return ResultWrapper::fail($freeExpressPriceResult->getData(), $freeExpressPriceResult->getData());
  2930. }
  2931. $freeExpressPrice = $freeExpressPriceResult->getData();
  2932. $this->freeExpressPrice = (isset($freeExpressPrice['freeExpressPrice']) && !empty($freeExpressPrice['freeExpressPrice'])) ? $freeExpressPrice['freeExpressPrice'] : 0;
  2933. //所有结算商品id
  2934. $goodsIds = [$goods['goodsId']];
  2935. $cartDataResult = self::formatGoodsAndShop([$goods], $data['couponId'], $data['vipCardId']);
  2936. if (!$cartDataResult->isSuccess()) {
  2937. return ResultWrapper::fail($cartDataResult->getData(), $cartDataResult->getErrorCode());
  2938. }
  2939. $cartData = $cartDataResult->getData();
  2940. if (empty($cartData['goodsData'])) {
  2941. return ResultWrapper::fail('商品已失效,不能进行结算', ErrorCode::$paramError);
  2942. }
  2943. if (empty($addRessData)) {
  2944. $cartData['address'] = (object)[];
  2945. } else {
  2946. $objMSysAreaChina = new MSysAreaChina();
  2947. $areaName = $objMSysAreaChina->getNameByCode([
  2948. $addRessData['provinceCode'],
  2949. $addRessData['cityCode'],
  2950. $addRessData['districtCode']
  2951. ]);
  2952. $cartData['address'] = [
  2953. 'name' => isset($addRessData['name']) ? $addRessData['name'] : '',
  2954. 'mobile' => isset($addRessData['mobile']) ? $addRessData['mobile'] : '',
  2955. 'address' => isset($addRessData['address']) ? $addRessData['address'] : '',
  2956. 'id' => isset($addRessData['id']) ? $addRessData['id'] : '',
  2957. 'provinceName' => isset($areaName[$addRessData['provinceCode']]) ? $areaName[$addRessData['provinceCode']] : '',
  2958. 'cityName' => isset($areaName[$addRessData['cityCode']]) ? $areaName[$addRessData['cityCode']] : '',
  2959. 'districtName' => isset($areaName[$addRessData['districtCode']]) ? $areaName[$addRessData['districtCode']] : '',
  2960. ];
  2961. }
  2962. //订单使用的优惠券
  2963. $userCouponInfo = [];
  2964. if (!empty($data['couponId'])) {
  2965. $objMUserCoupon = new MUserCoupon($this->onlineUserId, $this->onlineEnterpriseId);
  2966. $dbResult = $objMUserCoupon->getUserCoupon(['id' => $data['couponId']]);
  2967. if ($dbResult->isSuccess()) $userCouponInfo = $dbResult->getData();
  2968. $userCouponInfo = isset($userCouponInfo[0]) ? $userCouponInfo[0] : [];
  2969. }
  2970. // 订单金额小于银行打款设置的启用金额,不支持银行打款
  2971. if(!empty($paymentData)){
  2972. foreach ($paymentData as $key => $value){
  2973. if($value['id'] == StatusCode::$payType['bankLoans'] && $cartData['payMoney'] <= $value['limit']){
  2974. unset($paymentData[$key]);
  2975. }
  2976. }
  2977. }
  2978. $cartData['payment'] = array_values($paymentData);
  2979. $cartData['useCoupon'] = $userCouponInfo;
  2980. $cartData['delivery'] = $DeliveryData;
  2981. $cartData['selfExpressRule'] = $selfExpressRule;
  2982. //优惠券数据
  2983. $cartData = self::findCoupon($cartData);
  2984. //获取订单会员卡
  2985. $vipCard = self::getVipCard($goodsIds);
  2986. if ($vipCard->isSuccess()) {
  2987. $vipCard = $vipCard->getData();
  2988. } else {
  2989. $vipCard = [];
  2990. }
  2991. $cartData['vipCard'][] = $vipCard;
  2992. // 客户余额
  2993. $cartData['balance'] = $customerData['money'];
  2994. // 会员余额
  2995. $cartData['memberBalance'] = $customerData['memberBalance'];
  2996. return ResultWrapper::success($cartData);
  2997. }
  2998. /**
  2999. * Doc: (des="购买组合套餐")
  3000. * User: XMing
  3001. * Date: 2021/1/22
  3002. * Time: 4:34 下午
  3003. * @param array $lists
  3004. * @param array $data
  3005. * @return ResultWrapper
  3006. * @throws \Exception
  3007. */
  3008. private function buyComBin(array $lists, array $data): ResultWrapper
  3009. {
  3010. $objMCustomer = new MCustomer($this->onlineEnterpriseId,$this->onlineUserId);
  3011. $customerId = $objMCustomer->getCustomerIdByUserCenterId($this->onlineUserId);
  3012. //验证组合套餐
  3013. if (empty($data['comBinId'])) {
  3014. return ResultWrapper::fail('组合套餐错误', ErrorCode::$paramError);
  3015. }
  3016. $objMComBinPackage = new MComBinPackage($this->onlineEnterpriseId, $this->onlineUserId);
  3017. $detailsResult = $objMComBinPackage->details($data['comBinId']);
  3018. if (!$detailsResult->isSuccess()) {
  3019. return ResultWrapper::fail($detailsResult->getData(), $detailsResult->getErrorCode());
  3020. }
  3021. $details = $detailsResult->getData();
  3022. if (empty($details)) {
  3023. return ResultWrapper::fail('未获取到指定的组合套餐', ErrorCode::$paramError);
  3024. }
  3025. $time = time();
  3026. if ($details['isExpire'] == StatusCode::$standard) {
  3027. if ($time < $details['startTime']) {
  3028. return ResultWrapper::fail('组合套餐活动未开始', ErrorCode::$paramError);
  3029. }
  3030. if ($time > $details['endTime']) {
  3031. return ResultWrapper::fail('组合套餐活动已结束', ErrorCode::$paramError);
  3032. }
  3033. }
  3034. if ($details['isLimit'] == StatusCode::$standard) {
  3035. //获取用户组合套餐购买数量(TODO)
  3036. $user_log_num = 0;
  3037. if ($user_log_num >= $details['limitNum']) {
  3038. return ResultWrapper::fail('你已经购买过此组合套餐了', ErrorCode::$paramError);
  3039. }
  3040. }
  3041. //验证商品在售状态,sku是否参与组合,库存
  3042. $allowSkuArr = [];
  3043. $goodsData = $details['goodsData'];
  3044. $mapping = [];//商品映射
  3045. foreach ($goodsData as $goods) {
  3046. $sku = $goods['joinSku'];
  3047. $allowSkuArr = array_merge($sku, $allowSkuArr);
  3048. $mapping[$goods['id']] = $goods;
  3049. }
  3050. //验证商品完整性
  3051. $goodsIdArr = explode(',', $details['goodsIds']);
  3052. $selectGoodsIdArr = [];
  3053. foreach ($lists as $val) {
  3054. if (!in_array($val['goodsId'], $selectGoodsIdArr)) {
  3055. $selectGoodsIdArr[] = $val['goodsId'];
  3056. }
  3057. $thisRow = getArrayItem($mapping,$val['goodsId'],[]);
  3058. if (isset($thisRow['joinSku']) && !empty($thisRow['joinSku'])){
  3059. if (!in_array($val['skuId'], $allowSkuArr)) {
  3060. return ResultWrapper::fail('商品规格选择异常', ErrorCode::$paramError);
  3061. }
  3062. }
  3063. }
  3064. $diffBool = array_diff($goodsIdArr, $selectGoodsIdArr);
  3065. if (!empty($diffBool)) {
  3066. return ResultWrapper::fail('你还没选择完组合商品', ErrorCode::$paramError);
  3067. }
  3068. unset($diffBool);
  3069. //店铺
  3070. $objMGoods = new MShop($this->onlineEnterpriseId, $this->onlineUserId);
  3071. $shopResult = $objMGoods->getShopByIdd($details['shopId']);
  3072. if (!$shopResult->isSuccess()) {
  3073. return ResultWrapper::fail($shopResult->getData(), $shopResult->getErrorCode());
  3074. }
  3075. $shop = $shopResult->getData();
  3076. $c_goods_Lists = [];
  3077. foreach ($lists as $val) {
  3078. if (!isset($mapping[$val['goodsId']])) {
  3079. return ResultWrapper::fail('商品信息异常', ErrorCode::$paramError);
  3080. }
  3081. $row = getArrayItem($mapping, $val['goodsId'], []);
  3082. $specMultiple = getArrayItem($row, 'specMultiple', []);
  3083. $specMultipleMap = [];//sku映射
  3084. foreach ($specMultiple as $value) {
  3085. $specMultipleMap[$value['id']] = $value;
  3086. }
  3087. if ($row['enableStatus'] == StatusCode::$delete) {
  3088. return ResultWrapper::fail('组合套餐商品下架了', ErrorCode::$paramError);
  3089. }
  3090. $skuRow = getArrayItem($specMultipleMap, $val['skuId'], []);
  3091. if ($this->preSale == StatusCode::$delete) {
  3092. if ($skuRow['inventory'] < 1) {
  3093. return ResultWrapper::fail('组合套餐库存不足', ErrorCode::$paramError);
  3094. }
  3095. }
  3096. $c_goods_Lists[] = [
  3097. 'goodsId' => getArrayItem($row, 'id', 0),
  3098. 'goodsCode' => createCode(StatusCode::$code['goodsBasic']['prefix'], $row['basicGoodsId'], StatusCode::$code['goodsBasic']['length']),
  3099. 'buyNum' => 1,
  3100. 'shopId' => getArrayItem($row, 'shopId', 0),
  3101. 'shopLogo' => getArrayItem($shop, 'logo', ''),
  3102. 'goodsBasicId' => getArrayItem($row, 'basicGoodsId', 0),
  3103. 'selection' => StatusCode::$standard,
  3104. 'skuId' => $val['skuId'],
  3105. 'warehouseId' => getArrayItem($row, 'warehouseId', 0),
  3106. 'activityId' => 0,
  3107. 'shopName' => getArrayItem($row, 'shopName', ''),
  3108. 'brandName' => getArrayItem($row, 'brandName', ''),
  3109. 'categoryName' => getArrayItem($row, 'categoryName', ''),
  3110. 'barCode' => getArrayItem($skuRow, 'barCode', ''),
  3111. 'storageCode' => getArrayItem($row, 'storageCode', ''),
  3112. 'goodsName' => getArrayItem($row, 'title', ''),
  3113. 'goodsImages' => array_shift($row['images']),
  3114. 'isInvalid' => StatusCode::$standard,
  3115. 'describe' => getArrayItem($row, 'describe', ''),
  3116. 'categoryId' => getArrayItem($row, 'categoryId', 0),
  3117. 'brandId' => getArrayItem($row, 'brandId', 0),
  3118. 'categoryPath' => getArrayItem($row, 'categoryPath', ''),
  3119. 'isActivity' => StatusCode::$delete,
  3120. 'specType' => getArrayItem($row, 'specType', 0),
  3121. 'unitName' => getArrayItem($skuRow, 'unitName', ''),
  3122. 'specGroup' => getArrayItem($skuRow, 'specGroup', []),
  3123. 'notExpress' => StatusCode::$standard,
  3124. 'supplierId' => getArrayItem($row, 'supplierId', 0),
  3125. 'express' => [
  3126. "weight" => getArrayItem($skuRow, 'weight', 0),
  3127. "expressType" => getArrayItem($row, 'expressType', 0),
  3128. "ruleId" => getArrayItem($row, 'ruleId', 0),
  3129. "expressFee" => getArrayItem($row, 'expressFee', 0),
  3130. ],
  3131. 'originPrice' => getArrayItem($skuRow, 'marketPrice', 0),
  3132. 'price' => getArrayItem($skuRow, 'salePrice', 0),
  3133. 'preferential' => 0,
  3134. 'totalMoney' => getArrayItem($skuRow, 'salePrice', 0),
  3135. 'activityMoney' => 0,
  3136. 'isMutex' => StatusCode::$delete,
  3137. 'costPrice' => getArrayItem($skuRow, 'costPrice', 0),
  3138. 'inventoryNum' => getArrayItem($skuRow, 'inventory', 0),
  3139. 'conversion' => getArrayItem($skuRow, 'conversion', 0),
  3140. 'expressMoney' => 0,
  3141. ];
  3142. }
  3143. //获取客户的默认收货地址
  3144. $objMShippingAddress = new MShippingAddress($this->onlineEnterpriseId);
  3145. $selectParams = [
  3146. 'deleteStatus' => StatusCode::$standard,
  3147. 'defaultStatus' => StatusCode::$standard,
  3148. 'customerId' => $customerId
  3149. ];
  3150. $dbResult = $objMShippingAddress->getShippingAddressInfo($selectParams);
  3151. if (!$dbResult->isSuccess()) {
  3152. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  3153. }
  3154. $addRessData = $dbResult->getData();
  3155. unset($dbResult);
  3156. //获取自提点
  3157. $objMDeliverySetting = new MDeliverySetting($this->onlineUserId, $this->onlineEnterpriseId);
  3158. $selfExpressRuleResult = $objMDeliverySetting->getAllSelfExpressRule();
  3159. if (!$selfExpressRuleResult->isSuccess()) {
  3160. return ResultWrapper::fail($selfExpressRuleResult->getData(), $selfExpressRuleResult->getErrorCode());
  3161. }
  3162. $selfExpressRule = $selfExpressRuleResult->getData();
  3163. //支付方式
  3164. $objMEnterpriseBindPayment = new MEnterpriseBindPayment($this->onlineUserId, $this->onlineEnterpriseId);
  3165. $paymentData = $objMEnterpriseBindPayment->getPaymentType();
  3166. if (!$paymentData->isSuccess()) {
  3167. return ResultWrapper::fail($paymentData->getData(),$paymentData->getErrorCode());
  3168. }
  3169. $paymentData = $paymentData->getData();
  3170. //配送方式
  3171. $objMDeliverySetting = new MDeliverySetting($this->onlineUserId, $this->onlineEnterpriseId);
  3172. $DeliveryData = $objMDeliverySetting->allDelivery();
  3173. if (!$DeliveryData->isSuccess()) {
  3174. return ResultWrapper::fail($DeliveryData->getData(),$DeliveryData->getErrorCode());
  3175. }
  3176. $DeliveryData = array_values($DeliveryData->getData()['data']);
  3177. $deliveryId = getArrayItem($data,'deliveryId',0);
  3178. //当前用户选择的配送方式
  3179. if (!empty($deliveryId)) {
  3180. $this->onlineUserDefaultDeliveryType = $deliveryId;
  3181. } else {
  3182. if (!empty($DeliveryData)) {
  3183. foreach ($DeliveryData as $value) {
  3184. if ($value['defaultStatus'] == StatusCode::$standard) {
  3185. $this->onlineUserDefaultDeliveryType = $value['deliveryType'];
  3186. break;
  3187. }
  3188. }
  3189. }
  3190. }
  3191. //当前用户的收货地址code 省-市-区
  3192. $addressId = getArrayItem($data,'addressId',0);
  3193. if (!empty($addressId)) {
  3194. $addressResult = $objMShippingAddress->getShippingAddressInfo(['id' => $addressId]);
  3195. if (!$addressResult->isSuccess()) {
  3196. return ResultWrapper::fail($addressResult->getData(), ErrorCode::$dberror);
  3197. }
  3198. $addressInfo = $addressResult->getData();
  3199. if (!empty($addressInfo)) {
  3200. $this->onlineUserAddressCode = $addressInfo['provinceCode'] . '-' . $addressInfo['cityCode'] . '-' . $addressInfo['districtCode'];
  3201. }
  3202. } else {
  3203. if (!empty($addRessData)) {
  3204. $this->onlineUserAddressCode = $addRessData['provinceCode'] . '-' . $addRessData['cityCode'] . '-' . $addRessData['districtCode'];
  3205. }
  3206. }
  3207. if (empty($addRessData)) {
  3208. $address = (object)[];
  3209. } else {
  3210. $objMSysAreaChina = new MSysAreaChina();
  3211. $areaName = $objMSysAreaChina->getNameByCode([
  3212. $addRessData['provinceCode'],
  3213. $addRessData['cityCode'],
  3214. $addRessData['districtCode']
  3215. ]);
  3216. $address = [
  3217. 'name' => isset($addRessData['name']) ? $addRessData['name'] : '',
  3218. 'mobile' => isset($addRessData['mobile']) ? $addRessData['mobile'] : '',
  3219. 'address' => isset($addRessData['address']) ? $addRessData['address'] : '',
  3220. 'id' => isset($addRessData['id']) ? $addRessData['id'] : '',
  3221. 'provinceName' => isset($areaName[$addRessData['provinceCode']]) ? $areaName[$addRessData['provinceCode']] : '',
  3222. 'cityName' => isset($areaName[$addRessData['cityCode']]) ? $areaName[$addRessData['cityCode']] : '',
  3223. 'districtName' => isset($areaName[$addRessData['districtCode']]) ? $areaName[$addRessData['districtCode']] : '',
  3224. ];
  3225. }
  3226. //获取当前企业设置的包邮价格
  3227. $objMBasicSetup = new MBasicSetup($this->onlineEnterpriseId);
  3228. $freeExpressPriceResult = $objMBasicSetup->getBasicField('freeExpressPrice');
  3229. if (!$freeExpressPriceResult->isSuccess()) {
  3230. return ResultWrapper::fail($freeExpressPriceResult->getData(), $freeExpressPriceResult->getData());
  3231. }
  3232. $freeExpressPrice = $freeExpressPriceResult->getData();
  3233. $this->freeExpressPrice = (isset($freeExpressPrice['freeExpressPrice']) && !empty($freeExpressPrice['freeExpressPrice'])) ? $freeExpressPrice['freeExpressPrice'] : 0;
  3234. //组合套餐是否计算运费
  3235. if ($details['expressType'] = StatusCode::$delete){
  3236. //计算运费
  3237. $result = self::calExpress($c_goods_Lists);
  3238. if (!$result->isSuccess()) {
  3239. return ResultWrapper::fail($result->getData(), $result->getErrorCode());
  3240. }
  3241. }
  3242. $c_shop = [
  3243. 'shopId' => getArrayItem($shop, 'id', 0),
  3244. 'shopName' => getArrayItem($shop, 'name', ''),
  3245. 'shopLogo' => getArrayItem($shop, 'logo', ''),
  3246. 'expressMoney' => $this->expressMoney,
  3247. 'totalMoney' => floatval($details['price']),
  3248. 'preferential' => 0,
  3249. 'payMoney' => bcadd(floatval($details['price']),$this->expressMoney,2),
  3250. 'shopGoodsData' => $c_goods_Lists
  3251. ];
  3252. $ret = [
  3253. 'goodsData' => [$c_shop],
  3254. 'totalMoney' => floatval($details['price']),
  3255. 'payMoney' => bcadd(floatval($details['price']),$this->expressMoney,2),
  3256. 'preferential' => 0,
  3257. 'vipDiscount' => 0,
  3258. 'vipDoubleDiscount' => 0,
  3259. 'activityMoney' => 0,
  3260. 'expressMoney' => $this->expressMoney,
  3261. 'checkNum' => 0,
  3262. 'cartNum' => 0,
  3263. 'goodsNum' => 0,
  3264. 'invalidData' => [],
  3265. 'address' => $address,
  3266. 'useCoupon' => [],
  3267. 'payment' => $paymentData,
  3268. 'delivery' => $DeliveryData,
  3269. 'selfExpressRule' => $selfExpressRule,
  3270. 'coupon' => [],
  3271. 'vipCard' => [],
  3272. 'comBinId' => $data['comBinId']
  3273. ];
  3274. return ResultWrapper::success($ret);
  3275. }
  3276. }