OrderForm.php 152 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\client\models\v1\order;
  8. use app\constants\OptionSetting;
  9. use app\jobs\SetCloudGoodsStatus;
  10. use app\models\Address;
  11. use app\models\Admin;
  12. use app\models\AgentGoodsBindGoods;
  13. use app\models\Attr;
  14. use app\models\AttrGroup;
  15. use app\models\Cart;
  16. use app\models\Cat;
  17. use app\models\common\CommonGoods;
  18. use app\models\Coupon;
  19. use app\models\CouponAutoSend;
  20. use app\models\DeliveryRules;
  21. use app\models\DistrictArr;
  22. use app\models\FoodCart;
  23. use app\models\FoodFlag;
  24. use app\models\Form;
  25. use app\models\FreeDeliveryRules;
  26. use app\models\Goods;
  27. use app\models\GoodsBook;
  28. use app\models\GoodsCat;
  29. use app\models\GoodsFullMinus;
  30. use app\models\IntegralAppreciationGoods;
  31. use app\models\IntegralAppreciationPool;
  32. use app\models\IntegralAppreciationUser;
  33. use app\models\Level;
  34. use app\models\Mch;
  35. use app\models\MchGoodsCat;
  36. use app\models\MchOption;
  37. use app\models\MchPlugin;
  38. use app\models\Md;
  39. use app\models\MdGoods;
  40. use app\models\MdGroupActivities;
  41. use app\models\MdGroupActivitiesGoods;
  42. use app\models\OfferPrice;
  43. use app\models\Option;
  44. use app\models\Order;
  45. use app\models\OrderDetail;
  46. use app\models\PostageRules;
  47. use app\models\SaasUser;
  48. use app\models\SeckillActivity;
  49. use app\models\SeckillActivityGoods;
  50. use app\models\SeckillActivityOrderLog;
  51. use app\models\Shop;
  52. use app\models\Store;
  53. use app\models\TerritorialLimitation;
  54. use app\models\User;
  55. use app\models\UserCoupon;
  56. use app\models\CartOffline;
  57. use app\models\District;
  58. use app\models\WechatIntracityService;
  59. use app\models\Worker;
  60. use app\models\WorkerGoods;
  61. use app\models\WorkerGoodsExt;
  62. use app\models\WorkerOrderExt;
  63. use app\models\WorkerSetting;
  64. use app\plugins\adopt\models\AdoptGoods;
  65. use app\plugins\adopt\models\AdoptSetting;
  66. use app\utils\Delivery\Delivery;
  67. use app\utils\Delivery\Alipay\ADelivery;
  68. use app\utils\OrderNo;
  69. use app\models\VerifyCard;
  70. use app\models\VerifyCardSale;
  71. use app\models\ActivityWechatRoom;
  72. use app\models\ActivityWechatRoomGoods;
  73. use app\models\ActivityNewUser;
  74. use app\models\ActivityNewUserGoods;
  75. use app\models\ActivityCutPrice;
  76. use app\models\ActivityCutPriceGoods;
  77. use app\models\ActivityCutPriceOrder;
  78. use app\utils\Tools;
  79. use Yii;
  80. use yii\base\Model;
  81. use yii\helpers\Json;
  82. use app\modules\admin\models\maiyatian\MaiyatianForm;
  83. use app\modules\admin\models\keloop\KeloopForm;
  84. use app\models\FugouCart;
  85. class OrderForm extends Model
  86. {
  87. public $mch_list;
  88. public $address_id;
  89. public $worker_id;
  90. public $_from;
  91. public $longitude;
  92. public $latitude;
  93. public $send_price;
  94. public $balance;
  95. public $take_price;
  96. public $store_id;
  97. public $store;
  98. public $user_id;
  99. public $verify_card_id;
  100. /** @var User $user */
  101. protected $user;
  102. protected $address;
  103. protected $worker;
  104. protected $level;
  105. protected $travel;
  106. protected $integral;
  107. protected $keyword;
  108. public $order_type; //1认养商品
  109. public $goods_count_activity_new_user = [];
  110. public $goods_count_activity_cut_price = [];
  111. public $activity_cut_price_order_id = 0;
  112. public $activity_wechat_room_id = 0;
  113. public $order_no = '';
  114. public $invoiceConf = [];
  115. public $is_seckill;
  116. public $is_wastore;
  117. public $traceId;
  118. public $is_giving_gifts;
  119. public $giving_gifts_data;
  120. public $is_worker;
  121. public $send;
  122. public $pre_order_data;
  123. public function reInitMchList()
  124. {
  125. if ($this->activity_cut_price_order_id) {
  126. $activityOrder = ActivityCutPriceOrder::findOne($this->activity_cut_price_order_id);
  127. $this->mch_list = json_decode($activityOrder['order_mch_list'], true);
  128. }
  129. }
  130. public function rules()
  131. {
  132. $rules = [
  133. ['mch_list', 'required'],
  134. ['address_id', 'integer'],
  135. ['verify_card_id', 'integer'],
  136. ['order_type', 'integer'],
  137. [['order_type',], 'default', 'value' => 0],
  138. ['mch_list', function ($attr, $params) {
  139. if (!is_array($this->mch_list)) {
  140. $data = Json::decode($this->mch_list);
  141. if (!$data) {
  142. $this->addError($attr, "{$attr}数据格式错误。");
  143. }
  144. $this->mch_list = $data;
  145. }
  146. }],
  147. ['mch_list', function ($attr, $params) {
  148. $this->_filter_mch_list();
  149. foreach ($this->mch_list as $i => &$mch) {
  150. if (!is_array($mch['goods_list'])) {
  151. $this->addError($attr, "{$attr}[{$i}]['goods_list']必须是一个数组。");
  152. return;
  153. }
  154. }
  155. }],
  156. ['invoiceConf', function ($attr, $params) {
  157. $this->invoiceConf = is_string($this->invoiceConf) ? json_decode($this->invoiceConf, true) : $this->invoiceConf;
  158. }],
  159. [['longitude', 'latitude', '_from'], 'trim'],
  160. [['_from'], 'in', 'range' => ['app', 'mini', 'h5', 'official']],
  161. [['activity_cut_price_order_id', 'is_seckill', 'is_giving_gifts', 'giving_gifts_data', 'is_worker', 'worker_id', 'activity_wechat_room_id', 'order_no', 'traceId', 'is_wastore', 'pre_order_data'], 'safe'],
  162. ];
  163. return $rules;
  164. }
  165. public function _filter_mch_list()
  166. {
  167. try {
  168. if (!is_array($this->mch_list)) {
  169. $data = Json::decode($this->mch_list);
  170. if (!$data) {
  171. $this->addError('mch_list', "attr参数错误1");
  172. }
  173. $this->mch_list = $data;
  174. }
  175. if (isset($this->mch_list['_filter_func'])) {
  176. $_filter_func = $this->mch_list['_filter_func'];
  177. $this->mch_list = $this->$_filter_func($this->mch_list);
  178. }
  179. } catch (\Exception $ex) {
  180. \Yii::error($ex);
  181. $this->addError('mch_list', "attr参数错误2。" . $ex->getMessage());
  182. return;
  183. }
  184. return $this->mch_list;
  185. }
  186. public function _filter_func_ali_goodsDetailPlugin($param)
  187. {
  188. $mch_item = [];
  189. $data = $param['data'];
  190. $goods_id = Goods::goodsIdOriginal($data['outItemId']);
  191. $goods = Goods::findOne($goods_id);
  192. $attrs = json_decode($goods['attr'], true);
  193. $mch_item['product_type'] = $goods['product_type'];
  194. $mch_item['mch_id'] = $goods['mch_id'];
  195. $goods_item = [
  196. 'goods_id' => $goods['id'],
  197. 'num' => $data['count'],
  198. 'attr' => [],
  199. ];
  200. $attr = $attrs[0];
  201. $sku = Goods::skuAttrOriginal($goods, $data['outSkuId']);
  202. if ($sku) {
  203. $attr = $sku;
  204. }
  205. $attr_id_list = array_column($attr['attr_list'], 'attr_id');
  206. sort($attr_id_list);
  207. $attr_list = Attr::find()->alias('a')
  208. ->select('attr_group_id, a.id AS attr_id, a.attr_name')
  209. ->where(['a.id' => $attr_id_list])
  210. ->asArray()->all();
  211. $goods_item['attr'] = $attr_list;
  212. $mch_item['goods_list'] = [$goods_item];
  213. $mch_list = [$mch_item];
  214. return $mch_list;
  215. }
  216. public function afterValidate()
  217. {
  218. $this->user = User::findOne($this->user_id);
  219. $this->level = $this->getLevelData();
  220. $this->address = $this->getAddressData();
  221. $this->worker = $this->getWorkerData();
  222. $this->travel = $this->getWorkerTravelPrice();
  223. $this->integral = [
  224. 'forehead' => 0,
  225. 'forehead_integral' => 0,
  226. 'integration' => Option::get(OptionSetting::STORE_INTEGRATION, get_store_id(), 'gift', Option::get(OptionSetting::STORE_INTEGRATION, get_store_id(), 'store')['value'])['value']
  227. ];
  228. parent::afterValidate();
  229. }
  230. /**
  231. * @throws \Exception
  232. */
  233. protected function getMchListData($submit = false)
  234. {
  235. $submit || $this->reInitMchList();
  236. if($submit){
  237. $submitMchList = $this->mch_list;
  238. }
  239. $delivery_type = [
  240. 'express',//快递
  241. 'shop',//门店自提
  242. 'delivery',//同城配送
  243. 'online'//在线支付(虚拟产品或其他非普通)
  244. ];
  245. // 先处理订单商品 为拆单作准备
  246. foreach($this->mch_list as $i => &$mch){
  247. $mch['goods_list'] = $this->getGoodsList($mch['goods_list'], $submit, $mch['list']);
  248. if (empty($mch['goods_list'])) {
  249. throw new \Exception($mch['goods_list']['msg'] ?? '参数错误', 1);
  250. }
  251. if ($mch['goods_list']['code'] === 1) {
  252. throw new \Exception($mch['goods_list']['msg'], 1);
  253. }
  254. //获取商品配送方式 获取所有商品配送方式的交集 如果没有交集就报错
  255. $goods_delivery_type_arr = array_column($mch['goods_list'], 'delivery_type');
  256. $goods_delivery_type_init = $delivery_type;
  257. foreach ($goods_delivery_type_arr as $item) {
  258. $goods_delivery_type_init = array_values(array_intersect($goods_delivery_type_init, $item));
  259. }
  260. if (empty($goods_delivery_type_init)) {
  261. throw new \Exception('多种商品未设置相同的配送方式', 1);
  262. }
  263. $delivery_type = array_values(array_intersect($delivery_type, $goods_delivery_type_init));
  264. if (!empty($delivery_type)) {
  265. foreach ($mch['goods_list'] as &$goods_item) {
  266. $goods_item['delivery_type'] = $delivery_type;
  267. }
  268. }
  269. }
  270. if (empty($delivery_type)) {
  271. throw new \Exception('下单商品未设置相同的配送方式', 1);
  272. }
  273. $checkMchList = \app\modules\admin\models\localPublicRanking\LocalPublicRankingForm::checkMchList($this->store_id, $this->mch_list);
  274. if($checkMchList['code']){
  275. return $checkMchList;
  276. }
  277. // 根据不同的到货时间进行拆单
  278. foreach($this->mch_list as &$value){
  279. // 只有一个商品
  280. if(count($value['goods_list']) == 1){
  281. continue;
  282. }
  283. // 根据商品的到货时间 进行拆单
  284. $goodsListTemp = [];
  285. foreach($value['goods_list'] as $goodsValue){
  286. // 当商品没有设置到货规则的时候 统一默认按0处理
  287. $goodsListTemp[$goodsValue['delivery_rules'] ? $goodsValue['delivery_rules']['arrival_time'] : 0][] = $goodsValue;
  288. }
  289. $goodsListTemp = array_values($goodsListTemp);
  290. foreach($goodsListTemp as $temKey=>$temValue){
  291. if($temKey == 0) {
  292. $value['goods_list'] = $temValue;
  293. }else{
  294. $this->mch_list[] = [
  295. 'mch_id' => $value['mch_id'],
  296. 'goods_list' => $temValue
  297. ];
  298. }
  299. }
  300. }
  301. unset($value);
  302. // 再根据不同活动拆单
  303. foreach($this->mch_list as &$value){
  304. // 只有一个商品
  305. if(count($value['goods_list']) == 1){
  306. continue;
  307. }
  308. $goodsListTemp = [];
  309. foreach($value['goods_list'] as $goodsValue){
  310. $goodsListTemp[$goodsValue['md_group_activities_id'] ?? 0][] = $goodsValue;
  311. }
  312. $goodsListTemp = array_values($goodsListTemp);
  313. foreach($goodsListTemp as $temKey=>$temValue){
  314. if($temKey == 0) {
  315. $value['goods_list'] = $temValue;
  316. }else{
  317. $this->mch_list[] = [
  318. 'mch_id' => $value['mch_id'],
  319. 'goods_list' => $temValue
  320. ];
  321. }
  322. }
  323. }
  324. unset($value);
  325. //20240729加根据云仓商品(为仓库配送与非仓库配送进行拆单)与非云仓商品进行拆单
  326. foreach($this->mch_list as &$value){
  327. // 只有一个商品
  328. if(count($value['goods_list']) == 1){
  329. continue;
  330. }
  331. $goodsListTemp = [];
  332. foreach($value['goods_list'] as $goodsValue){
  333. $goods_index = 0;
  334. //如果是云仓商品
  335. if (intval($goodsValue['cloud_goods_id']) && !intval($goodsValue['is_wholesale'])) {
  336. $goods_index = 1;
  337. //是仓库配送产品
  338. if (intval($goodsValue['is_front_delivery'])) {
  339. $goods_index = 2;
  340. }
  341. //是仓库配送产品
  342. if (intval($goodsValue['is_front_centralize'])) {
  343. $goods_index = 3;
  344. }
  345. }
  346. $goodsListTemp[$goods_index][] = $goodsValue;
  347. }
  348. $goodsListTemp = array_values($goodsListTemp);
  349. foreach($goodsListTemp as $temKey=>$temValue){
  350. if($temKey == 0) {
  351. $value['goods_list'] = $temValue;
  352. }else{
  353. $this->mch_list[] = [
  354. 'mch_id' => $value['mch_id'],
  355. 'goods_list' => $temValue
  356. ];
  357. }
  358. }
  359. }
  360. unset($value);
  361. //20240729加根据是否是增值积分产品下单
  362. foreach($this->mch_list as &$value){
  363. // 只有一个商品
  364. if(count($value['goods_list']) == 1){
  365. continue;
  366. }
  367. $goodsListTemp = [];
  368. foreach($value['goods_list'] as $goodsValue){
  369. $goods_index = 0;
  370. //如果是增值积分商品
  371. $integralAppreciationGoods = IntegralAppreciationGoods::findOne(['goods_id' => $goodsValue['id'], 'is_delete' => 0]);
  372. if ($integralAppreciationGoods && $integralAppreciationGoods->integral_amount > 0) {
  373. $goods_index = 1;
  374. }
  375. $goodsListTemp[$goods_index][] = $goodsValue;
  376. }
  377. $goodsListTemp = array_values($goodsListTemp);
  378. foreach($goodsListTemp as $temKey=>$temValue){
  379. if($temKey == 0) {
  380. $value['goods_list'] = $temValue;
  381. }else{
  382. $this->mch_list[] = [
  383. 'mch_id' => $value['mch_id'],
  384. 'goods_list' => $temValue
  385. ];
  386. }
  387. }
  388. }
  389. unset($value);
  390. unset($mch);
  391. foreach ($this->mch_list as $i => &$mch) {
  392. $mch['mch_id'] = $mch['goods_list'][0]['mch_id'];
  393. // 将获取订单商品的方法提到上面单独执行
  394. // $mch['goods_list'] = $this->getGoodsList($mch['goods_list'], $submit);
  395. // if (empty($mch['goods_list'])) {
  396. // throw new \Exception($mch['goods_list']['msg'] ?? '参数错误', 1);
  397. // }
  398. // if ($mch['goods_list']['code'] === 1) {
  399. // throw new \Exception($mch['goods_list']['msg'], 1);
  400. // }
  401. $shop_count_result = $this->checkCatShopCount($mch['goods_list']);
  402. if ($shop_count_result['code'] !== 0) {
  403. return $shop_count_result;
  404. }
  405. $is_integral = false;
  406. // if ($mch['mch_id']) {
  407. if( isset($mch['goods_list'][0]['product_type']) && $mch['goods_list'][0]['product_type'] == Goods::GOODS_TYPE_INTEGRAL){
  408. $integral_name = Option::get(OptionSetting::STORE_INTEGRAL_NAME, $this->store_id, 'gift', Option::get(OptionSetting::STORE_INTEGRAL_NAME, $this->store_id, 'store', '积分')['value'])['value'];
  409. $mch['name'] = $integral_name.'商品';
  410. $is_integral = true;
  411. }else{
  412. $mch['name'] = '平台自营';
  413. }
  414. // if ($submit == false) {
  415. // $mch['form'] = $this->getFormData();
  416. // } else {
  417. // $mch['form'] = $this->getForm($mch['form']);
  418. // }
  419. $send_type_arr = [];
  420. if (!$this->is_worker) {
  421. $send_type_arr = Order::getSendTypeArr(get_store_id(), $submit, $mch['goods_list'], ['mini_id' => get_mini_id(), 'address' => $this->address, 'delivery_time' => $mch['delivery_time']]);
  422. }
  423. // } else {
  424. if ($mch['mch_id']) {
  425. $_mch = Mch::findOne([
  426. 'store_id' => $this->store_id,
  427. 'id' => $mch['mch_id'],
  428. ]);
  429. if (!$_mch) {
  430. unset($this->mch_list[$i]);
  431. continue;
  432. }
  433. // $send_type_arr = [];
  434. // if (!$this->is_worker) {
  435. //
  436. // if ($_mch['express_delivery']) {
  437. // $send_type_arr[] = 'express';
  438. // }
  439. // if ($_mch['self_delivery']) {
  440. // $send_type_arr[] = 'shop';
  441. // }
  442. // }
  443. $mch['name'] = $_mch->name;
  444. // $mch['form'] = null;
  445. // $mch['shop_list'] = [(object)[
  446. // 'address' => $_mch->address,
  447. // 'distance' => '',
  448. // 'id' => $_mch->id,
  449. // 'is_default' => 1,
  450. // 'latitude' => $_mch->latitude,
  451. // 'longitude' => $_mch->longitude,
  452. // 'mobile' => $_mch->tel,
  453. // 'name' => $_mch->name,
  454. // ]];
  455. }
  456. if (!$this->is_worker) {
  457. unset($goods_item);
  458. foreach ($mch['goods_list'] as $goods_index => $goods_item) {
  459. if ($goods_item['product_type'] == 3) {
  460. array_push($send_type_arr, 'online');
  461. // array_push($mch['goods_list'][$goods_index]['delivery_type'], 'express');
  462. // array_push($goods_item['delivery_type'], 'express');
  463. }
  464. $goods_delivery_type = $goods_item['delivery_type'];
  465. if (empty($goods_delivery_type)) {
  466. $goods_delivery_type = ['express'];
  467. }
  468. if (empty(array_intersect($send_type_arr, $goods_delivery_type))) {
  469. unset($mch['goods_list'][$goods_index]);
  470. }
  471. }
  472. $mch['goods_list'] = array_values($mch['goods_list']);
  473. if (empty($mch['goods_list'])) {
  474. return [
  475. 'code' => 1,
  476. 'msg' => '当前商品不支持当前配送方式'
  477. ];
  478. }
  479. $delivery_type_arr = array_column($mch['goods_list'], 'delivery_type');
  480. $delivery_type_ = [];
  481. foreach ($delivery_type_arr as $delivery_type_time) {
  482. $delivery_type_ = array_merge($delivery_type_, $delivery_type_time) ;
  483. }
  484. // if (in_array('online', $delivery_type_) && !in_array('shop', $delivery_type_)) {
  485. // array_push($delivery_type_, 'shop');
  486. // }
  487. // if (in_array('online', $send_type_arr) && !in_array('shop', $send_type_arr)) {
  488. // array_push($send_type_arr, 'shop');
  489. // }
  490. $delivery_type_ = array_unique($delivery_type_);
  491. $delivery_type_ = array_values($delivery_type_);//商品中的
  492. $delivery_type_ = array_values(array_intersect($send_type_arr, $delivery_type_));
  493. if (!empty($delivery_type_)) {
  494. $send_type_arr = $delivery_type_;
  495. }
  496. $send_type_arr = array_unique($send_type_arr);
  497. $mch['send_type'] = $send_type_arr;
  498. $local_type = Option::get(OptionSetting::STORE_LOCAL_TYPE, $this->store_id, 'store')['value'];
  499. $local_type = Option::get(OptionSetting::STORE_LOCAL_TYPE, $this->store_id, 'pay', $local_type);
  500. if (\Yii::$app->prod_hide_city_delivery() && $local_type['value'] == 'aggregate') { // 同城配送
  501. $mch['send_type'] = array_diff($mch['send_type'], ['delivery']);
  502. }
  503. if (in_array('shop', $send_type_arr)) {
  504. $shopArr = $this->getShopList();
  505. $mch['is_shop'] = $shopArr['shop'];
  506. $mch['shop_list'] = $shopArr['list'];
  507. } else {
  508. $mch['shop_list'] = [];
  509. $mch['is_shop'] = '';
  510. }
  511. } else {
  512. $mch['send_type'] = ['express'];
  513. }
  514. $total_price = 0;
  515. $level_price = 0;
  516. $final_price = 0;
  517. $pre_price = 0;
  518. $payment_type = 0;
  519. $next_level_price = 0;
  520. $integral = [
  521. 'forehead' => 0,
  522. 'forehead_integral' => 0
  523. ];
  524. $mch['plugin_type'] = isset($mch['plugin_type']) ? $mch['plugin_type'] : 0;
  525. $open = false;
  526. if ($this->is_seckill) {
  527. foreach ($mch['goods_list'] as &$mch_goods) {
  528. $seckill_activity_goods = SeckillActivityGoods::find()->alias('sag')->where(['sag.goods_id' => $mch_goods['goods_id']])
  529. ->leftJoin(['sg' => SeckillActivity::tableName()], 'sg.id = sag.activity_id')
  530. ->andWhere(['AND', ['>', 'sg.end_time', time()], ['<', 'sg.start_time', time()], ['sg.is_delete' => 0, 'sag.is_delete' => 0, 'sg.store_id' => get_store_id()]])
  531. ->select('sg.is_use_coupon')->asArray()->one();
  532. if ($seckill_activity_goods && (int)$seckill_activity_goods['is_use_coupon'] === 0) {
  533. $open = true;
  534. }
  535. }
  536. }
  537. //计算每个等级下单金额
  538. $level_price_arr = [];
  539. $userLevelIntegralEnlarge = 1;
  540. if($this->level != -1){
  541. $level = Level::findOne(['level'=>$this->level, 'store_id' => $this->store_id,'is_delete'=>Level::NOT_DELETE,'status' => Level::STATUS_TRUE]);
  542. if($level){
  543. $userLevelIntegralEnlarge = $level->integral_enlarge ?? 1;
  544. }
  545. }
  546. $integral_appreciation_integral = 0;
  547. $integral_appreciation_price = 0;
  548. foreach ($mch['goods_list'] as &$_goods) {
  549. //计算每个等级下单金额
  550. if (!empty($_goods['level_price_arr'])) {
  551. foreach ($_goods['level_price_arr'] as &$level_price_item) {
  552. $level_price_item *= $_goods['num'];
  553. }
  554. if (empty($level_price_arr)) {
  555. $level_price_arr = $_goods['level_price_arr'];
  556. } else {
  557. foreach ($level_price_arr as $level_index => $level_) {
  558. $level_price_arr[$level_index] += $_goods['level_price_arr'][$level_index];
  559. $level_price_arr[$level_index] = sprintf('%.2f', $level_price_arr[$level_index]);
  560. }
  561. }
  562. }
  563. if (in_array($_goods['product_type'], [1, 2])) {
  564. $mch['send_type'] = ['shop'];
  565. }
  566. if (in_array($_goods['product_type'], [1, 2]) && $submit == true) {
  567. $res = $this->bookCheckGoodsNum($_goods, $_goods['product_type']);
  568. if ($res['code'] != 0) {
  569. throw new \Exception($res['msg'], 1);
  570. }
  571. }
  572. if ($submit == false) {
  573. $_goods = array_merge($_goods, [
  574. 'form' => []
  575. ]);
  576. $_goods['form'] = $this->getNewFormData($_goods);
  577. } else {
  578. $_goods['form'] = $this->getForm($_goods['form']);
  579. }
  580. if ((int)$_goods['product_type'] === 2) {
  581. $_goods['level_price'] = sprintf('%.2f', $mch['list']['price']);
  582. $_goods['price'] = $mch['list']['price'];
  583. }
  584. if (!$this->is_worker) {
  585. $total_price += doubleval($_goods['price']);
  586. $level_price += doubleval($_goods['level_price']) > 0 ? doubleval($_goods['level_price']) : doubleval($_goods['price']);
  587. $next_level_price += doubleval($_goods['next_level_price']) > 0 ? doubleval($_goods['next_level_price']) : doubleval($_goods['price']);
  588. //计算每个产品最大可抵扣多少金额
  589. $integral_appreciation_integral = bcadd($integral_appreciation_integral, $_goods['integral_appreciation_amount'], 2);
  590. $integral_appreciation_price = bcadd($integral_appreciation_price, $_goods['integral_appreciation_price'], 2);
  591. } else {
  592. if ($_goods['payment_type']) {
  593. $payment_type = 1;
  594. $level_price += doubleval($_goods['pre_price']);
  595. $total_price += doubleval($_goods['pre_price']);
  596. $final_price += doubleval($_goods['final_price']);
  597. $pre_price += doubleval($_goods['pre_price']);
  598. } else {
  599. $level_price += doubleval($_goods['price']);
  600. $total_price += doubleval($_goods['price']);
  601. $pre_price += doubleval($_goods['price']);
  602. }
  603. }
  604. $_goods['integral'] = [
  605. 'forehead' => doubleval($_goods['resIntegral']['forehead']),
  606. 'forehead_integral' => doubleval($_goods['resIntegral']['forehead_integral'])
  607. ];
  608. $integral['forehead'] += doubleval($_goods['resIntegral']['forehead']);
  609. $integral['forehead_integral'] += doubleval($_goods['resIntegral']['forehead_integral']);
  610. unset($_goods['is_form']);
  611. unset($_goods['form_name']);
  612. // 处理下单用户会员等级中的积分放大倍数
  613. $_goods['give'] = $_goods['give'] > 0 ? floor($_goods['give'] * $userLevelIntegralEnlarge) : 0;
  614. }
  615. $integral['forehead'] = round($integral['forehead'], 2);
  616. $mch['total_price'] = !empty($this->verify_card_id) ? 0.00 : sprintf('%.2f', $total_price);
  617. $mch['level_price'] = !empty($this->verify_card_id) ? 0.00 : sprintf('%.2f', $level_price);
  618. //获取当前mch中增值积分最大可抵扣商品金额
  619. $mch['integral_appreciation_integral'] = $integral_appreciation_integral ?: 0;
  620. $mch['integral_appreciation_price'] = $integral_appreciation_price ?: 0;
  621. $mch['level_price_arr'] = $level_price_arr;
  622. $mch['payment_type'] = $payment_type;
  623. $mch['diy_send_type'] = [
  624. [
  625. 'key' => 'express',
  626. 'name' => Option::get(OptionSetting::DIY_EXPRESS_NAME, get_store_id(), 'pay', Option::get(OptionSetting::DIY_EXPRESS_NAME, get_store_id(), 'store', '快递配送')['value'] ?: '快递配送')['value'] ?: '快递配送'
  627. ],
  628. [
  629. 'key' => 'shop',
  630. 'name' => Option::get(OptionSetting::DIY_SHOP_NAME, get_store_id(), 'pay', Option::get(OptionSetting::DIY_SHOP_NAME, get_store_id(), 'store', '自提配送')['value'] ?: '自提配送')['value'] ?: '自提配送'
  631. ],
  632. [
  633. 'key' => 'delivery',
  634. 'name' => Option::get(OptionSetting::DIY_DELIVERY_NAME, get_store_id(), 'pay', Option::get(OptionSetting::DIY_DELIVERY_NAME, get_store_id(), 'store', '同城配送')['value'] ?: '同城配送')['value'] ?: '同城配送'
  635. ]
  636. ];
  637. if ($this->is_worker) {
  638. $mch['final_price'] = floatval(sprintf('%.2f', $final_price));
  639. $mch['pre_price'] = floatval(sprintf('%.2f', $pre_price));
  640. $mch['integral'] = [];
  641. $mch['coupon_list'] = [];
  642. } else {
  643. //计算下级等级金额
  644. $next_level = null;
  645. //获取下一会员等级
  646. $next_level = Level::find()->where([
  647. 'store_id' => get_store_id(),
  648. 'is_delete' => Level::NOT_DELETE
  649. ])->andWhere(['AND', ['>', 'level', get_user()->level], ['>', 'price', 0]])->select('id, level, name, discount, price')->orderBy('level ASC')->asArray()->one();
  650. if (!empty($next_level)) {
  651. $next_level['diff_price'] = 0;
  652. if ($mch['level_price'] > $next_level_price) {
  653. $next_level['diff_price'] = sprintf('%.2f',($mch['level_price'] - $next_level_price));
  654. }
  655. $mch['next_level_price'] = !empty($this->verify_card_id) ? 0.00 : sprintf('%.2f', ($next_level_price + $next_level['price']));
  656. }
  657. if ($next_level['diff_price'] <= 0) {
  658. $next_level = null;
  659. }
  660. $mch['next_level'] = $next_level;
  661. $mch['integral'] = !empty($this->verify_card_id) ? [] : $integral;
  662. if($is_integral || $open){
  663. //积分兑换商品不能使用优惠券 或 秒杀活动中不允许使用优惠券则所有商品不允许使用优惠券
  664. $mch['coupon_list'] = [];
  665. }else{
  666. $this->getCouponList($mch);
  667. }
  668. }
  669. if (!$this->is_worker) {
  670. $mch['express_price'] = $this->getExpressPrice($mch);
  671. } else {
  672. $result = $this->travel;
  673. $mch['travel_price'] = floatval(sprintf('%.2f', $result['travelPrice']));
  674. $mch['express_price'] = 0;
  675. }
  676. if (!$this->is_worker) {
  677. $mch['offer_rule'] = $this->getOfferRule($mch);
  678. // if(empty(input_params('flag_id'))){
  679. $mch['is_area'] = $this->getTerritorialLimitation($mch);
  680. // }
  681. }
  682. // 如果是点餐的商品,结构需要变一下
  683. if ((!empty(input_params('flag_id')) || !empty(input_params('table_num'))) && !$submit) {//get_md_id() &&
  684. $user_list = [];
  685. $user_ids = array_unique(array_column($mch['goods_list'], 'user_id'));
  686. foreach ($user_ids as $user_id) {
  687. $goods_list = [];
  688. foreach ($mch['goods_list'] as $item) {
  689. if ($item['user_id'] == $user_id) {
  690. $goods_list[] = $item;
  691. }
  692. }
  693. $saas_user = SaasUser::findOne(['mobile' => User::findOne($user_id)->binding]);
  694. $user_list[] = [
  695. 'name' => $saas_user->name,
  696. 'avatar' => $saas_user->avatar,
  697. 'user_id' => $user_id,
  698. 'goods_list' => $goods_list
  699. ];
  700. }
  701. $mch['goods_list'] = $user_list;
  702. }
  703. $tax_price = \app\modules\admin\models\InvoiceForm::tax_price($this->store_id, $mch['total_price']);
  704. $mch['tax_price'] = $tax_price;
  705. }
  706. // unset($mch_item);
  707. // $coupon_id_arr = [];
  708. // foreach ($this->mch_list as &$mch_item) {
  709. //
  710. // if ($mch_item['coupon_list']) {
  711. // foreach ($mch_item['coupon_list'] as $coupon_index => $coupon_item) {
  712. // foreach ($coupon_id_arr as $coupon_id_item) {
  713. // if ($coupon_item['id'] == $coupon_id_item) {
  714. // unset($mch_item['coupon_list'][$coupon_index]);
  715. // }
  716. // }
  717. // array_push($coupon_id_arr, $coupon_item['id']);
  718. // }
  719. // $mch_item['coupon_list'] = array_values($mch_item['coupon_list']);
  720. //
  721. // }
  722. // }
  723. // 随机立减
  724. $mchList = &$this->mch_list;
  725. unset($_mchItem);
  726. foreach($mchList as &$_mchItem){
  727. if(!$submit){
  728. $_mchItem['rand_discount_price'] = 0;
  729. $_mchItem['max_rand_discount_price'] = 0;
  730. $inTypes = [Goods::GOODS_TYPE_NORMAL, Goods::GOODS_TYPE_VIRTUAL];
  731. $gTypes = array_column($_mchItem['goods_list'], 'product_type');
  732. if(array_diff($gTypes, $inTypes)){
  733. continue;
  734. }
  735. $randDiscountOption = \app\utils\RandDiscount::getOption(\get_store_id(), $_mchItem['total_price']);
  736. if ($randDiscountOption['is_open'] && (float)$randDiscountOption['rand'] > 0) {
  737. $_mchItem['max_rand_discount_price'] = $randDiscountOption['rand'];
  738. }
  739. }else{
  740. if ($_mchItem['rand_discount_price'] && $_mchItem['max_rand_discount_price'] < $_mchItem['rand_discount_price']) {
  741. return [
  742. 'code' => 1,
  743. 'msg' => '非法请求!',
  744. ];
  745. }
  746. }
  747. }
  748. if($submit){
  749. $store_integral = Option::get(\app\constants\OptionSetting::STORE_INTEGRAL, $this->store_id, 'gift', Option::get(\app\constants\OptionSetting::STORE_INTEGRAL, $this->store_id, 'store')['value'])['value'];
  750. foreach($this->mch_list as $i => &$_mchItem){
  751. $_mchItem['rand_discount_price'] = $submitMchList[$i]['rand_discount_price'];
  752. $_mchItem['use_integral'] = $submitMchList[$i]['use_integral'];
  753. $_mchItem['integral'] = $submitMchList[$i]['integral'];
  754. $_mchItem['use_balance'] = $submitMchList[$i]['use_balance'];
  755. $_mchItem['integral']['forehead_integral'] = sprintf("%.2f", $_mchItem['integral']['forehead'] * $store_integral);
  756. $_mchItem['resIntegral'] = $_mchItem['integral'];
  757. foreach($_mchItem['goods_list'] as $g => &$_mchGoodsItem){
  758. $_mchGoodsItem['rand_discount_price'] = $submitMchList[$i]['goods_list'][$g]['rand_discount_price'];
  759. $_mchGoodsItem['take_price'] = $submitMchList[$i]['goods_list'][$g]['take_price'];
  760. $_mchGoodsItem['balance'] = $submitMchList[$i]['goods_list'][$g]['balance'];
  761. $_mchGoodsItem['integral'] = $submitMchList[$i]['goods_list'][$g]['integral'];
  762. $_mchGoodsItem['integral']['forehead_integral'] = sprintf("%.2f", $_mchGoodsItem['integral']['forehead'] * $store_integral);
  763. $_mchGoodsItem['resIntegral'] = $_mchGoodsItem['integral'];
  764. }
  765. }
  766. }
  767. return $this->mch_list;
  768. }
  769. //分类起购数量 修正为当前分类下所有商品数量未达到数量后警告
  770. private function checkCatShopCount($goodsList)
  771. {
  772. $new_goods_list = [];
  773. foreach ($goodsList as $item) {
  774. $cat_id_arr = GoodsCat::find()->where(['goods_id' => $item['goods_id'], 'is_delete' => 0])->select('cat_id')->column();
  775. foreach ($cat_id_arr as $goods_cat_id) {
  776. $open = true;
  777. foreach ($new_goods_list as $new_goods_item) {
  778. if ($new_goods_item['cat_id'] === $goods_cat_id) {
  779. $new_goods_list[$goods_cat_id]['goods_list'][] = [
  780. 'goods_id' => $item['goods_id'],
  781. 'num' => $item['num']
  782. ];
  783. $open = false;
  784. }
  785. }
  786. if ($open) {
  787. $new_goods_list[$goods_cat_id]['cat_id'] = $goods_cat_id;
  788. $cat = Cat::find()->where(['id' => $goods_cat_id])
  789. ->select('shop_count, name')->asArray()->one();
  790. $new_goods_list[$goods_cat_id]['shop_count'] = $cat['shop_count'] ?: 0;
  791. $new_goods_list[$goods_cat_id]['name'] = $cat['name'] ?: '';
  792. $new_goods_list[$goods_cat_id]['goods_list'][] = [
  793. 'goods_id' => $item['goods_id'],
  794. 'num' => $item['num']
  795. ];
  796. }
  797. }
  798. }
  799. foreach ($new_goods_list as $index => $goods_item) {
  800. if ($goods_item['shop_count'] > 0) {
  801. $goods_num_arr = array_column($goods_item['goods_list'], 'num');
  802. if (array_sum($goods_num_arr) < $goods_item['shop_count']) {
  803. return [
  804. 'code' => 1,
  805. 'msg' => '分类' . $goods_item['name'] . "起购数量为" . $goods_item['shop_count'] . ',当前购买数量为' . array_sum($goods_num_arr),
  806. ];
  807. }
  808. }
  809. }
  810. return [
  811. 'code' => 0,
  812. 'msg' => '检测起购数量完成',
  813. ];
  814. }
  815. //$list预约商品前端会传这个
  816. protected function getGoodsList($goods_list, $submit, $list = [])
  817. {
  818. // 获取卡券绑定的运费模板id
  819. $VerifyCardSale = VerifyCardSale::findOne(['id' => $this->verify_card_id]);
  820. $VerifyCard = null;
  821. if ($VerifyCardSale) {
  822. $VerifyCard = VerifyCard::findOne(['id' => $VerifyCardSale['verify_card_id']]);
  823. }
  824. $goodsIds = [];
  825. $cards = [];
  826. $send_price = 0;
  827. $take_price = 0;
  828. $goods_integral_amount = 0;
  829. foreach ($goods_list as $i => &$item) {
  830. $food_ext_goods = [];
  831. if (isset($item['fugou_cart_id'])) {
  832. $cart = FugouCart::findOne([
  833. 'store_id' => get_store_id(),
  834. 'id' => $item['fugou_cart_id'],
  835. ]);
  836. if (!$cart) {
  837. unset($goods_list[$i]);
  838. continue;
  839. }
  840. $item['num'] = $cart->num;
  841. $attr_id_list = (array)Json::decode($cart->attr);
  842. $goods = Goods::findOne($cart->goods_id);
  843. $goods->price = $cart->price;
  844. } elseif (isset($item['cart_id'])) {
  845. $cart = Cart::findOne([
  846. 'store_id' => get_store_id(),
  847. 'id' => $item['cart_id'],
  848. 'is_delete' => 0
  849. ]);
  850. if (!$cart) {
  851. unset($goods_list[$i]);
  852. continue;
  853. }
  854. $item['num'] = $cart->num;
  855. $attr_id_list = (array)Json::decode($cart->attr);
  856. $goods = Goods::findOne($cart->goods_id);
  857. } elseif (isset($item['food_cart_id'])) {
  858. $cart = FoodCart::findOne([
  859. 'id' => $item['food_cart_id'],
  860. 'status' => 1,
  861. 'is_delete' => 0
  862. ]);
  863. if (!$cart) {
  864. unset($goods_list[$i]);
  865. continue;
  866. }
  867. $food_ext_goods = $cart->food_ext_goods;
  868. $item['food_ext_goods'] = (array)json_decode($food_ext_goods, true);
  869. $item['num'] = $cart->num;
  870. $attr_id_list = (array)Json::decode($cart->attr);
  871. $goods = Goods::findOne($cart->goods_id);
  872. $user_id = $cart->user_id;
  873. } elseif ($item['goods_id']) {
  874. $attr_id_list = [];
  875. if ($item['attr']) {
  876. foreach ($item['attr'] as $_a) {
  877. array_push($attr_id_list, $_a['attr_id']);
  878. }
  879. }
  880. $goods = Goods::findOne([
  881. 'store_id' => get_store_id(),
  882. 'id' => $item['goods_id'],
  883. ]);
  884. if ($goods->product_type === Goods::GOODS_TYPE_WORKER) {
  885. $attr_id_list = [];
  886. // $attr = json_decode($goods->attr, true)[0];
  887. foreach ($item['attr'] as $_a) {
  888. array_push($attr_id_list, $_a['attr_id']);
  889. }
  890. $worker_goods_ext = WorkerGoodsExt::findOne(['goods_id' => $item['goods_id']]);
  891. if ($worker_goods_ext && intval($worker_goods_ext->bind_worker) === 1 && intval($this->worker['id']) === 0) {
  892. throw new \Exception('请选择技师');
  893. }
  894. }
  895. } else {
  896. unset($goods_list[$i]);
  897. continue;
  898. }
  899. if (!$goods) {
  900. unset($goods_list[$i]);
  901. continue;
  902. }
  903. if ((int)$goods->status === 0) {
  904. unset($goods_list[$i]);
  905. continue;
  906. }
  907. if (!isset($item['fugou_cart_id'])) { // 复购商品不走此逻辑,会污染价格
  908. \app\modules\admin\models\jushuitan\JuShuiTanForm::syncStoreJstGoodsQty(get_store_id(), $goods);
  909. }
  910. //增值积分产品 获取积分价格
  911. $integral_appreciation_setting = Option::get('integral_appreciation_setting', $this->store_id, 'integral_appreciation')['value'];
  912. $integral_appreciation_setting = json_decode($integral_appreciation_setting ?? '', true);
  913. $pool = IntegralAppreciationPool::findOne(['store_id' => $this->store_id]);
  914. $integral_price = $pool->integral_price ?: ($integral_appreciation_setting['integral_init_price'] ?: 0);
  915. $item['integral_appreciation_amount'] = 0;
  916. //增值积分活动商品检测
  917. $integralAppreciationGoods = IntegralAppreciationGoods::findOne(['goods_id' => $goods->id, 'is_delete' => 0]);
  918. if ($integralAppreciationGoods && $integralAppreciationGoods->integral_amount > 0) {
  919. $integral_appreciation_setting = Option::get('integral_appreciation_setting', get_store_id(), 'integral_appreciation')['value'];
  920. $integral_appreciation_setting = json_decode($integral_appreciation_setting ?? '', true);
  921. $integral_custom_name = $integral_appreciation_setting['integral_custom_name'] ?: '增值积分';
  922. $integralAppreciationUser = IntegralAppreciationUser::findOne(['user_id' => $this->user_id]);
  923. if (!$integralAppreciationUser) {
  924. return [
  925. 'code' => 1,
  926. 'msg' => "用户{$integral_custom_name}数量不足"
  927. ];
  928. }
  929. $goods_integral_amount = bcadd(bcmul($integralAppreciationGoods->integral_amount, $item['num'], 2), $goods_integral_amount, 2);
  930. if ($goods_integral_amount > $integralAppreciationUser->integral) {
  931. return [
  932. 'code' => 1,
  933. 'msg' => "用户{$integral_custom_name}数量不足"
  934. ];
  935. }
  936. $item['integral_appreciation_amount'] = bcmul($integralAppreciationGoods->integral_amount, $item['num'], 2);
  937. $item['integral_appreciation_price'] = bcmul($integral_price, $item['integral_appreciation_amount'], 2);
  938. }
  939. //购买方式检测
  940. // //判断会员是否可以购买
  941. // if (!empty($goods->buy_type_info)) {
  942. // $buy_type_info = json_decode($goods->buy_type_info, true);
  943. // if ((int)$buy_type_info['type'] === 1) { //会员购买
  944. // if ((int)$buy_type_info['member_level'] !== 0) {
  945. // $user = User::findOne($this->user_id);
  946. // if ((int)$user->level !== (int)$buy_type_info['member_level']) {
  947. // $level = Level::findOne(['level' => $buy_type_info['member_level']])->name ?? "普通会员";
  948. // return [
  949. // 'code' => 1,
  950. // 'msg' => '当前商品仅支持' . $level . '购买',
  951. // ];
  952. // }
  953. // }
  954. // }
  955. // if ((int)$buy_type_info['type'] === 2) { //新用户购买
  956. // $order = Order::findOne(['user_id' => $this->user_id]);
  957. // if (!empty($order)) {
  958. // return [
  959. // 'code' => 1,
  960. // 'msg' => "当前商品仅支持新用户购买",
  961. // ];
  962. // }
  963. // }
  964. // }
  965. // $cat_id_arr = GoodsCat::find()->where(['goods_id' => $goods->id, 'is_delete' => 0])->select('cat_id')->column();
  966. // $shop_count = Cat::find()->where(['id' => $cat_id_arr])->andWhere(['>', 'shop_count', 0])->select('shop_count')->min('shop_count') ?: 0;
  967. // if ($shop_count > 0 && $shop_count > $item['num']) {
  968. // return [
  969. // 'code' => 1,
  970. // 'msg' => $goods->name . "起购数量为" . $shop_count,
  971. // ];
  972. // }
  973. foreach ($attr_id_list as $attr_index => $attr_item) {
  974. if ($attr_item < 0) {
  975. unset($attr_id_list[$attr_index]);
  976. }
  977. }
  978. $item['delivery_rules'] = null;
  979. $item['send_verify_card_num'] = $goods->send_verify_card_num;
  980. if (!$this->is_worker) {
  981. $delivery_rules = DeliveryRules::find()->where([
  982. 'id' => $goods->delivery_rules_id,
  983. 'is_delete' => 0,
  984. 'status' => 1,
  985. 'store_id' => get_store_id()
  986. ])->select('type, times, days, name')->asArray()->one();
  987. if ($delivery_rules) {
  988. $days = "下单" . $delivery_rules['days'] . "天后";
  989. $primitive = $delivery_rules['times'];
  990. $delivery_rules['times'] =
  991. (int)$delivery_rules['type'] === 1 ? $days : date("m月d日 H:i:s", $delivery_rules['times']);
  992. $delivery_rules['type'] .= '';
  993. // 计算到货时间
  994. $delivery_rules['arrival_time'] = (int)$delivery_rules['type'] === 1 ? strtotime("+".$delivery_rules['days']." day",strtotime(date('Y-m-d',time()))) : strtotime(date('Y-m-d',$primitive));
  995. }
  996. $item['delivery_rules'] = $delivery_rules;
  997. }
  998. if (($goods->confine_count && $goods->confine_count > 0)) {
  999. $goodsNum = Goods::getBuyNum($this->user, $goods->id);
  1000. if ($goodsNum) {
  1001. } else {
  1002. $goodsNum = 0;
  1003. }
  1004. $goodsTotalNum = intval($goodsNum + $item['num']);
  1005. if ($goodsTotalNum > $goods->confine_count) {
  1006. throw new \Exception('商品:' . $goods->name . ' 只允许购买' . $goods->confine_count . $goods->unit, 1);
  1007. }
  1008. }
  1009. //起订数量
  1010. if (($goods['order_min_count'] && $goods['order_min_count'] > 0)) {
  1011. if ($item['num'] < $goods['order_min_count']) {
  1012. if($submit){
  1013. throw new \Exception('商品:' . $goods->name . ' 起订数量' . $goods['order_min_count'], 1);
  1014. }else{
  1015. $item['_errors']['order_min_count'] = $goods['order_min_count'];
  1016. }
  1017. }
  1018. }
  1019. $attr_info = $goods->getAttrInfo($attr_id_list);
  1020. // 排除当面付检测库存
  1021. if ((in_array($goods->type, [2, 6]) == false && !in_array($goods->product_type, [1, 2, 4, 6]) && $item['num'] > $attr_info['num']) || $item['num'] <= 0) { //库存不足
  1022. return [
  1023. 'code' => 1,
  1024. 'msg' => $goods->name . "库存数量不足,仅剩余" . $attr_info['num'],
  1025. ];
  1026. // unset($goods_list[$i]);
  1027. // continue;
  1028. }
  1029. if (!$this->is_worker) {
  1030. $cards = [];
  1031. if (!empty($goods->verify_card_id)) {
  1032. $ids = explode(',', $goods->verify_card_id);
  1033. $cards = Tools::getVerifyList($ids);
  1034. } else {
  1035. $cards = [];
  1036. }
  1037. }
  1038. $store = Store::findOne(get_store_id());
  1039. $attr_list = Attr::find()->alias('a')
  1040. ->select('ag.id AS attr_group_id,ag.attr_group_name,a.id AS attr_id,a.attr_name')
  1041. ->leftJoin(['ag' => AttrGroup::tableName()], 'a.attr_group_id=ag.id')
  1042. ->where(['a.id' => $attr_id_list, 'ag.store_id' => get_store_id(),])
  1043. ->asArray()->all();
  1044. $item['cost_price'] = $goods->use_attr ? $attr_info['cost_price'] : $goods->cost_price;
  1045. $item['user_id'] = !empty($user_id) ? $user_id : 0;
  1046. $item['attr_list'] = $attr_list;
  1047. $item['cloud_goods_id'] = $goods->cloud_goods_id;
  1048. $item['is_wholesale'] = $goods->is_wholesale;
  1049. $item['cloud_supplier_id'] = $goods->cloud_supplier_id;
  1050. $item['is_front_delivery'] = $goods->is_front_delivery;
  1051. $item['is_front_centralize'] = $goods->is_front_centralize;
  1052. $item['goods_no'] = $attr_info['no'];
  1053. $item['goods_id'] = $goods->id;
  1054. $item['mch_id'] = $goods->mch_id;
  1055. $item['rate'] = $goods->rate;
  1056. $item['rate_type'] = $goods->rate_type;
  1057. $item['chain_rate_type'] = $goods->chain_rate_type;
  1058. $item['chain_rate'] = $goods->chain_rate;
  1059. $item['goods_name'] = $goods->name;
  1060. $item['goods_pic'] = $attr_info['pic'] ? $attr_info['pic'] : $goods->cover_pic;
  1061. $item['balance'] = 0;
  1062. $item['max_balance'] = ($store->balance == 1) ? round($goods->balance, 2) : 0;
  1063. //如果没有使用规格,则使用商品售价 否则使用规格售价
  1064. $item['price'] = sprintf('%.2f', (($goods->use_attr ? $attr_info['price'] : $goods->price) * $item['num']));
  1065. $item['single_price'] = !empty($this->verify_card_id) ? 0 : sprintf('%.2f', $attr_info['price']);
  1066. $item['weight'] = $goods->weight;
  1067. if (!empty($this->verify_card_id)) {
  1068. $item['integral'] = 0;
  1069. } else {
  1070. $item['integral'] = $goods->integral ? $goods->integral : 0;
  1071. }
  1072. $item['goods_integral'] = json_decode($goods->integral, true);
  1073. $item['integral_price'] = $goods->integral_price;
  1074. $item['freight'] = !empty($VerifyCard['freight_id']) ? $VerifyCard['freight_id'] : $goods->freight;
  1075. $item['full_cut'] = $goods->full_cut;
  1076. $item['goods_cat_id'] = $goods->cat_id;
  1077. $item['id'] = $goods->id;
  1078. $item['verify_card_id'] = $cards;
  1079. $item['type'] = $goods->type;
  1080. $item['delivery_type'] = Json::decode($goods->delivery_type);
  1081. if (get_md_id() && empty(input_params('flag_id'))) {
  1082. $md = Md::findOne(get_md_id());
  1083. if ($md->is_single) {
  1084. $md_goods = MdGoods::findOne(['goods_id' => $goods->id, 'md_id' => get_md_id()]);
  1085. if ($md_goods) {
  1086. $md_delivery_type = Json::decode(Md::findOne(get_md_id())->delivery_type);
  1087. $md_goods_delivery_type = Json::decode($md_goods->delivery_type);
  1088. $delivery_type = [];
  1089. foreach ($md_goods_delivery_type as $delivery_type_item) {
  1090. if (in_array($delivery_type_item, $md_delivery_type)) {
  1091. $delivery_type[] = $delivery_type_item;
  1092. }
  1093. }
  1094. $item['delivery_type'] = $delivery_type;
  1095. }
  1096. }
  1097. }
  1098. // 当前选择的规格
  1099. $attrIdArr = [];
  1100. foreach ($item['attr_list'] as $attrListItem) {
  1101. $attrIdArr[] = $attrListItem['attr_id'];
  1102. }
  1103. $GoodsFullMinus = [];
  1104. if (!$this->is_worker) {
  1105. $GoodsFullMinus = GoodsFullMinus::find()
  1106. ->select('*')
  1107. ->where(['store_id' => get_store_id(), 'goods_id' => $goods->id, 'is_delete' => 0])
  1108. ->orderBy('full_minus_num ASC')->asArray()->all();
  1109. }
  1110. // 门店逻辑
  1111. $attr = $goods->attr;
  1112. $price = $goods->price;
  1113. // 独立运营门店不参与活动 团购活动需要写在判断门店之前
  1114. $activityModel = MdGroupActivitiesGoods::find()->alias('mgag')->leftJoin(['mga'=>MdGroupActivities::tableName()],'mga.id=mgag.activities_id')->where(['goods_id'=>$goods->id,'mgag.is_delete'=>0])->andWhere(['>=','mga.end_time',time()])->andWhere(['mga.is_delete'=>0])->asArray()->select('mgag.*,mga.start_time,mga.end_time')->one();
  1115. if($activityModel){
  1116. $attr = $activityModel['attr'];
  1117. $price = $activityModel['price'];
  1118. }
  1119. $item['md_group_activities_id'] = $activityModel ? $activityModel['activities_id'] : 0;
  1120. if (get_md_id() && empty(input_params('flag_id'))) {
  1121. $md = Md::findOne(get_md_id());
  1122. if ($md->is_single) {
  1123. $md_goods = MdGoods::findOne(['goods_id' => $goods->id, 'md_id' => get_md_id()]);
  1124. if ($md_goods) {
  1125. $attr = $md_goods->attr;
  1126. $price = $md_goods->price;
  1127. }
  1128. }
  1129. }
  1130. if ($goods->product_type == Goods::GOODS_TYPE_DATE) {
  1131. $price = 0;
  1132. $service_book_desc = json_decode($goods->service_book_desc ?: '', true);
  1133. if (!empty($service_book_desc)) {
  1134. if (empty($list)) {
  1135. return [
  1136. 'code' => 1,
  1137. 'msg' => '预约日期数据为空'
  1138. ];
  1139. }
  1140. array_pop($list);
  1141. foreach ($list as $value) {
  1142. $book_date = strtotime($value['date']);
  1143. foreach ($service_book_desc as $service_book_item) {
  1144. $service_book_date = strtotime($service_book_item['date']);
  1145. if ($book_date === $service_book_date) {
  1146. $price += $service_book_item['price'];
  1147. }
  1148. }
  1149. }
  1150. // $price = $price * $item['num'];
  1151. //判断是否有库存
  1152. $num = Goods::getGoodsNum($goods)['data'];
  1153. foreach ($list as $iattr) {
  1154. $idate = strtotime($iattr['date']);
  1155. foreach ($num as $inum) {
  1156. $indate = strtotime($inum['date']);
  1157. if(($idate == $indate) && ($inum['num'] < $item['num'])){
  1158. return ['code' => 1, 'msg' => $iattr['date'].'库存不足'];
  1159. }
  1160. }
  1161. }
  1162. }
  1163. }
  1164. $res = \app\modules\client\models\v1\common\CommonGoods::currentGoodsAttr([
  1165. 'attr' => $attr,
  1166. 'price' => $price,
  1167. 'is_level' => $goods->is_level,
  1168. 'mch_id' => $goods->mch_id,
  1169. 'full_minus' => $GoodsFullMinus,
  1170. 'unit' => $goods->unit,
  1171. 'use_attr' => $goods->use_attr,
  1172. 'food_ext_goods' => $food_ext_goods,
  1173. ], $attrIdArr, [], $item['num']);
  1174. $item['batch_price_tips'] = $res['batch_price_tips'];
  1175. $item['current_batch_price_tips'] = $res['current_batch_price_tips'];
  1176. $item['price'] = sprintf('%.2f', ($res['price'] * $item['num']));
  1177. $item['level_price'] = sprintf('%.2f', ($res['level_price'] * $item['num']));
  1178. $item['next_level_price'] = sprintf('%.2f', ($res['next_level_price'] * $item['num']));
  1179. $item['is_level'] = $res['is_level'];
  1180. if ($res['level_price_arr']) {
  1181. $item['level_price_arr'] = $res['level_price_arr'];
  1182. }
  1183. $send_integral_profit = Option::get(OptionSetting::SEND_INTEGRAL_PROFIT, get_store_id(), 'gift', Option::get(OptionSetting::SEND_INTEGRAL_PROFIT, get_store_id(), 'store')['value'])['value'];
  1184. $integralArr = $this->getIntegral((object)$item, Option::get(OptionSetting::STORE_INTEGRAL,get_store_id(), 'gift', Option::get(OptionSetting::STORE_INTEGRAL,get_store_id(), 'store')['value'])['value'], $goodsIds, $send_integral_profit);
  1185. $item['give'] = $integralArr['give'];
  1186. $item['resIntegral'] = $integralArr['resIntegral'];
  1187. $item['maxIntegral'] = $integralArr['maxIntegral'];
  1188. $goodsIds[] = $goods->id;
  1189. $item['goods_card_list'] = $this->is_worker ? [] : Goods::getGoodsCard($goods->id);
  1190. $item['is_form'] = $goods->is_form;
  1191. $item['form_name'] = $goods->form_name;
  1192. $item['product_type'] = $goods->product_type;
  1193. $item['pre_price'] = 0; //定金金额
  1194. $item['final_price'] = 0; //尾款金额
  1195. $item['payment_type'] = 0; //支付模式
  1196. if (!$this->is_worker) {
  1197. $res_acnu = $this->getActivityNewUserGoodsPrice($res, $goods, $attr_id_list, $submit, $item['num']);
  1198. if ($res_acnu['code'] === 0) {
  1199. if ($res_acnu['price'] > 0) {
  1200. $item['is_level'] = 0;
  1201. $item['price'] = $item['level_price'] = sprintf('%.2f', ($res_acnu['price']));
  1202. $item['price_str'] = $res_acnu['price_str'];
  1203. }
  1204. } else {
  1205. return $res_acnu;
  1206. }
  1207. if($this->activity_wechat_room_id){
  1208. $res_acwr = $this->getActivityWorkRoomGoodsPrice($res, $goods, $attr_id_list, $submit, $item['num']);
  1209. if ($res_acwr['code'] === 0) {
  1210. $item['is_level'] = 0;
  1211. if ($res_acwr['price'] > 0) {
  1212. $item['price'] = $item['level_price'] = sprintf('%.2f', ($res_acwr['price']));
  1213. $item['price_str'] = $res_acwr['price_str'];
  1214. }
  1215. } else {
  1216. return $res_acwr;
  1217. }
  1218. }
  1219. $item['send_price'] = bcmul($goods->goods_send_profit * 0.01, $item['level_price'], 2);
  1220. $item['take_price'] = bcmul($goods->goods_take_price * 0.01, $item['level_price'], 2);
  1221. $item['max_take_price'] = bcmul($goods->goods_take_price * 0.01, $item['level_price'], 2);
  1222. $user = User::findOne(get_user_id());
  1223. $user_league_price = 0;
  1224. $saas_user = SaasUser::findOne(['mobile' => $user->binding]);
  1225. if ($saas_user) {
  1226. $user_league_price = $saas_user->league_price;
  1227. }
  1228. if(bcadd($take_price, $item['take_price'], 2) > $user_league_price){
  1229. $item['take_price'] = $user_league_price;
  1230. }
  1231. if (bcadd($send_price, $item['send_price'], 2) > $store->league_price) {
  1232. $item['send_price'] = 0;
  1233. }
  1234. $send_price += $item['send_price'];
  1235. $take_price += $item['take_price'];
  1236. } else {
  1237. //全款 / 订金
  1238. if ($goods->product_type === Goods::GOODS_TYPE_WORKER) {
  1239. $goods_ext = WorkerGoodsExt::findOne(['goods_id' => $goods->id]);
  1240. if ($goods_ext->payment_type === 1) {
  1241. $item['payment_type'] = 1;
  1242. $final_profit = $goods_ext->final_profit;
  1243. $item['final_price'] = floatval(sprintf('%.2f', $item['price'] * ($final_profit / 100)));
  1244. $item['pre_price'] = floatval(sprintf('%.2f', ($item['price'] - $item['final_price'])));
  1245. }
  1246. }
  1247. }
  1248. if($this->activity_cut_price_order_id){
  1249. $res_accp = $this->getActivityCutPriceGoodsPrice($res, $goods, $attr_id_list, $submit, $item['num']);
  1250. // var_dump($res_accp);die;
  1251. if ($res_accp['code'] === 0) {
  1252. $item['is_level'] = 0;
  1253. if ($res_accp['price'] > 0) {
  1254. $item['price'] = $item['level_price'] = sprintf('%.2f', ($res_accp['price']));
  1255. $item['price_str'] = $res_accp['price_str'];
  1256. }
  1257. } else {
  1258. return $res_accp;
  1259. }
  1260. }
  1261. if ($this->is_seckill) {
  1262. $res = $this->getSceKillGoodsPrice($goods, $attr_id_list, $submit, $item['num']);
  1263. if ($res['code'] === 0) {
  1264. $item['is_level'] = 0;
  1265. if ($res['data'] > 0) {
  1266. $item['price'] = $item['level_price'] = sprintf('%.2f', ($res['data'] * $item['num']));
  1267. }
  1268. } else {
  1269. return $res;
  1270. }
  1271. }
  1272. if ($goods->product_type == Goods::GOODS_TYPE_ADOPT) {
  1273. $adopt_goods = AdoptGoods::find()->where(['goods_id' => $goods->id,'is_delete' => 0])->one();
  1274. $item['desc'] = $adopt_goods->desc;
  1275. }
  1276. }
  1277. // $user = User::findOne(get_user_id());
  1278. // $totalGoodsBalance = array_sum(array_column($goods_list, 'balance'));
  1279. // $userMoney = $user->money;
  1280. // if ($userMoney < $totalGoodsBalance) {
  1281. // $remainingBalance = $totalGoodsBalance - $userMoney;
  1282. // $numGoods = count($goods_list);
  1283. // $adjustmentPerGood = round($remainingBalance / $numGoods, 2);
  1284. // for ($i = 0; $i < $numGoods; $i++) {
  1285. // $goods_list[$i]['balance'] = floatval(number_format(
  1286. // $goods_list[$i]['balance'] - $adjustmentPerGood,
  1287. // 2,
  1288. // '.',
  1289. // ','
  1290. // ));
  1291. // }
  1292. // }
  1293. // 和空数组合并重建索引,避免出现因索引key间断导致客户端显示问题
  1294. return array_merge($goods_list, []);
  1295. }
  1296. //砍价商品处理
  1297. public function getActivityCutPriceGoodsPrice($res, $goods, $attr, $submit, $num)
  1298. {
  1299. try {
  1300. $price_str = [];
  1301. $activityOrder = ActivityCutPriceOrder::findOne($this->activity_cut_price_order_id);
  1302. if(!$activityOrder){
  1303. throw new \Exception('砍价活动订单信息不存在');
  1304. }
  1305. $goods_ext = ActivityCutPriceGoods::findOne(['activity_id' => $activityOrder->activity_id, 'goods_id' => $goods->id, 'is_delete' => 0]);
  1306. if(!$goods_ext){
  1307. throw new \Exception('砍价商品信息不存在');
  1308. }
  1309. $ext_attrs = json_decode($goods_ext['attr'], true);
  1310. foreach ($ext_attrs as $ext_attr) {
  1311. $ext_attr_id = array_column($ext_attr['attr_list'], 'attr_id');
  1312. if (empty(array_diff($ext_attr_id, $attr))) {
  1313. if($ext_attr['num'] < $num){
  1314. throw new \Exception('砍价商品库存不足');
  1315. }
  1316. }
  1317. }
  1318. //全部享受优惠
  1319. $price = $activityOrder->pay_price;
  1320. $price_str[] = '砍价优惠价¥' . sprintf('%.2f', $price);
  1321. return [
  1322. 'code' => 0,
  1323. 'msg' => '获取成功',
  1324. 'price' => $price,
  1325. 'price_str' => implode('+', $price_str),
  1326. 'id' => $activityOrder->id,
  1327. ];
  1328. } catch (\Exception $e) {
  1329. return [
  1330. 'code' => 1,
  1331. 'msg' => $e->getMessage()
  1332. ];
  1333. }
  1334. }
  1335. //新人专享商品处理
  1336. public function getActivityNewUserGoodsPrice($res, $goods, $attr, $submit, $num)
  1337. {
  1338. try {
  1339. $price = 0;
  1340. $price_str = [];
  1341. $activity = ActivityNewUser::activityAt($goods->store_id);
  1342. $open = false;
  1343. if($activity){
  1344. $goods_ext = ActivityNewUserGoods::findOne(['activity_id' => $activity->id, 'goods_id' => $goods->id, 'is_delete' => 0]);
  1345. if($goods_ext){
  1346. $ext_attrs = json_decode($goods_ext['attr'], true);
  1347. foreach ($ext_attrs as $ext_attr) {
  1348. $ext_attr_id = array_column($ext_attr['attr_list'], 'attr_id');
  1349. //与购物车添加的规格id数组比较
  1350. if (empty(array_diff($ext_attr_id, $attr))) {
  1351. $ext_price = $ext_attr['price'];
  1352. $id = $goods_ext['id'];
  1353. $open = true;
  1354. }
  1355. }
  1356. if ($open) {
  1357. $buy_limit = $activity->buy_limit;
  1358. if (($buy_limit && $buy_limit > 0)) {
  1359. // $goodsNum = 0;
  1360. //部分享受优惠
  1361. $goodsNum = intval(Goods::getBuyNum(get_user(), $goods->id));
  1362. $diff_num = $buy_limit - $goodsNum;
  1363. if ($diff_num > 0) {
  1364. $buy_num = $num - $diff_num;
  1365. if ($buy_num > 0) {
  1366. $price += ($diff_num * $ext_price) + ($buy_num * $res['level_price']);
  1367. $price_str[] = '新人专享¥' . sprintf('%.2f', $ext_price) . '×' . $diff_num;
  1368. } else {
  1369. $price += $num * $ext_price;
  1370. $price_str[] = '新人专享¥' . sprintf('%.2f', $ext_price) . '×' . $num;
  1371. }
  1372. }
  1373. // for($i=$goodsNum+$this->goods_count_activity_new_user[$goods->id]; $i<$num; $i++){
  1374. // if($i < $buy_limit){
  1375. // $price += $ext_price;
  1376. // $price_str[] = '新人专享¥' . sprintf('%.2f', $ext_price);
  1377. // $this->goods_count_activity_new_user[$goods->id]++;
  1378. // }else{
  1379. // $price += sprintf('%.2f', $res['level_price']);
  1380. // $price_str[] = sprintf('%.2f', $res['level_price']);
  1381. // }
  1382. // }
  1383. }else{
  1384. //全部享受优惠
  1385. $price = $ext_price * $num;
  1386. $price_str[] = '新人专享¥' . sprintf('%.2f', $ext_price) . '×' . $num;
  1387. }
  1388. }
  1389. }
  1390. }
  1391. return [
  1392. 'code' => 0,
  1393. 'msg' => '获取成功',
  1394. 'price' => $price,
  1395. 'price_str' => implode('+', $price_str),
  1396. 'id' => $id
  1397. ];
  1398. } catch (\Exception $e) {
  1399. return [
  1400. 'code' => 1,
  1401. 'msg' => $e->getMessage()
  1402. ];
  1403. }
  1404. }
  1405. //群活动专享商品处理
  1406. public function getActivityWorkRoomGoodsPrice($res, $goods, $attr, $submit, $num)
  1407. {
  1408. try {
  1409. $price = 0;
  1410. $price_str = [];
  1411. $activity = ActivityWechatRoom::activityAt($this->activity_wechat_room_id);
  1412. if($activity){
  1413. $wechatRoomIds = explode(',', $activity['wechat_room_id']);
  1414. foreach($wechatRoomIds as $roomId){
  1415. $inRoom = \app\modules\admin\models\mochat\MochatForm::userInRoom($this->store_id, $roomId, $this->user_id);
  1416. if($inRoom){
  1417. break;
  1418. }
  1419. }
  1420. if(!$inRoom){
  1421. throw new \Exception('操作失败,用户不在群里面');
  1422. }
  1423. $goods_ext = ActivityWechatRoomGoods::findOne(['activity_id' => $activity->id, 'goods_id' => $goods->id, 'is_delete' => 0]);
  1424. if($goods_ext){
  1425. $ext_attrs = json_decode($goods_ext['attr'], true);
  1426. foreach ($ext_attrs as $ext_attr) {
  1427. $ext_attr_id = array_column($ext_attr['attr_list'], 'attr_id');
  1428. //与购物车添加的规格id数组比较
  1429. if (empty(array_diff($ext_attr_id, $attr))) {
  1430. $ext_price = $ext_attr['price'];
  1431. $id = $goods_ext['id'];
  1432. }
  1433. }
  1434. //全部享受优惠
  1435. $price = $ext_price * $num;
  1436. $price_str[] = '群友专享¥' . sprintf('%.2f', $ext_price) . '×' . $num;
  1437. }
  1438. }else{
  1439. throw new \Exception('操作失败,群活动信息错误');
  1440. }
  1441. return [
  1442. 'code' => 0,
  1443. 'msg' => '获取成功',
  1444. 'price' => $price,
  1445. 'price_str' => implode('+', $price_str),
  1446. 'id' => $id
  1447. ];
  1448. } catch (\Exception $e) {
  1449. return [
  1450. 'code' => 1,
  1451. 'msg' => $e->getMessage()
  1452. ];
  1453. }
  1454. }
  1455. //秒杀商品处理
  1456. public function getSceKillGoodsPrice($goods, $attr, $submit, $num)
  1457. {
  1458. $t = \Yii::$app->db->beginTransaction();
  1459. try {
  1460. //秒杀订单
  1461. $sql = SeckillActivityGoods::find()->alias('sag')->where(['sag.goods_id' => $goods->id])
  1462. ->leftJoin(['sg' => SeckillActivity::tableName()], 'sg.id = sag.activity_id')
  1463. ->andWhere(['AND', ['>', 'sg.end_time', time()], ['<', 'sg.start_time', time()], ['sg.is_delete' => 0, 'sag.is_delete' => 0, 'sg.store_id' => get_store_id()]])
  1464. ->select('sag.id sag_id, sg.id, sg.end_time, sag.attr, sag.use_attr, sag.seckill_num, sag.seckill_price, sag.sale_num, sg.order_limit_num, sg.self_limit_num')->createCommand()->getRawSql();
  1465. $sql = $sql . ' FOR UPDATE';
  1466. $seckill_activity_goods = Yii::$app->db->createCommand($sql)->queryOne();
  1467. $price = 0;
  1468. $id = 0;
  1469. if (!empty($seckill_activity_goods)) {
  1470. // 这里未统计已经取消的订单
  1471. $sum = SeckillActivityOrderLog::find()->alias('saol')
  1472. ->leftJoin(['o' => Order::tableName()],'saol.order_id = o.id')
  1473. ->where(['saol.activity_goods_id' => $seckill_activity_goods['sag_id'], 'saol.store_id' => get_store_id(), 'saol.user_id' => get_user_id(), 'saol.is_delete' => 0,'o.is_delete' => 0])
  1474. ->andWhere(['!=', 'o.trade_status' ,1 ])
  1475. ->count('saol.num');
  1476. if ($seckill_activity_goods['self_limit_num'] > 0 && ($sum * 1 + $num) > $seckill_activity_goods['self_limit_num']) {
  1477. throw new \Exception("购买数量超出限购数量");
  1478. }
  1479. if ($seckill_activity_goods['order_limit_num'] > 0 && $num > $seckill_activity_goods['order_limit_num']) {
  1480. throw new \Exception("购买数量超出订单限购数量");
  1481. }
  1482. //如果商品使用规格 且 已经查找到活动
  1483. // if ((int)$goods->use_attr === 1 && !empty($seckill_activity_goods['attr'])) {
  1484. //解码
  1485. $seckill_activity_goods['attr'] = $sag_attrs = json_decode($seckill_activity_goods['attr'], true);
  1486. //获取设置的商品秒杀规格id数组与购物车添加的规格id数组比较
  1487. // $sag_attrs = array_column($sag_attrs, 'attr_list');
  1488. //假设没有对应的规格信息
  1489. $open = false;
  1490. foreach ($sag_attrs as $sag_attr) {
  1491. $sag_attr_id = array_column($sag_attr['attr_list'], 'attr_id');
  1492. // $sag_attr['seckill_num'] -= $num;
  1493. //与购物车添加的规格id数组比较
  1494. if (empty(array_diff($sag_attr_id, $attr))) {
  1495. if ((int)$sag_attr['seckill_num'] >= $num) {
  1496. $price = $sag_attr['seckill_price'];
  1497. $id = $seckill_activity_goods['sag_id'];
  1498. } else {
  1499. throw new \Exception("当前秒杀商品库存不足");
  1500. }
  1501. }
  1502. }
  1503. // } else {
  1504. // if ($seckill_activity_goods['seckill_num'] >= ($seckill_activity_goods['sale_num'] + $num)) {
  1505. // $price = $seckill_activity_goods['seckill_price'];
  1506. // $id = $seckill_activity_goods['sag_id'];
  1507. // } else {
  1508. // throw new \Exception("当前秒杀商品库存不足");
  1509. // }
  1510. // }
  1511. if ($submit && $id > 0) {
  1512. $activity_goods = SeckillActivityGoods::findOne($id);
  1513. $activity_goods_attr = json_decode($activity_goods->attr, true);
  1514. foreach ($activity_goods_attr as &$sag_attr) {
  1515. $sag_attr_id = array_column($sag_attr['attr_list'], 'attr_id');
  1516. // $sag_attr['seckill_num'] -= $num;
  1517. //与购物车添加的规格id数组比较
  1518. if (empty(array_diff($sag_attr_id, $attr))) {
  1519. $sag_attr['seckill_num'] = $sag_attr['seckill_num'] - $num;
  1520. }
  1521. }
  1522. $activity_goods->attr = json_encode($activity_goods_attr);
  1523. $activity_goods->sale_num = ($activity_goods->sale_num * 1 + $num);
  1524. $activity_goods->seckill_num = ($activity_goods->seckill_num - $num);
  1525. if (!$activity_goods->save()) {
  1526. throw new \Exception(json_encode($activity_goods->errors));
  1527. }
  1528. }
  1529. }
  1530. $t->commit();
  1531. return [
  1532. 'code' => 0,
  1533. 'msg' => '获取成功',
  1534. 'data' => $price,
  1535. 'id' => $id
  1536. ];
  1537. } catch (\Exception $e) {
  1538. $t->rollBack();
  1539. return [
  1540. 'code' => 1,
  1541. 'msg' => $e->getMessage()
  1542. ];
  1543. }
  1544. }
  1545. //自定义表单
  1546. protected function getFormData()
  1547. {
  1548. $new_list = [];
  1549. $new_list['is_form'] = Option::get('is_form', $this->store_id, 'store', 0)['value'];
  1550. $form_list = [];
  1551. if ($new_list['is_form'] == 1) {
  1552. $new_list['name'] = Option::get('form_name', $this->store_id, 'store', '表单信息')['value'];
  1553. $form_list = Form::find()->where([
  1554. 'store_id' => $this->store_id, 'is_delete' => 0,
  1555. ])->orderBy(['sort' => SORT_ASC])->asArray()->all();
  1556. foreach ($form_list as $index => $value) {
  1557. if (in_array($value['type'], ['radio', 'checkbox'])) {
  1558. $default = str_replace(",", ",", $value['default']);
  1559. $list = explode(',', $default);
  1560. $default_list = [];
  1561. foreach ($list as $k => $v) {
  1562. $default_list[$k]['name'] = $v;
  1563. if ($k == 0) {
  1564. if ($value['type'] == 'radio') {
  1565. $form_list[$index]['default'] = $v;
  1566. } else {
  1567. $form_list[$index]['default'] = [$v];
  1568. }
  1569. $default_list[$k]['checked'] = true;
  1570. } else {
  1571. $default_list[$k]['checked'] = false;
  1572. }
  1573. }
  1574. $form_list[$index]['default_list'] = $default_list;
  1575. }
  1576. }
  1577. }
  1578. $new_list['list'] = $form_list;
  1579. return $new_list;
  1580. }
  1581. //自定义表单
  1582. public function getNewFormData($goods)
  1583. {
  1584. $new_list = [];
  1585. $new_list['is_form'] = $goods['is_form'];
  1586. $form_list = [];
  1587. if ($new_list['is_form'] == 1) {
  1588. $new_list['name'] = $goods['form_name'];
  1589. $form_list = Form::find()->where([
  1590. 'store_id' => $this->store_id, 'is_delete' => 0, 'goods_id' => $goods['id']
  1591. ])->orderBy(['sort' => SORT_ASC])->asArray()->all();
  1592. foreach ($form_list as $index => $value) {
  1593. if (in_array($value['type'], ['radio', 'checkbox'])) {
  1594. $default = str_replace(",", ",", $value['default']);
  1595. $list = explode(',', $default);
  1596. $default_list = [];
  1597. foreach ($list as $k => $v) {
  1598. $default_list[$k]['name'] = $v;
  1599. if ($k == 0) {
  1600. if ($value['type'] == 'radio') {
  1601. $form_list[$index]['default'] = $v;
  1602. } else {
  1603. $form_list[$index]['default'] = [$v];
  1604. }
  1605. $default_list[$k]['checked'] = true;
  1606. } else {
  1607. $default_list[$k]['checked'] = false;
  1608. }
  1609. }
  1610. $form_list[$index]['default_list'] = $default_list;
  1611. }
  1612. }
  1613. }
  1614. $new_list['list'] = $form_list;
  1615. return $new_list;
  1616. }
  1617. protected function getAddress()
  1618. {
  1619. if (!$this->address) {
  1620. if ($this->address_id) {
  1621. $this->address = Address::findOne(['id' => $this->address_id, 'user_id' => get_saas_user_id(), 'is_delete' => 0]);
  1622. } else {
  1623. $this->address = Address::find()->where([
  1624. 'user_id' => get_saas_user_id(),
  1625. 'is_default' => 1,
  1626. 'is_delete' => 0,
  1627. ])->limit(1)->one();
  1628. }
  1629. }
  1630. return (object)$this->address;
  1631. }
  1632. //获取收货地址,有address_id优先获取,没有则获取默认地址
  1633. protected function getAddressData()
  1634. {
  1635. $address = $this->getAddress();
  1636. if (isset($address->id)) {
  1637. return [
  1638. 'id' => $address->id,
  1639. 'name' => $address->name,
  1640. 'mobile' => $address->mobile,
  1641. 'province_id' => $address->province_id,
  1642. 'province' => $address->province,
  1643. 'city_id' => $address->city_id,
  1644. 'city' => $address->city,
  1645. 'district_id' => $address->district_id,
  1646. 'district' => $address->district,
  1647. 'town_id' => $address->town_id,
  1648. 'town' => $address->town,
  1649. 'village_id' => $address->village_id,
  1650. 'village' => $address->village,
  1651. 'detail' => $address->detail,
  1652. 'is_default' => $address->is_default,
  1653. 'latitude' => $address->latitude,
  1654. 'longitude' => $address->longitude,
  1655. ];
  1656. } else {
  1657. return [
  1658. 'id' => '',
  1659. 'name' => '',
  1660. 'mobile' => '',
  1661. 'province_id' => '',
  1662. 'province' => '',
  1663. 'city_id' => '',
  1664. 'city' => '',
  1665. 'district_id' => '',
  1666. 'district' => '',
  1667. 'detail' => '',
  1668. 'is_default' => 1,
  1669. 'latitude' => '',
  1670. 'longitude' => '',
  1671. ];
  1672. }
  1673. }
  1674. //如果为服务订单则获取服务人员
  1675. protected function getWorkerData()
  1676. {
  1677. $worker = (object)$this->worker;
  1678. if (!$this->is_worker) {
  1679. return null;
  1680. }
  1681. if (!$worker->id) {
  1682. if ($this->worker_id) {
  1683. $worker = Worker::findOne(['id' => $this->worker_id, 'store_id' => get_store_id(), 'status' => 1, 'open_status' => 1]);
  1684. } else {
  1685. // $worker_list = Worker::find()->where([
  1686. // 'store_id' => get_store_id(),
  1687. // 'status' => 1,
  1688. // 'open_status' => 1,
  1689. // ])->select('id')->column();
  1690. // if ($worker_list) {
  1691. // $rand_index = array_rand($worker_list);
  1692. // $worker_id = $worker_list[$rand_index];
  1693. // $worker = Worker::findOne($worker_id);
  1694. // }
  1695. $worker = (object)[
  1696. 'id' => 0,
  1697. 'name' => '',
  1698. 'logo' => '',
  1699. 'lat' => 0,
  1700. 'lng' => 0,
  1701. ];
  1702. }
  1703. }
  1704. $arr = [
  1705. 'id' => $worker->id,
  1706. 'name' => $worker->name,
  1707. 'logo' => $worker->logo,
  1708. 'lat' => $worker->lat,
  1709. 'lng' => $worker->lng,
  1710. 'time' => null,
  1711. 'default_date' => ''
  1712. ];
  1713. //配置服务人员默认可预定时间
  1714. // $worker
  1715. $result = $this->workerTime($worker->id);
  1716. if ($result['code'] === 0) {
  1717. $arr['time'] = $result['data'];
  1718. if ($arr['time']) {
  1719. $times = $result['data'][0]['time'][0]['times'];
  1720. foreach ($times as $item) {
  1721. if ($item['status'] === 0) {
  1722. $arr['default_date'] = date('Y-m-d H:i', $item['time_int']);
  1723. break;
  1724. }
  1725. }
  1726. }
  1727. }
  1728. return $arr;
  1729. }
  1730. public function getWorkerTime() {}
  1731. //获取支付方式 $order_type 0为系统其他订单 5为认养订单 该字段主要为了区分认养订单
  1732. public function getPayTypeList($order_type = 0, $ignore = [])
  1733. {
  1734. if ($order_type == 5) {
  1735. $adopt_setting = AdoptSetting::findOne(['store_id' => get_store_id()]);
  1736. $adopt_payment = $adopt_setting->adopt_payment;
  1737. $adopt_pay_list = [];
  1738. if (!empty($adopt_payment)) {
  1739. $adopt_pay_type = Json::decode($adopt_payment);
  1740. foreach ($adopt_pay_type as &$value) {
  1741. if ($value['key'] == 'alipay') {
  1742. $value['payment'] = 4;
  1743. }
  1744. if ($value['key'] == 'wechat') {
  1745. $value['payment'] = 1;
  1746. }
  1747. }
  1748. $adopt_pay_list = $adopt_pay_type;
  1749. }
  1750. foreach ($adopt_pay_list as $k => $val) {
  1751. if ($val['payment'] == 4 && is_wechat_platform()) {
  1752. unset($adopt_pay_list[$k]);
  1753. }
  1754. if ($val['payment'] == 1 && is_alipay_platform()) {
  1755. unset($adopt_pay_list[$k]);
  1756. }
  1757. }
  1758. $new_list = array_values($adopt_pay_list);
  1759. } else {
  1760. $pay_type_list_json = Option::get(OptionSetting::STORE_PAYMENT, get_store_id(), 'pay', Option::get(OptionSetting::STORE_PAYMENT, get_store_id(), 'store', '{"wechat":{"value":1}}')['value']);
  1761. $pay_type_list = Json::decode($pay_type_list_json['value']);
  1762. $user_pay_list_json = Option::get('payment_' . get_user_id(), get_store_id(), 'user')['value'];
  1763. if ($user_pay_list_json) {
  1764. $user_pay_list_arr = Json::decode($user_pay_list_json);
  1765. foreach ($pay_type_list as $key => &$value) {
  1766. if (isset($user_pay_list_arr[$key]) && $user_pay_list_arr[$key]['value'] == 0 && $value['value'] == 1) {
  1767. $value['value'] = 0;
  1768. }
  1769. }
  1770. }
  1771. $new_list = [];
  1772. $ok = true;
  1773. $is_virtual = false;
  1774. $is_integral = false; //积分兑换商品
  1775. foreach ($this->mch_list as $mch) {
  1776. if (!empty($mch['goods_list'][0]['product_type']) && $mch['goods_list'][0]['product_type'] == 3) {
  1777. $is_virtual = true;
  1778. }
  1779. if (!empty($mch['goods_list'][0]['product_type']) && $mch['goods_list'][0]['product_type'] == Goods::GOODS_TYPE_INTEGRAL) {
  1780. $is_integral = true;
  1781. }
  1782. if (!empty($mch['goods_list'][0]['product_type']) && $mch['goods_list'][0]['product_type'] == Goods::GOODS_TYPE_TIME) {
  1783. $is_integral = true;
  1784. }
  1785. if ($mch['mch_id'] == 0) {
  1786. continue;
  1787. } else {
  1788. $ok = false;
  1789. break;
  1790. }
  1791. }
  1792. foreach ($pay_type_list as $index => $pay_type_value) {
  1793. if (in_array($index, $ignore)) {
  1794. continue;
  1795. }
  1796. if ((is_wechat_platform() || is_h5() || is_app_platform()) && $index == 'wechat' && $pay_type_value['value'] == 1) {
  1797. $new_list[] = [
  1798. 'name' => '微信支付',
  1799. 'payment' => 1,
  1800. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1801. ];
  1802. }
  1803. if ((is_wechat_platform()) && $index == Order::PAY_TYPE_KEY_WX_B2B && $pay_type_value['value'] == 1) {
  1804. $new_list[] = [
  1805. 'name' => Order::PAY_TYPE_NAME_WX_B2B,
  1806. 'payment' => Order::PAY_TYPE_WX_B2B,
  1807. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1808. ];
  1809. }
  1810. if ((is_alipay_platform() || is_h5() || is_app_platform()) && $index == 'alipay' && $pay_type_value['value'] == 1) {
  1811. $new_list[] = [
  1812. 'name' => '支付宝支付',
  1813. 'payment' => 4,
  1814. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-alipay.png'
  1815. ];
  1816. }
  1817. //如果是微信且商城已配置通联支付进件数据
  1818. if (is_wechat_platform() && $index == Order::PAY_TYPE_KEY_YUNST_WECHAT_PAY && $pay_type_value['value'] == 1) {
  1819. $store = Store::findOne(get_store_id());
  1820. if (!empty($store->cusid)) {
  1821. $new_list[] = [
  1822. 'name' => '通联支付',
  1823. 'payment' => Order::PAY_TYPE_YUNST_WECHAT_PAY,
  1824. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1825. ];
  1826. }
  1827. }
  1828. if ((is_h5() || is_app_platform() || is_wechat_platform()) && $index == Order::PAY_TYPE_KEY_ALLINPAY_WX && $pay_type_value['value'] == 1) {
  1829. $new_list[] = [
  1830. 'name' => Order::PAY_TYPE_NAME_ALLINPAY_WX,
  1831. 'payment' => Order::PAY_TYPE_ALLINPAY_WX,
  1832. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1833. ];
  1834. }
  1835. if ((is_app_platform() || is_wechat_platform()) && $index == Order::PAY_TYPE_KEY_ADAPAY_WX && $pay_type_value['value'] == 1) {
  1836. $new_list[] = [
  1837. 'name' => Order::PAY_TYPE_NAME_ADAPAY_WX,
  1838. 'payment' => Order::PAY_TYPE_ADAPAY_WX,
  1839. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1840. ];
  1841. }
  1842. if ((is_app_platform() || is_alipay_platform()) && $index == Order::PAY_TYPE_KEY_ADAPAY_ALIPAY && $pay_type_value['value'] == 1) {
  1843. $new_list[] = [
  1844. 'name' => Order::PAY_TYPE_NAME_ADAPAY_ALIPAY ,
  1845. 'payment' => Order::PAY_TYPE_ADAPAY_ALIPAY ,
  1846. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-alipay.png'
  1847. ];
  1848. }
  1849. if ($index == Order::PAY_TYPE_KEY_ADAPAY_QUICKPAY_FRONTPAY && $pay_type_value['value'] == 1) {
  1850. $new_list[] = [
  1851. 'name' => Order::PAY_TYPE_NAME_ADAPAY_QUICKPAY_FRONTPAY,
  1852. 'payment' => Order::PAY_TYPE_ADAPAY_QUICKPAY_FRONTPAY,
  1853. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1854. ];
  1855. }
  1856. if (is_wechat_platform() && $index == Order::PAY_TYPE_KEY_HUIFU_V2_JSPAY_WX && $pay_type_value['value'] == 1) {
  1857. $new_list[] = [
  1858. 'name' => Order::PAY_TYPE_NAME_HUIFU_V2_JSPAY_WX,
  1859. 'payment' => Order::PAY_TYPE_HUIFU_V2_JSPAY_WX,
  1860. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1861. ];
  1862. }
  1863. if ($index == Order::PAY_TYPE_KEY_OFFLINE && $pay_type_value['value'] == 1) {
  1864. $new_list[] = [
  1865. 'name' => Order::PAY_TYPE_NAME_OFFLINE,
  1866. 'payment' => Order::PAY_TYPE_OFFLINE,
  1867. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1868. ];
  1869. }
  1870. if ($index == Order::PAY_TYPE_KEY_MONTH && $pay_type_value['value'] == 1) {
  1871. $new_list[] = [
  1872. 'name' => Order::PAY_TYPE_NAME_MONTH,
  1873. 'payment' => Order::PAY_TYPE_MONTH,
  1874. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1875. ];
  1876. }
  1877. if ($index == 'huodao' && $pay_type_value['value'] == 1 && $ok && !$is_virtual && !$is_integral) {
  1878. $new_list[] = [
  1879. 'name' => '货到付款',
  1880. 'payment' => 2,
  1881. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-huodao.png'
  1882. ];
  1883. }
  1884. if ($index == 'friend' && $pay_type_value['value'] == 1 && !$is_integral) {
  1885. $new_list[] = [
  1886. 'name' => '朋友代付',
  1887. 'payment' => 7,
  1888. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-huodao.png'
  1889. ];
  1890. }
  1891. }
  1892. if (is_toutiao_platform()) {
  1893. $new_list[] = [
  1894. 'name' => '线上支付',
  1895. 'payment' => 5,
  1896. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1897. ];
  1898. }
  1899. }
  1900. return $new_list;
  1901. }
  1902. /**
  1903. * 支付方式
  1904. * @param array $is_payment //支付方式
  1905. * @param array $ignore //忽略的支付方式
  1906. * @return array
  1907. */
  1908. public static function getPayType($is_payment = array(), $ignore = array())
  1909. {
  1910. if (!$is_payment || empty($is_payment)) {
  1911. $default = '{"wechat":{"value":1}}';
  1912. if (is_alipay_platform()) {
  1913. $default = '{"alipay":{"value":1}}';
  1914. }
  1915. if (is_toutiao_platform()) {
  1916. $default = '{"toutiao":{"value":1}}';
  1917. }
  1918. $pay_str = Option::get(OptionSetting::STORE_PAYMENT, get_store_id(), 'pay', Option::get(OptionSetting::STORE_PAYMENT, get_store_id(), 'store', $default)['value']);
  1919. $is_payment = Json::decode($pay_str['value']);
  1920. $user_pay_list_json = Option::get('payment_' . get_user_id(), get_store_id(), 'user')['value'];
  1921. if ($user_pay_list_json) {
  1922. $user_pay_list_arr = Json::decode($user_pay_list_json);
  1923. foreach ($is_payment as $key => &$value) {
  1924. if (isset($user_pay_list_arr[$key]) && $user_pay_list_arr[$key]['value'] == 0 && $value['value'] == 1) {
  1925. $value['value'] = 0;
  1926. }
  1927. }
  1928. }
  1929. }
  1930. $pay_type_list = [];
  1931. foreach ($is_payment as $index => $value) {
  1932. if (in_array($index, $ignore)) {
  1933. continue;
  1934. }
  1935. if ($index == 'wechat' && $value['value'] == 1 && !is_alipay_platform()) {
  1936. $pay_type_list[] = [
  1937. 'name' => '微信支付',
  1938. 'payment' => 1,
  1939. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/v1/statics/wxapp/images/icon-payment-online.png'
  1940. ];
  1941. }
  1942. if ((is_wechat_platform()) && $index == Order::PAY_TYPE_KEY_WX_B2B && $value['value'] == 1) {
  1943. $pay_type_list[] = [
  1944. 'name' => Order::PAY_TYPE_NAME_WX_B2B,
  1945. 'payment' => Order::PAY_TYPE_WX_B2B,
  1946. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1947. ];
  1948. }
  1949. if ((is_h5() || is_app_platform() || is_wechat_platform()) && $index == Order::PAY_TYPE_KEY_ALLINPAY_WX && $value['value'] == 1) {
  1950. $pay_type_list[] = [
  1951. 'name' => Order::PAY_TYPE_NAME_ALLINPAY_WX,
  1952. 'payment' => Order::PAY_TYPE_ALLINPAY_WX,
  1953. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1954. ];
  1955. }
  1956. if ((is_app_platform() || is_wechat_platform()) && $index == Order::PAY_TYPE_KEY_ADAPAY_WX && $value['value'] == 1) {
  1957. $pay_type_list[] = [
  1958. 'name' => Order::PAY_TYPE_NAME_ADAPAY_WX,
  1959. 'payment' => Order::PAY_TYPE_ADAPAY_WX,
  1960. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1961. ];
  1962. }
  1963. if ((is_app_platform() || is_alipay_platform()) && $index == Order::PAY_TYPE_KEY_ADAPAY_ALIPAY && $value['value'] == 1) {
  1964. $pay_type_list[] = [
  1965. 'name' => Order::PAY_TYPE_NAME_ADAPAY_ALIPAY,
  1966. 'payment' => Order::PAY_TYPE_ADAPAY_ALIPAY,
  1967. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-alipay.png'
  1968. ];
  1969. }
  1970. if ($index == Order::PAY_TYPE_KEY_ADAPAY_QUICKPAY_FRONTPAY && $value['value'] == 1) {
  1971. $pay_type_list[] = [
  1972. 'name' => Order::PAY_TYPE_NAME_ADAPAY_QUICKPAY_FRONTPAY,
  1973. 'payment' => Order::PAY_TYPE_ADAPAY_QUICKPAY_FRONTPAY,
  1974. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1975. ];
  1976. }
  1977. if (is_wechat_platform() && $index == Order::PAY_TYPE_KEY_HUIFU_V2_JSPAY_WX && $value['value'] == 1) {
  1978. $pay_type_list[] = [
  1979. 'name' => Order::PAY_TYPE_NAME_HUIFU_V2_JSPAY_WX,
  1980. 'payment' => Order::PAY_TYPE_HUIFU_V2_JSPAY_WX,
  1981. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  1982. ];
  1983. }
  1984. if ($index == 'toutiao' && $value['value'] == 1 && is_toutiao_platform()) {
  1985. $pay_type_list[] = [
  1986. 'name' => '线上支付',
  1987. 'payment' => 5,
  1988. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/v1/statics/wxapp/images/icon-payment-online.png'
  1989. ];
  1990. }
  1991. if ($index == 'huodao' && $value['value'] == 1) {
  1992. $pay_type_list[] = [
  1993. 'name' => '货到付款',
  1994. 'payment' => 2,
  1995. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/v1/statics/wxapp/images/icon-payment-huodao.png'
  1996. ];
  1997. }
  1998. if (get_params('_from') == OrderPayDataForm::PAY_FROM_APP || is_alipay_platform() || is_h5()) {
  1999. if ($index == 'alipay' && $value['value'] == 1) {
  2000. $pay_type_list[] = [
  2001. 'name' => '支付宝支付',
  2002. 'payment' => 4,
  2003. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/statics/images/recharge/icon-alipay.png'
  2004. ];
  2005. }
  2006. }
  2007. if ($index == 'balance' && $value['value'] == 1) {
  2008. $pay_type_list[] = [
  2009. 'name' => '账户余额支付',
  2010. 'payment' => 3,
  2011. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/v1/statics/wxapp/images/icon-payment-balance.png'
  2012. ];
  2013. }
  2014. if ($index == 'friend' && $value['value'] == 1) {
  2015. $pay_type_list[] = [
  2016. 'name' => '朋友代付',
  2017. 'payment' => 7,
  2018. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-huodao.png'
  2019. ];
  2020. }
  2021. //如果是微信且商城已配置通联支付进件数据
  2022. if (is_wechat_platform() && $index == Order::PAY_TYPE_KEY_YUNST_WECHAT_PAY && $value['value'] == 1) {
  2023. $store = Store::findOne(get_store_id());
  2024. if (!empty($store->cusid)) {
  2025. $new_list[] = [
  2026. 'name' => '通联支付',
  2027. 'payment' => Order::PAY_TYPE_YUNST_WECHAT_PAY,
  2028. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  2029. ];
  2030. }
  2031. }
  2032. if ($index == Order::PAY_TYPE_KEY_OFFLINE && $value['value'] == 1) {
  2033. $pay_type_list[] = [
  2034. 'name' => Order::PAY_TYPE_NAME_OFFLINE,
  2035. 'payment' => Order::PAY_TYPE_OFFLINE,
  2036. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  2037. ];
  2038. }
  2039. if ($index == Order::PAY_TYPE_KEY_MONTH && $value['value'] == 1) {
  2040. $pay_type_list[] = [
  2041. 'name' => Order::PAY_TYPE_NAME_MONTH,
  2042. 'payment' => Order::PAY_TYPE_MONTH,
  2043. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/recharge/icon-online.png'
  2044. ];
  2045. }
  2046. }
  2047. $is_open_combine = Option::get(OptionSetting::STORE_COMBINE_PAY, get_store_id(), 'recharge')['value'];
  2048. $use = get_user();
  2049. if ($is_open_combine && $use['money']) {
  2050. array_unshift($pay_type_list, [
  2051. 'name' => '余额支付',
  2052. 'payment' => 3,
  2053. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/clientImg/images/account_pay_icon.png'
  2054. ]);
  2055. }
  2056. if (!$pay_type_list) {
  2057. if (is_wechat_platform()) {
  2058. $pay_type_list[] = [
  2059. 'name' => '微信支付',
  2060. 'payment' => 1,
  2061. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/v1/statics/images/recharge/icon-online.png'
  2062. ];
  2063. }
  2064. if (is_toutiao_platform()) {
  2065. $pay_type_list[] = [
  2066. 'name' => '线上支付',
  2067. 'payment' => 5,
  2068. 'icon' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/v1/statics/images/recharge/icon-online.png'
  2069. ];
  2070. }
  2071. }
  2072. return $pay_type_list;
  2073. }
  2074. protected function getCouponList(&$mch)
  2075. {
  2076. // if (get_md_id()) {
  2077. // $mch['coupon_list'] = [];
  2078. // return;
  2079. // }
  2080. if (!isset($mch['mch_id'])) {
  2081. $mch['mch_id'] = 0;
  2082. }
  2083. $goods_total_price = $mch['total_price'];
  2084. $cat_ids = $this->getCatIdList($mch['goods_list'],$mch['mch_id']);
  2085. $coupon_goods_id = $this->getGoodsIdList($mch['goods_list']);
  2086. $list = UserCoupon::find()->alias('uc')
  2087. ->leftJoin(['c' => Coupon::tableName()], 'uc.coupon_id=c.id')
  2088. ->leftJoin(['cas' => CouponAutoSend::tableName()], 'uc.coupon_auto_send_id=cas.id')
  2089. ->where([
  2090. 'AND',
  2091. ['uc.is_delete' => 0],
  2092. ['uc.is_use' => 0],
  2093. ['c.mch_id' => $mch['mch_id']],
  2094. ['uc.is_expire' => 0],
  2095. ['uc.user_id' => $this->user_id],
  2096. ['<=', 'c.min_price', $goods_total_price],
  2097. ])
  2098. ->andWhere($mch['plugin_type'] == 6 ? ['c.appoint_type' => 3] : [
  2099. 'OR',
  2100. ['<>', 'c.appoint_type', 3],
  2101. 'c.appoint_type IS NULL'
  2102. ])
  2103. ->select('c.name, c.expire_day, c.id, c.expire_type, c.discount_type, c.discount, c.discount_max_price, uc.id user_coupon_id,c.mch_id,c.rule,c.sub_price,c.min_price,cas.event,uc.begin_time,uc.end_time,uc.type,c.appoint_type,c.cat_id_list,c.goods_id_list')
  2104. ->indexBy('user_coupon_id')->asArray()->all();
  2105. $events = [
  2106. 0 => '平台发放',
  2107. 1 => '分享红包',
  2108. 2 => '购物返券',
  2109. 3 => '领券中心',
  2110. ];
  2111. $max_price = 0;
  2112. if ($mch['plugin_type'] == 6) {
  2113. $max_price = $mch['total_price'];
  2114. } else {
  2115. foreach ($mch['goods_list'] as $v) {
  2116. $max_price += $v['price'];
  2117. }
  2118. }
  2119. $new_list = [];
  2120. foreach ($list as $i => $item) {
  2121. if ($item['expire_type'] == 1) {
  2122. if ($item['end_time'] > 0) {
  2123. if (time() > $item['end_time']) {
  2124. $list[$i]['_reason'] = 'time() > $item[\'end_time\']';
  2125. continue;
  2126. }
  2127. }
  2128. }
  2129. if ($item['expire_type'] == 2) {
  2130. if (time() > $item['end_time'] || time() < $item['begin_time']) {
  2131. $list[$i]['_reason'] = '(time() > $item[\'end_time\'] || time() < $item[\'begin_time\'])';
  2132. continue;
  2133. }
  2134. }
  2135. $list[$i]['status'] = 0;
  2136. if (isset($item['is_use']) && $item['is_use']) {
  2137. $list[$i]['status'] = 1;
  2138. }
  2139. if (isset($item['is_expire']) && $item['is_expire']) {
  2140. $list[$i]['status'] = 2;
  2141. }
  2142. $list[$i]['min_price_desc'] = $item['min_price'] == 0 ? '无门槛' : '满' . $item['min_price'] . '元可用';
  2143. $list[$i]['begin_time'] = date('Y.m.d H:i', (int)$item['begin_time']);
  2144. $list[$i]['end_time'] = date('Y.m.d H:i', (int)$item['end_time']);
  2145. $list[$i]['discount_type'] = $item['discount_type'];
  2146. $list[$i]['discount'] = $item['discount'];
  2147. if (!$item['event']) {
  2148. if ($item['type'] == 2) {
  2149. $list[$i]['event'] = $item['event'] = 3;
  2150. } else {
  2151. $list[$i]['event'] = $item['event'] = 0;
  2152. }
  2153. }
  2154. $list[$i]['event_desc'] = $events[$item['event']] ?: '领券中心';
  2155. $list[$i]['min_price'] = doubleval($item['min_price']);
  2156. if ($list[$i]['discount_type'] == 1) {
  2157. $list[$i]['sub_price'] = round($mch['total_price'] - doubleval($mch['total_price'] * $list[$i]['discount'] / 10), 2);
  2158. if($item['discount_max_price'] > 0 && $list[$i]['sub_price'] > $item['discount_max_price']){
  2159. $list[$i]['sub_price'] = $item['discount_max_price'];
  2160. }
  2161. } else {
  2162. $list[$i]['sub_price'] = doubleval($item['sub_price']);
  2163. }
  2164. $goodsAdd = array_column($mch['goods_list'], 'goods_id');
  2165. if ($list[$i]['appoint_type'] == 1) {
  2166. $list[$i]['cat_id_list'] = json_decode($list[$i]['cat_id_list']);
  2167. if ($list[$i]['cat_id_list'] != null) {
  2168. $current = array_intersect($list[$i]['cat_id_list'], $cat_ids);
  2169. if ($current) {
  2170. $goodsAdd = [];
  2171. $price = 0;
  2172. foreach ($current as $v) {
  2173. foreach ($mch['goods_list'] as $v2) {
  2174. if (in_array($v, $v2['cat_id']) && !in_array($v2['goods_id'], $goodsAdd)) {
  2175. $price += $v2['price'];
  2176. array_push($goodsAdd, $v2['goods_id']);
  2177. }
  2178. };
  2179. }
  2180. if ($list[$i]['discount_type'] == 1) {
  2181. $list[$i]['sub_price'] = round($price - doubleval($price * $list[$i]['discount'] / 10), 2);
  2182. if($item['discount_max_price'] > 0 && $list[$i]['sub_price'] > $item['discount_max_price']){
  2183. $list[$i]['sub_price'] = $item['discount_max_price'];
  2184. }
  2185. } else {
  2186. $list[$i]['sub_price'] = doubleval($item['sub_price']);
  2187. }
  2188. if ($price < $list[$i]['min_price']) {
  2189. $list[$i]['_reason'] = '$price < $list[$i][\'min_price\']';
  2190. // unset($list[$i]);
  2191. continue;
  2192. }
  2193. } else {
  2194. $list[$i]['_reason'] = '$current else';
  2195. // unset($list[$i]);
  2196. continue;
  2197. }
  2198. }
  2199. } elseif ($list[$i]['appoint_type'] == 2) {
  2200. $list[$i]['goods_id_list'] = json_decode($list[$i]['goods_id_list']);
  2201. if ($list[$i]['goods_id_list'] != null) {
  2202. $current = array_intersect($list[$i]['goods_id_list'], $coupon_goods_id);
  2203. if ($current) {
  2204. $goodsAdd = [];
  2205. $price = 0;
  2206. foreach ($current as $v) {
  2207. foreach ($mch['goods_list'] as $v2) {
  2208. if ($v == $v2['goods_id'] && !in_array($v2['goods_id'], $goodsAdd)) {
  2209. $price += $v2['price'];
  2210. array_push($goodsAdd, $v2['goods_id']);
  2211. }
  2212. }
  2213. }
  2214. if ($list[$i]['discount_type'] == 1) {
  2215. $list[$i]['sub_price'] = round($price - doubleval($price * $list[$i]['discount'] / 10), 2);
  2216. if($item['discount_max_price'] > 0 && $list[$i]['sub_price'] > $item['discount_max_price']){
  2217. $list[$i]['sub_price'] = $item['discount_max_price'];
  2218. }
  2219. } else {
  2220. $list[$i]['sub_price'] = doubleval($item['sub_price']);
  2221. }
  2222. if ($price < $list[$i]['min_price']) {
  2223. $list[$i]['_reason'] = '$price < $list[$i][\'min_price\']';
  2224. // unset($list[$i]);
  2225. continue;
  2226. }
  2227. } else {
  2228. $list[$i]['_reason'] = '$current else';
  2229. // unset($list[$i]);
  2230. continue;
  2231. }
  2232. }
  2233. } else {
  2234. if ($max_price < $list[$i]['min_price']) {
  2235. $list[$i]['_reason'] = '$max_price < $list[$i][\'min_price\']';
  2236. // unset($list[$i]);
  2237. continue;
  2238. }
  2239. }
  2240. $list[$i]['goods_use'] = $goodsAdd;
  2241. $new_list[] = $list[$i];
  2242. }
  2243. $mch['__coupon_list'] = $list;
  2244. if (!empty($this->verify_card_id)) {
  2245. $mch['coupon_list'] = [];
  2246. } else {
  2247. if (!$this->is_worker) {
  2248. $mch['coupon_list'] = $new_list;
  2249. }
  2250. }
  2251. }
  2252. protected function getCatIdList(&$goods_list,$mch_id = 0)
  2253. {
  2254. $cat_id_list = [];
  2255. foreach ($goods_list as &$goods) {
  2256. if ($goods['goods_cat_id'] == 0) {
  2257. if ($mch_id > 0) {
  2258. $goods_cat_list = MchGoodsCat::find()
  2259. ->select('cat_id')->where([
  2260. 'goods_id' => $goods['goods_id'],
  2261. ])->all();
  2262. }else {
  2263. $goods_cat_list = GoodsCat::find()
  2264. ->select('cat_id')->where([
  2265. 'goods_id' => $goods['goods_id'],
  2266. 'is_delete' => 0,
  2267. ])->all();
  2268. }
  2269. foreach ($goods_cat_list as $goods_cat) {
  2270. $cat_id_list[] = $goods_cat->cat_id;
  2271. $goods['cat_id'][] = $goods_cat->cat_id;
  2272. }
  2273. } else {
  2274. $cat_id_list[] = $goods['goods_cat_id'];
  2275. $goods['cat_id'][] = $goods['goods_cat_id'];
  2276. }
  2277. $cat_parent_list = Cat::find()->select('parent_id')
  2278. ->andWhere(['id' => $goods['cat_id'], 'store_id' => $this->store_id, 'is_delete' => 0])->andWhere(['>', 'parent_id', 0])
  2279. ->column();
  2280. $cat_id_list = array_merge($cat_parent_list, $cat_id_list);
  2281. $goods['cat_id'] = array_merge($cat_parent_list, is_array($goods['cat_id']) ? $goods['cat_id'] : []);
  2282. }
  2283. unset($goods);
  2284. return array_unique($cat_id_list);
  2285. }
  2286. protected function getGoodsIdList($goods_list)
  2287. {
  2288. $goods_id_list = [];
  2289. foreach ($goods_list as $goods) {
  2290. $goods_id_list[] = $goods['goods_id'];
  2291. }
  2292. return $goods_id_list;
  2293. }
  2294. protected function getLevelData()
  2295. {
  2296. $level = Level::find()->select([
  2297. 'name', 'level', 'discount',
  2298. ])->where(['level' => $this->user->level, 'store_id' => $this->store_id, 'is_delete' => 0])
  2299. ->asArray()->one();
  2300. return $level;
  2301. }
  2302. //积分计算
  2303. /**
  2304. * @param $goods_item object 重新编写的goods_item
  2305. * @param $store_integral int 商城设置的积分规则
  2306. * @param $goods_id array 已设置积分的商品id数组
  2307. * @return array
  2308. */
  2309. protected function getIntegral($goods_item, $store_integral, $goods_id = array(), $send_integral_profit = 0)
  2310. {
  2311. $integral = json_decode($goods_item->integral, true);
  2312. $resIntegral = [
  2313. 'forehead' => 0,
  2314. 'forehead_integral' => 0,
  2315. ];
  2316. $maxIntegral = [
  2317. 'forehead' => 0,
  2318. 'forehead_integral' => 0,
  2319. ];
  2320. // 赠送积分计算
  2321. // if ($send_integral_profit > 0) {
  2322. // // 百分比
  2323. // $goods_item->give = (int)($goods_item->price * ($send_integral_profit / 100));
  2324. // }
  2325. // else {
  2326. // 固定积分
  2327. // $goods_item->give = (int)($give * $goods_item->num);
  2328. // }
  2329. if ($integral) {
  2330. // // 赠送积分计算
  2331. $give = (int)$integral['give'];
  2332. if (strpos($give, '%') !== false) {
  2333. // 百分比
  2334. $give = trim($give, '%');
  2335. $goods_item->give = (int)(intval($goods_item->price) * ($give / 100));
  2336. } else {
  2337. // 固定积分
  2338. $goods_item->give = (intval($give) * intval($goods_item->num));
  2339. }
  2340. if ($give <= 0 && $send_integral_profit > 0) {
  2341. $goods_item->give = (int)(intval($goods_item->price) * ($send_integral_profit / 100));
  2342. }
  2343. // 抵扣积分计算
  2344. $forehead = $integral['forehead'];
  2345. if ($forehead) {
  2346. if (strpos($forehead, '%') !== false) {//百分比积分抵扣计算
  2347. if ($forehead >= 100) {
  2348. $forehead = 100;
  2349. }
  2350. if ($integral['more'] == '1') {//多件累计计算
  2351. $resIntegral['forehead_integral'] = (int)(($forehead / 100) * $goods_item->price * $store_integral);
  2352. } else {
  2353. if (!in_array($goods_item->id, $goods_id)) { //不允许多件累计 同id商品值计算一次积分抵扣
  2354. $resIntegral['forehead_integral'] = (int)(($forehead / 100) * $goods_item->single_price * $store_integral);
  2355. }
  2356. }
  2357. } else {
  2358. // if ($integral['more'] == '1') {
  2359. // $resIntegral['forehead_integral'] = (int)($store_integral * $goods_item->price);
  2360. // if ($goods_item->price > ($forehead * $goods_item->num)) {
  2361. // $resIntegral['forehead_integral'] = (int)($forehead * $goods_item->num * $store_integral);
  2362. // }
  2363. // } else {
  2364. // if (!in_array($goods_item->id, $goods_id)) {
  2365. // $goodsPrice = $goods_item->single_price;
  2366. // $resIntegral['forehead_integral'] = (int)($store_integral * $goodsPrice);
  2367. // if ($goodsPrice > $forehead) {
  2368. // if ($forehead > 0) {
  2369. // $resIntegral['forehead_integral'] = (int)($forehead * $store_integral);
  2370. // } else {
  2371. // $resIntegral['forehead_integral'] = 0;
  2372. // }
  2373. // }
  2374. // }
  2375. // }
  2376. // 累计
  2377. $resIntegral['forehead_integral'] = bcmul($store_integral, $goods_item->price);
  2378. if ($goods_item->price > ($forehead * $goods_item->num)) {
  2379. $resIntegral['forehead_integral'] = (int)($forehead * $goods_item->num * $store_integral);
  2380. }
  2381. }
  2382. $maxIntegral['forehead_integral'] = $resIntegral['forehead_integral'];
  2383. $maxIntegral['forehead'] = $store_integral ? sprintf("%.2f", ($maxIntegral['forehead_integral'] / $store_integral)) : 0;
  2384. }
  2385. $user_integral = $this->user->integral;
  2386. $user_integral = floor_num($user_integral, 0);
  2387. if ($this->integral['forehead_integral'] < $user_integral) {
  2388. $resetIntegral = $user_integral - $this->integral['forehead_integral'];
  2389. $resIntegral['forehead_integral'] = $resIntegral['forehead_integral'] >= $resetIntegral ? $resetIntegral : $resIntegral['forehead_integral'];
  2390. $resIntegral['forehead'] = $store_integral ? sprintf("%.2f", ($resIntegral['forehead_integral'] / $store_integral)) : 0;
  2391. $this->integral['forehead_integral'] += $resIntegral['forehead_integral'];
  2392. $this->integral['forehead'] += $resIntegral['forehead'];
  2393. } else {
  2394. $resIntegral['forehead_integral'] = 0;
  2395. $resIntegral['forehead'] = 0;
  2396. }
  2397. }
  2398. return [
  2399. 'maxIntegral' => $maxIntegral,
  2400. 'resIntegral' => $resIntegral,
  2401. 'give' => $goods_item->give ?? ''
  2402. ];
  2403. }
  2404. public function getExpressPrice($mch)
  2405. {
  2406. if($this->is_giving_gifts){
  2407. return 0;
  2408. }
  2409. $address = $this->address ?: $this->address = Address::findOne([
  2410. 'user_id' => get_saas_user_id(),
  2411. 'is_default' => 1,
  2412. 'is_delete' => 0,
  2413. ]);
  2414. $expressPrice = 0;
  2415. if ($address) {
  2416. //先计算单品满件包邮和满额包邮
  2417. $resGoodsList = Goods::cutFull($mch['goods_list']);
  2418. //再通过运费规则计算运费
  2419. $expressPrice = PostageRules::getExpressPriceMore($this->store_id ?? get_store_id(), $address['city_id'], $resGoodsList, $address['province_id']);
  2420. }
  2421. $mchTotalPrice = array_sum(array_column($mch['goods_list'], 'price'));
  2422. $expressPrice = $this->getFreeDeliveryRules($mch, $expressPrice, $mchTotalPrice);
  2423. return $expressPrice['expressPrice'] >= 0 ? $expressPrice['expressPrice'] : 0;
  2424. }
  2425. public function getWorkerTravelPrice()
  2426. {
  2427. $travelPrice = 0;
  2428. $store_id = get_store_id();
  2429. $lat = 0;
  2430. $lng = 0;
  2431. if ($this->address) {
  2432. $address = $this->address;
  2433. $lat = $address['latitude'];
  2434. $lng = $address['longitude'];
  2435. }
  2436. if (empty($this->worker['id'])) {
  2437. return [
  2438. 'distance' => 0,
  2439. 'starting_price' => 0,
  2440. 'additional_charge' => 0,
  2441. 'travelPrice' => 0
  2442. ];
  2443. }
  2444. $from = [
  2445. $this->worker['lat'] > 0 ? $this->worker['lat'] : '1.11',
  2446. $this->worker['lng'] > 0 ? $this->worker['lng'] : '1.11'
  2447. ];
  2448. $to = [
  2449. $lat ?: ($from[0]),
  2450. $lng ?: ($from[1])
  2451. ];
  2452. sort($from);
  2453. sort($to);
  2454. // $from = implode(",", $from);
  2455. // $to = implode(",", $to);
  2456. $distance = $this->get_distance($from, $to);
  2457. $distance *= 2;
  2458. // $place_url = 'https://apis.map.qq.com/ws/distance/v1/?mode=driving&from='.$from.'&to='.$to .'&key=7XCBZ-2BHRO-FK4WS-SM73D-4DQ43-WUBUT';
  2459. // $json_place = file_get_contents($place_url);
  2460. // $result = json_decode($json_place, true);
  2461. // $distance = 0;
  2462. // if ($result['status'] === 0) {
  2463. // $distance = $result['result']['elements'][0]['distance'];
  2464. // }
  2465. //
  2466. //
  2467. // $place_url = 'https://apis.map.qq.com/ws/distance/v1/?mode=driving&from='.$to.'&to='.$from .'&key=OMQBZ-ACWE2-VWZU5-C6W7M-Y6EIF-VNBYM';
  2468. // $json_place = file_get_contents($place_url);
  2469. // $result_ = json_decode($json_place, true);
  2470. // if ($result_['status'] === 0) {
  2471. // $distance += $result_['result']['elements'][0]['distance'];
  2472. // }
  2473. $setting = WorkerSetting::findOne(['store_id' => $store_id, 'is_delete' => 0]);
  2474. $starting_price = $setting->starting_price ?? 0;
  2475. $additional_charge = $setting->additional_charge ?? 0;
  2476. if ($distance > 0 && $setting) {
  2477. $distance = sprintf("%.2f", $distance / 1000); //千米
  2478. //计算起步数
  2479. $travelPrice += floatval($starting_price);
  2480. if ($distance > 1) {
  2481. //大于一公里按照每公里加收算
  2482. $diff = ceil($distance - 1);
  2483. $travelPrice += floatval(sprintf("%.2f",$diff * $additional_charge));
  2484. }
  2485. }
  2486. return [
  2487. 'distance' => $distance,
  2488. 'starting_price' => $starting_price,
  2489. 'additional_charge' => $additional_charge,
  2490. 'travelPrice' => $travelPrice
  2491. ];
  2492. }
  2493. public function get_distance($from, $to, $km = true, $decimal = 2)
  2494. {
  2495. sort($from);
  2496. sort($to);
  2497. $EARTH_RADIUS = 6370996.81; // 地球半径系数
  2498. $distance = $EARTH_RADIUS*2*asin(sqrt(pow(sin( ($from[0]*pi()/180-$to[0]*pi()/180)/2),2)+cos($from[0]*pi()/180)*cos($to[0]*pi()/180)* pow(sin( ($from[1]*pi()/180-$to[1]*pi()/180)/2),2)))*1000;
  2499. if($km){
  2500. $distance = $distance / 1000;
  2501. }
  2502. return round($distance, $decimal);
  2503. }
  2504. //获取服务人员时间
  2505. public function workerTime($id)
  2506. {
  2507. try {
  2508. $worker = Worker::findOne($id);
  2509. // if (!$worker) {
  2510. // return [
  2511. // 'code' => 0,
  2512. // 'msg' => 'success',
  2513. // 'data' => null
  2514. // ];
  2515. // }
  2516. $time = null;
  2517. $book_start_time_ = 0000;
  2518. $book_end_time_ = 2400;
  2519. $times_arr = [];
  2520. if ($worker) {
  2521. $book_start_time_ = $worker->book_start_time;
  2522. $book_end_time_ = $worker->book_end_time;
  2523. if ($book_start_time_ > $book_end_time_) {
  2524. $middle = $book_start_time_;
  2525. $book_start_time_ = $book_end_time_;
  2526. $book_end_time_ = $middle;
  2527. }
  2528. }
  2529. $book_end_time_ = $book_end_time_ > 0 ? $book_end_time_ : 2400;
  2530. //判断是否存在服务开始结束时间
  2531. if ($book_start_time_ >= 0 && $book_end_time_ >= 0) {
  2532. $book_start_time_ = intval($book_start_time_);
  2533. $book_end_time_ = intval($book_end_time_);
  2534. if ($id > 0) {
  2535. $order_ids = WorkerOrderExt::find()->where(['worker_id' => $id, 'user_revoke' => 0, 'status_ext' => [WorkerOrderExt::STATUS_EXT_HAS_BIND, WorkerOrderExt::STATUS_EXT_ON_ROAD, WorkerOrderExt::STATUS_EXT_ARRIVE, WorkerOrderExt::STATUS_EXT_START]])
  2536. ->select('order_id')->column();
  2537. $times_arr = Order::find()->where(['id' => $order_ids])->select('book_info')->column();
  2538. foreach ($times_arr as &$time_item_) {
  2539. $book_info = json_decode($time_item_, true);
  2540. $time_item_ = strtotime($book_info['worker_time']);
  2541. }
  2542. }
  2543. $time = [];
  2544. //计算7天日期
  2545. $book_date_arr = [];//range(date('Ymd'), date('Ymd')+6);
  2546. for($i = 0;$i<=6;$i++) {
  2547. array_push($book_date_arr, date('Ymd', strtotime('+'.$i.' day')));
  2548. }
  2549. //每天开始结束时间
  2550. foreach ($book_date_arr as $date_index => $date_item) {
  2551. //更改日期格式
  2552. $book_start_time = $book_start_time_;
  2553. $book_end_time = $book_end_time_;
  2554. //周几
  2555. $week = date('N', strtotime($date_item));
  2556. switch ($week) {
  2557. case 1:
  2558. $week = "周一";
  2559. break;
  2560. case 2:
  2561. $week = "周二";
  2562. break;
  2563. case 3:
  2564. $week = "周三";
  2565. break;
  2566. case 4:
  2567. $week = "周四";
  2568. break;
  2569. case 5:
  2570. $week = "周五";
  2571. break;
  2572. case 6:
  2573. $week = "周六";
  2574. break;
  2575. default:
  2576. $week = "周日";
  2577. break;
  2578. }
  2579. //是否今天
  2580. $day = date('Ymd', strtotime($date_item));
  2581. $today = date('Ymd');
  2582. if ($day === $today) {
  2583. $week = "今天";
  2584. }
  2585. $time[$date_index]['date'] = $week . date('m.d', strtotime($date_item));
  2586. $book_start_time = sprintf("%04d", $book_start_time);
  2587. $book_end_time = sprintf("%04d", $book_end_time);
  2588. $book_start_time = substr(str_pad($book_start_time, 4, 0, STR_PAD_LEFT), -4, 2) . ':' . substr($book_start_time, -2);
  2589. $book_end_time = substr(str_pad($book_end_time, 4, 0, STR_PAD_LEFT), -4, 2) . ':' . substr($book_end_time, -2);
  2590. //生成时间
  2591. $book_start_time = strtotime($date_item . ' ' . $book_start_time);
  2592. $book_end_time = strtotime($date_item . ' ' . $book_end_time);
  2593. //不可预约已过去时间计算逻辑
  2594. if ($book_start_time <= time()) {
  2595. $i = '00';
  2596. if (date('i') >= 30) {
  2597. $i = '30';
  2598. }
  2599. //前半小时预约两小时后的整点,后半小时预约两小时后的半点
  2600. $book_start_time = strtotime(date('Ymd H:' . $i, time() + 7200));
  2601. }
  2602. if ($book_end_time <= time()) {
  2603. unset($time[$date_index]);
  2604. continue;
  2605. }
  2606. //每半个小时为一个可预约时间段
  2607. $book_time_arr = range($book_start_time, $book_end_time, 1800);
  2608. if (count($book_time_arr) <= 1) {
  2609. unset($time[$date_index]);
  2610. continue;
  2611. }
  2612. //记录开始结束时间
  2613. $time[$date_index]['time'][0]['start_time'] = date('H:i', $book_time_arr[0]);
  2614. $time[$date_index]['time'][0]['end_time'] = date('H:i', $book_time_arr[count($book_time_arr) - 1]);
  2615. $time[$date_index]['time'][0]['times'] = [];
  2616. foreach ($book_time_arr as $time_index_ => $time_item) {
  2617. if ($time_index_ !== count($book_time_arr) - 1) {
  2618. $status = 0;
  2619. $end_time = $time_item + 1800;
  2620. //显示时间段不可预约状态
  2621. if (!empty($times_arr) && in_array($time_item, $times_arr)) {
  2622. $status = 1;
  2623. }
  2624. $time[$date_index]['time'][0]['times'][$time_index_] = [
  2625. 'status' => $status,
  2626. 'time' => date('H:i', $time_item),
  2627. 'time_int' => $time_item
  2628. ];
  2629. }
  2630. }
  2631. }
  2632. }
  2633. $time = array_values($time);
  2634. return [
  2635. 'code' => 0,
  2636. 'msg' => 'success',
  2637. 'data' => $time
  2638. ];
  2639. } catch (\Exception $e) {
  2640. return [
  2641. 'code' => 1,
  2642. 'msg' => $e->getMessage()
  2643. ];
  2644. }
  2645. }
  2646. /**
  2647. * 计算打包费
  2648. * @param $mch
  2649. * @return int
  2650. */
  2651. protected function getDabaoPrice($mch)
  2652. {
  2653. $goods_list = $mch['goods_list'];
  2654. $dabao_price = 0;
  2655. foreach ($goods_list as $value) {
  2656. $dabao_price += $value['dabao_price'];
  2657. }
  2658. return $dabao_price >= 0 ? $dabao_price : 0;
  2659. }
  2660. // 获取门店列表
  2661. protected function getShopList()
  2662. {
  2663. $start = 0;
  2664. $shop_table_name = Shop::tableName();
  2665. $latitude = 0;
  2666. $longitude = 0;
  2667. if ($this->address && isset($this->address['id'])) {
  2668. $address = Address::findOne($this->address['id']);
  2669. if ($address) {
  2670. $latitude = $address->latitude ? $address->latitude : 0;
  2671. $longitude = $address->longitude ? $address->longitude : 0;
  2672. }
  2673. }
  2674. $sql = "SELECT *, acos(cos({$latitude}*pi()/180 )*cos(latitude*pi()/180)*cos({$longitude}*pi()/180 -longitude*pi()/180)+sin({$latitude}*pi()/180 )*sin(latitude*pi()/180))*6370996.81 as
  2675. distance FROM {$shop_table_name} WHERE ((`store_id`={$this->store_id}) AND (`is_delete`=0)) ";
  2676. if ($this->keyword) {
  2677. $sql .= " AND (`name` like '%{$this->keyword}%') ";
  2678. }
  2679. $sql .= "ORDER BY `distance` LIMIT {$start},30";
  2680. $list = \Yii::$app->db->createCommand($sql)->queryAll();
  2681. $shop = null;
  2682. foreach ($list as $index => $item) {
  2683. if ($item['is_default'] == 1) {
  2684. $shop = $item;
  2685. }
  2686. $list[$index]['distance'] = round($item['distance']/1000, 2).'km';
  2687. }
  2688. return [
  2689. 'list' => $list,
  2690. 'shop' => $shop
  2691. ];
  2692. }
  2693. // 获取起送规则
  2694. protected function getOfferRule($mch)
  2695. {
  2696. $res = [
  2697. 'is_allowed' => 0,
  2698. 'total_price' => 0,
  2699. 'msg' => ''
  2700. ];
  2701. if ($mch['mch_id'] > 0) {
  2702. $res['msg'] = '商户不支持起送规则';
  2703. return $res;
  2704. }
  2705. if (!$this->address) {
  2706. $res['msg'] = '请选择收货地址';
  2707. return $res;
  2708. }
  2709. $offerRule = OfferPrice::findOne(['store_id' => get_store_id(),'is_delete' => 0]);
  2710. if (!$offerRule) {
  2711. $res['msg'] = '起送规则不存在';
  2712. return $res;
  2713. }
  2714. if ($offerRule->is_enable == 0) {
  2715. $res['msg'] = '起送规则未开启';
  2716. return $res;
  2717. }
  2718. $ruleList = Json::decode($offerRule->detail);
  2719. $res['total_price'] = $offerRule->price;
  2720. if (is_array($ruleList)) {
  2721. foreach ($ruleList as $value) {
  2722. foreach ($value['province_list'] as $item) {
  2723. if (isset($item['districtAll'])) {
  2724. if ($item['id'] == $this->address['city_id']) {
  2725. $res['total_price'] = $value['offer_price'];
  2726. }
  2727. } else if (isset($item['cityAll'])){
  2728. if ($item['id'] == $this->address['province_id']) {
  2729. $res['total_price'] = $value['offer_price'];
  2730. }
  2731. } else {
  2732. if ($item['id'] == $this->address['district_id']) {
  2733. $res['total_price'] = $value['offer_price'];
  2734. }
  2735. }
  2736. }
  2737. }
  2738. }
  2739. if ($mch['total_price'] >= $res['total_price']) {
  2740. $res['is_allowed'] = 0;
  2741. } else {
  2742. $res['is_allowed'] = 1;
  2743. }
  2744. $value = round($res['total_price'] - $mch['total_price'], 2);
  2745. $res['msg'] = "自营商品,还差{$value}元起送";
  2746. return $res;
  2747. }
  2748. protected function getTerritorialLimitation($mch)
  2749. {
  2750. $isArea = 0;
  2751. if ($mch['mch_id'] > 0) {
  2752. return $isArea;
  2753. }
  2754. if ($this->address) {
  2755. $area = TerritorialLimitation::findOne([
  2756. 'store_id' => $this->store_id,
  2757. 'is_delete' => 0,
  2758. 'is_enable' => 1,
  2759. ]);
  2760. if ($area) {
  2761. $city_id = []; //限制的地区ID
  2762. $detail = json_decode($area->detail);
  2763. if (!is_array($detail)) {
  2764. $detail = [];
  2765. }
  2766. foreach ($detail as $key => $value) {
  2767. foreach ($value->province_list as $key2 => $value2) {
  2768. $city_id[] = $value2->id;
  2769. }
  2770. }
  2771. $addressArr = [
  2772. $this->address['province_id'],
  2773. $this->address['city_id'],
  2774. $this->address['district_id']
  2775. ];
  2776. $addressArray = array_intersect($addressArr, $city_id);
  2777. if (empty($addressArray)) {
  2778. $isArea = 1;
  2779. }
  2780. }
  2781. }
  2782. return $isArea;
  2783. }
  2784. // 包邮规则
  2785. protected function getFreeDeliveryRules($mch, $expressPrice, $mchTotalPrice)
  2786. {
  2787. if ($expressPrice == 0) {
  2788. // return $expressPrice;
  2789. return ['expressPrice' => $expressPrice, 'diff' => 0];
  2790. }
  2791. $freeDeliveryPrice = 0;
  2792. if ($mch['mch_id'] == 0) {
  2793. $free = FreeDeliveryRules::find()->where(['store_id' => $this->store_id ?? get_store_id(), 'is_delete' => 0, 'mch_id' => 0])->asArray()->all();
  2794. foreach ($free as $k => $v) {
  2795. $city = json_decode($v['city'], true);
  2796. foreach ($city as $v1) {
  2797. if ($this->address['district_id'] == $v1['id'] && $mch['total_price'] >= $v['price']) {
  2798. $expressPrice = 0;
  2799. break;
  2800. }
  2801. if ($this->address['district_id'] == $v1['id']) {
  2802. $freeDeliveryPrice = max($freeDeliveryPrice, $v['price']);
  2803. }
  2804. }
  2805. }
  2806. } else {
  2807. $free = FreeDeliveryRules::find()->where(['store_id' => $this->store_id ?? get_store_id(), 'mch_id' => $mch['mch_id'], 'is_delete' => 0])->asArray()->all();
  2808. foreach ($free as $k => $v) {
  2809. $city = json_decode($v['city'], true);
  2810. foreach ($city as $v1) {
  2811. if ($this->address['district_id'] == $v1['id'] && $mch['total_price'] >= $v['price']) {
  2812. $expressPrice = 0;
  2813. break;
  2814. }
  2815. }
  2816. }
  2817. }
  2818. $diff = 0;
  2819. // echo $mchTotalPrice;die;
  2820. if ($freeDeliveryPrice > 0) {
  2821. $diff = $freeDeliveryPrice - $mchTotalPrice;
  2822. }
  2823. if ($expressPrice > 0) {
  2824. return ['expressPrice' => $expressPrice, 'diff' => $diff];
  2825. } else {
  2826. return ['expressPrice' => $expressPrice, 'diff' => 0];
  2827. }
  2828. }
  2829. // 获取用户填写的自定义表单
  2830. protected function getForm(&$form)
  2831. {
  2832. if ($form['is_form'] == 1) {
  2833. $formList = &$form['list'];
  2834. foreach ($formList as $index => $value) {
  2835. if ($value['required'] == 1) {
  2836. if (in_array($value['type'], ['radio', 'checkbox'])) {
  2837. $is_true = false;
  2838. foreach ($value['default_list'] as $k => $v) {
  2839. if ($v['checked'] == true) {
  2840. $is_true = true;
  2841. }
  2842. }
  2843. if (!$is_true) {
  2844. return [
  2845. 'code' => 1,
  2846. 'msg' => '请填写' . $form['name'] . ',加“*”为必填项',
  2847. 'name' => $value['name']
  2848. ];
  2849. }
  2850. } else {
  2851. if (empty($value['default']) && strlen($value['default']) == 0) {
  2852. return [
  2853. 'code' => 1,
  2854. 'msg' => '请填写' . $form['name'] . ',加“*”为必填项',
  2855. 'name' => $value['name']
  2856. ];
  2857. }
  2858. }
  2859. }
  2860. if ($value['type'] == 'checkbox') {
  2861. $formList[$index]['default'] = is_array($value['default']) ? implode(',', $value['default']) : $value['default'];
  2862. }
  2863. }
  2864. }
  2865. return $form;
  2866. }
  2867. protected function goodsCardList()
  2868. {
  2869. $list = [];
  2870. foreach ($this->mch_list as $mch) {
  2871. if($mch['mch_id'] == 0) {
  2872. foreach ($mch['goods_list'] as $goods) {
  2873. if (!empty($goods['goods_list'])) {
  2874. foreach ($goods['goods_list'] as $val) {
  2875. if(!$val['goods_card_list']) {
  2876. $val['goods_card_list'] = [];
  2877. }
  2878. $list = array_merge($list, $val['goods_card_list']);
  2879. }
  2880. }
  2881. }
  2882. }
  2883. }
  2884. return $list;
  2885. }
  2886. /**
  2887. * @param $goods
  2888. * @param $type
  2889. */
  2890. public function bookCheckGoodsNum($goods, $type)
  2891. {
  2892. // 酒店预约
  2893. if ($type == 1) {
  2894. // $date_book = GoodsBook::findOne(['goods_id' => $goods['id']])->date_book;
  2895. // $date_book = Json::decode($date_book);
  2896. // if (!$date_book) {
  2897. // return [
  2898. // 'code' => 1,
  2899. // 'msg' => '数据异常'
  2900. // ];
  2901. // }
  2902. // $data_config = array_combine(array_column($date_book, 'date'), array_column($date_book, 'num'));
  2903. //
  2904. // foreach ($goods['book'] as $value) {
  2905. // if ($data_config[$value['date']] < $goods['num']) {
  2906. // return [
  2907. // 'code' => 1,
  2908. // 'msg' => '选中日期' . $value['date'] . '内暂无房源'
  2909. // ];
  2910. // }
  2911. // }
  2912. }
  2913. // 服务预约
  2914. if ($type == 2) {
  2915. $service_book = GoodsBook::findOne(['goods_id' => $goods['id']])->service_book;
  2916. $service_book = Json::decode($service_book);
  2917. if (!$service_book) {
  2918. return [
  2919. 'code' => 1,
  2920. 'msg' => '数据异常'
  2921. ];
  2922. }
  2923. $date_data = $this->getDateByInterval(7);
  2924. $count = 0;
  2925. $new_arr = [
  2926. 'data' => []
  2927. ];
  2928. $order = Order::find()->alias('o')
  2929. ->leftJoin(['od' => OrderDetail::tableName()], 'o.id = od.order_id')
  2930. ->where(['o.trade_status' => [0, 2, 3], 'o.is_delete' => 0, 'o.order_type' => 2, 'goods_id' => $goods['id']])
  2931. ->andWhere(['>', 'o.created_at', strtotime(date("Y-m-d"))])
  2932. ->select('od.attr, od.num')->asArray()->all();
  2933. foreach ($date_data as $index => $datum) {
  2934. $new_arr['data'][$index]['date'] = $datum;
  2935. $new_arr['data'][$index]['time'] = $service_book['data'][0]['time'];
  2936. }
  2937. if (!$new_arr) {
  2938. return [
  2939. 'code' => 1,
  2940. 'msg' => '数据异常'
  2941. ];
  2942. }
  2943. $service_book = $new_arr['data'];
  2944. $service_book_date = array_column($service_book, NULL, 'date');
  2945. $service_book_time = $service_book_date[$goods['service']['date']]['time'];
  2946. $num = 0;
  2947. $price = 0;
  2948. foreach ($order as $item) {
  2949. $item['attr'] = json_decode($item['attr'], true);
  2950. if ($item['attr']['date'] === $goods['service']['date']) {
  2951. if ($goods['service']['time'] === $item['attr']['time']) {
  2952. $num += $item['num'];
  2953. }
  2954. }
  2955. }
  2956. foreach ($service_book_time as $m) {
  2957. foreach ($m['times'] as $n) {
  2958. if ($n['time'] == $goods['service']['time']) {
  2959. if (($goods['num'] + $num) > $n['num']) {
  2960. return [
  2961. 'code' => 1,
  2962. 'msg' => $n['time'] . '时间段内暂不可预约'
  2963. ];
  2964. }
  2965. }
  2966. }
  2967. }
  2968. }
  2969. return [
  2970. 'code' => 0,
  2971. 'msg' => 'success',
  2972. 'data' => [
  2973. 'price' => $price
  2974. ]
  2975. ];
  2976. }
  2977. /**
  2978. * 计算初始价格
  2979. * @param $order_id
  2980. * @return array
  2981. */
  2982. public static function findPrice($order_id)
  2983. {
  2984. $order = Order::findOne($order_id);
  2985. $order_detail = OrderDetail::find()->where(['order_id' => $order_id])->asArray()->all();
  2986. $original_price = 0;
  2987. $md_price = 0;
  2988. foreach ($order_detail as $detail) {
  2989. $goods = Goods::findOne($detail['goods_id']);
  2990. if ($goods->use_attr > 0) {
  2991. $attrs = Json::decode($goods->attr);
  2992. // 当前选择的规格
  2993. $attrIdArr = [];
  2994. foreach (Json::decode($detail['attr']) as $attrListItem) {
  2995. $attrIdArr[] = $attrListItem['attr_id'];
  2996. }
  2997. foreach ($attrs as $attr) {
  2998. $attrIds = [];
  2999. foreach ($attr['attr_list'] as $item) {
  3000. $attrIds[] = $item['attr_id'];
  3001. }
  3002. sort($attrIds);
  3003. sort($attrIdArr);
  3004. // 找出当前规格信息
  3005. if (implode($attrIds) === implode($attrIdArr)) {
  3006. $attr_price = $attr['price'];
  3007. if (intval($detail['is_level']) && $order->discount) {
  3008. $attr_price = bcdiv(bcmul($attr_price, $order->discount, 2), 10, 2);
  3009. }
  3010. $original_price += $attr_price;
  3011. }
  3012. }
  3013. } else {
  3014. $goods_price = $goods->price;
  3015. if (intval($detail['is_level']) && $order->discount) {
  3016. $goods_price = bcdiv(bcmul($goods_price, $order->discount, 2), 10, 2);
  3017. }
  3018. $original_price += $goods_price;
  3019. }
  3020. }
  3021. foreach ($order_detail as $detail) {
  3022. $md_goods = MdGoods::findOne(['goods_id' => $detail['goods_id'], 'md_id' => get_md_id()]);
  3023. $goods = Goods::findOne($detail['goods_id']);
  3024. $goods_attr = $goods->attr;
  3025. if ($md_goods) {
  3026. $goods_attr = $md_goods->attr;
  3027. }
  3028. if ($goods->use_attr == 1) {
  3029. $attrs = Json::decode($goods_attr);
  3030. // 当前选择的规格
  3031. $attrIdArr = [];
  3032. foreach (Json::decode($detail['attr']) as $attrListItem) {
  3033. $attrIdArr[] = $attrListItem['attr_id'];
  3034. }
  3035. foreach ($attrs as $attr) {
  3036. $attrIds = [];
  3037. foreach ($attr['attr_list'] as $item) {
  3038. $attrIds[] = $item['attr_id'];
  3039. }
  3040. sort($attrIds);
  3041. sort($attrIdArr);
  3042. // 找出当前规格信息
  3043. if (implode($attrIds) === implode($attrIdArr)) {
  3044. $attr_price = $attr['price'];
  3045. if (intval($detail['is_level']) && $order->discount) {
  3046. $attr_price = bcdiv(bcmul($attr_price, $order->discount, 2), 10, 2);
  3047. }
  3048. $md_price += $attr_price;
  3049. }
  3050. }
  3051. } else {
  3052. if ($md_goods) {
  3053. $md_goods_price = $md_goods->price;
  3054. } else {
  3055. $md_goods_price = $goods->price;
  3056. }
  3057. if (intval($detail['is_level']) && $order->discount) {
  3058. $md_goods_price = bcdiv(bcmul($md_goods_price, $order->discount, 2), 10, 2);
  3059. }
  3060. $md_price += $md_goods_price;
  3061. }
  3062. }
  3063. return [
  3064. 'original_price' => $original_price > 0 ? $original_price : $md_price,
  3065. 'md_price' => $md_price
  3066. ];
  3067. }
  3068. public function getLeaguePrice($mchList)
  3069. {
  3070. //计算联盟券
  3071. $take_price = 0;
  3072. $send_price = 0;
  3073. // $send_profit_model = Option::findOne(['name' => 'store_send_profit']);//平台让利比例
  3074. // $this_store_send_profit_model= Option::findOne(['name' => 'store_this_profit','store_id' => get_store_id()]);
  3075. // if($this_store_send_profit_model->value > 0){
  3076. // $basic_send_profit = $this_store_send_profit_model->value;
  3077. // }else{
  3078. // $basic_send_profit = $send_profit_model->value;
  3079. // }
  3080. foreach ($mchList as &$arr) {
  3081. $goods = Goods::findOne($arr['goods_id']);
  3082. //TODO 新的
  3083. //计算返利
  3084. $send_price += floatval($goods->goods_send_profit * $arr['price'] * 0.01 * $arr['num']);
  3085. $take_price += floatval($goods->goods_take_price * $arr['price'] * 0.01 * $arr['num']);
  3086. }
  3087. $user = User::findOne(get_user_id());
  3088. $user_league_price = 0;
  3089. $saas_user = SaasUser::findOne(['mobile' => $user->binding]);
  3090. if($saas_user){
  3091. $user_league_price = $saas_user->league_price;
  3092. }
  3093. if($take_price > $user_league_price){
  3094. $take_price = $user_league_price;
  3095. }
  3096. $show_saas_alliance_coupon = true;
  3097. if (\Yii::$app->prod_is_dandianpu()) {
  3098. $send_price = 0;
  3099. $take_price = 0;
  3100. $show_saas_alliance_coupon = false;
  3101. }
  3102. return [$send_price, $take_price, $show_saas_alliance_coupon, $user_league_price];
  3103. }
  3104. public function getDateByInterval(int $num) :array
  3105. {
  3106. //var_dump($st, $et);die;
  3107. $returnData = [];
  3108. $i = 0;
  3109. do {
  3110. $temp = date('Y-m-d', strtotime('+' . $i . ' day', strtotime(date('Y-m-d'))));
  3111. $returnData[] = $temp;
  3112. $i++;
  3113. } while ($i < $num);
  3114. return $returnData;
  3115. }
  3116. //判断是否需为代理配送且要上门安装
  3117. public function goodsIsInstall($goods_id)
  3118. {
  3119. try {
  3120. $goods = Goods::findOne($goods_id);
  3121. if ($goods->cloud_goods_id <= 0) {
  3122. return 2;
  3123. }
  3124. $goods_url = "/goods/getAttrParams";
  3125. $param = [
  3126. 'id' => $goods->cloud_goods_id
  3127. ];
  3128. //请求接口
  3129. $domain = (new OptionSetting)->getCloudDomainName();
  3130. $goodsInfo = cloud_post($domain . $goods_url, $param);
  3131. $goodsInfo = json_decode($goodsInfo, true);
  3132. if ((int)$goodsInfo['code'] === 0) {
  3133. $goodsInfo = $goodsInfo['data'];
  3134. //需要安装
  3135. if ((int)$goodsInfo['send_type'] === 3 && (int)$goodsInfo['is_need_install'] === 1) {
  3136. return 1;
  3137. }
  3138. //不需要安装
  3139. if ((int)$goodsInfo['send_type'] === 3) {
  3140. return 3;
  3141. }
  3142. }
  3143. return 2;
  3144. } catch (\Exception $e) {
  3145. return 2;
  3146. }
  3147. }
  3148. //判断是否存在代理
  3149. public function goodsIsGoodsAgent($address, $goods_id, $cloud_goods_id = 0)
  3150. {
  3151. try {
  3152. if (empty($address) || !is_array($address)) {
  3153. throw new \Exception('缺少地址信息');
  3154. }
  3155. if (empty($cloud_goods_id)) {
  3156. $goods = Goods::findOne(['id' => $goods_id, 'is_delete' => 0]);
  3157. if ((!empty($goods) && empty($goods->cloud_goods_id) || empty($goods) )) {
  3158. return [
  3159. 'code' => 0,
  3160. 'msg' => '非云仓商品'
  3161. ];
  3162. }
  3163. $cloud_goods_id = $goods->cloud_goods_id;
  3164. }
  3165. $goods_agent_admin = AgentGoodsBindGoods::find()->where(['cloud_goods_id' => $cloud_goods_id, 'status' => 1, 'is_delete' => 0])
  3166. ->select('goods_agent_admin_id')->column();
  3167. $where = [
  3168. 'province_id' => $address['province_id'],
  3169. 'type' => 'goods_agent',
  3170. 'is_delete' => 0,
  3171. 'id' => $goods_agent_admin
  3172. ];
  3173. $admin = Admin::findOne(array_merge(
  3174. [
  3175. 'area_level' => 1,
  3176. 'city_id' => $address['city_id'],
  3177. 'district_id' => $address['district_id'],
  3178. ], $where));
  3179. if (!empty($admin)) {
  3180. return [
  3181. 'code' => 0,
  3182. 'msg' => 'success',
  3183. 'data' => $admin
  3184. ];
  3185. }
  3186. $admin = Admin::findOne(array_merge(
  3187. [
  3188. 'area_level' => 2,
  3189. 'city_id' => $address['city_id'],
  3190. ], $where));
  3191. if (!empty($admin)) {
  3192. return [
  3193. 'code' => 0,
  3194. 'msg' => 'success',
  3195. 'data' => $admin
  3196. ];
  3197. }
  3198. $admin = Admin::findOne(array_merge(
  3199. [
  3200. 'area_level' => 3,
  3201. ], $where));
  3202. if (!empty($admin)) {
  3203. return [
  3204. 'code' => 0,
  3205. 'msg' => 'success',
  3206. 'data' => $admin
  3207. ];
  3208. }
  3209. return [
  3210. 'code' => 1,
  3211. 'msg' => '该区域未存在产品代理,无法下单'
  3212. ];
  3213. } catch (\Exception $e) {
  3214. return [
  3215. 'code' => 1,
  3216. 'msg' => $e->getMessage()
  3217. ];
  3218. }
  3219. }
  3220. }