| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073 |
- <?php
- namespace addons\QiJuhe\common\service;
- use addons\QiJuhe\common\enums\OrderEnum;
- use addons\QiJuhe\common\enums\QiJuheEnum;
- use addons\QiJuhe\common\models\ExpressModel;
- use addons\QiJuhe\common\models\GoodsModel;
- use addons\QiJuhe\common\models\GoodsSkuModel;
- use addons\QiJuhe\common\models\MallGoodsModel;
- use addons\QiJuhe\common\models\MallOrderModel;
- use addons\QiJuhe\common\models\OrderModel;
- use addons\QiJuhe\common\models\SupplysModel;
- use common\enums\OrderStatusEnum;
- use common\enums\ShippingTypeEnum;
- use common\enums\StatusEnum;
- use common\enums\AddonsEnum;
- use common\logic\order\BaseOrderForm;
- use common\models\order\OrderDetail;
- use common\models\order\OrderExpress;
- use common\models\user\UserAddress;
- use addons\CardCoupons\common\models\CardCouponsGift;
- use common\models\goods\Goods;
- use Exception;
- use Yii;
- use yii\base\Model;
- use yii\data\Pagination;
- use yii\helpers\Json;
- class OrderService extends Model
- {
- /**
- * 收货人名称最低长度
- */
- public const NAME_MIN_LENGTH = 2;
- /**
- * 商城ID
- *
- * @var integer
- */
- public $mall_id;
- public $form;
- public function __construct($config)
- {
- parent::__construct($config);
- }
- /**
- * 获取列表
- *
- * @param array $params
- * @return void
- */
- public function getOrderList($params)
- {
- $limit = $params['limit'] ?? 20;
- $page = $params['page'] ?? 1;
- $model = OrderModel::find();
- $model->with(['mallOrder' => function ($query) {
- return $query->select('id, receiver_name as consignee, mobile, goods_price, pay_time, pay_money, status as order_status, order_source');
- }, 'mallOrderDetail' => function ($query) {
- return $query->select('order_id, num, goods_name, pic_url, goods_attr_name');
- }]);
- $model->andWhere(['mall_id' => $this->mall_id]);
- if (!empty($params['order_no'])) {
- $ids = MallOrderModel::find()->where(['mall_id' => $this->mall_id])->andWhere(['like', 'order_no', $params['order_no']])->select('id')->column();
- $model->andWhere(['in', 'order_id', $ids]);
- }
- if (!empty($params['user_id'])) {
- $ids = MallOrderModel::find()->where(['mall_id' => $this->mall_id])->andWhere(['=', 'user_id', $params['user_id']])->select('id')->column();
- $model->andWhere(['in', 'order_id', $ids]);
- }
- if (!empty($params['search_words'])) {
- $ids = OrderDetail::find()->where(['mall_id' => $this->mall_id])->andWhere(['like', 'goods_name', $params['search_words']])->select('order_id')->column();
- $model->andWhere(['in', 'order_id', $ids]);
- }
- if (!empty($params['push_status']) && $params['push_status'] > 0) {
- $model->andWhere(['=', 'status', $params['push_status']]);
- }
- if (!empty($params['order_status']) && $params['order_status'] > 0) {
- $ids = MallOrderModel::find()->where(['mall_id' => $this->mall_id])->andWhere(['=', 'status', $params['order_status']])->select('id')->column();
- $model->andWhere(['in', 'order_id', $ids]);
- }
- if (!empty($params['source']) && $params['source'] > 0) {
- $model->andWhere(['=', 'source', $params['source']]);
- }
- if (!empty($params['name'])) {
- $ids = MallOrderModel::find()->where(['mall_id' => $this->mall_id])->andWhere(['like', 'receiver_name', $params['name']])->select('id')->column();
- $model->andWhere(['in', 'order_id', $ids]);
- }
- if (!empty($params['supply_id'])) {
- $model->andWhere(['supply_id'=>$params['supply_id']]);
- }
- $pagination = new Pagination(['totalCount' => $model->count(), 'pageSize' => $limit]);
- $model->limit($pagination->limit)->offset($pagination->offset);
- $list = $model->orderBy('created_at desc')
- ->asArray()
- ->all();
- $model = SupplysModel::find()->select('id,app_name')->where(['mall_id' => $this->mall_id]);
- $supply_list = $model->indexBy('id')->asArray()->all();
- foreach ($list as &$item) {
- if(!empty($item['order_detail_id'])){
- $item['mallOrderDetail'] = OrderDetail::find()->where(['id'=>$item['order_detail_id']])->select('order_id, num, goods_name, pic_url, goods_attr_name')->asArray()->one();
- }
- // 推送状态
- $item['status_text'] = OrderEnum::getValue($item['status']) ?? '未知';
- $item['supply_name'] = isset($supply_list[$item['supply_id']]) ? $supply_list[$item['supply_id']]['app_name'] : "";
- }
- $data['list'] = $list;
- $data['page_count'] = $pagination->pageCount;
- $data['current_page'] = $page + 1;
- return $data;
- }
- /**
- * 聚合供应链生成订单前置检测
- *
- * @param BaseOrderForm $form 商城订单数据
- * @param booleam $is_new_record 是否创建订单
- * @return void
- */
- public function createBeforeCheck($form, $is_new_record = false)
- {
- $total_price = 0;
- $order_goods = $form->order_goods;
- // 获取购买的AttrId
- foreach ($order_goods as $goods) {
- $goods_id = $goods['goods_id'];
- $attr_id = $goods['goods_attr_id'];
- // 数量
- $num = $goods['num'];
- // 总价
- $total_price += $goods['goods_price'];
- }
- $sku = GoodsSkuModel::getSku($goods_id, $attr_id);
- $sku_id = $sku->sku_id;
- if (empty($sku_id)) {
- throw new Exception('下单商品SKU不存在,请重新下单');
- }
- // 获取用户收货地址信息
- if (empty($extra['address'])) {
- $address = UserAddress::getOne([['id' => $form['address_id']], ['user_id' => $form['user_id']]], true);
- $extra['address'] = $address;
- } else {
- $address = $extra['address'];
- }
- // 订单加上聚合供应链标识
- $group_order_goods = $form->group_order_goods;
- // 未选择地址不进行计算运费
- if (!empty($address)) {
- // 特殊地址处理
- $address = static::formatAddress($address);
- // 提交的地址
- $sub_address = [
- 'consignee' => $address['name'],
- 'phone' => $address['mobile'],
- 'province' => $address['province'],
- 'city' => $address['city'],
- 'area' => $address['district'],
- 'street' => $address['town'],
- 'description' => $address['detail'],
- ];
- // 获取运费请求参数
- $data = [
- 'spu' => [
- [
- 'sku' => $sku_id,
- 'goods_id' => $goods_id,
- 'shop_goods_id' => $sku->supply_goods_id,
- 'number' => intval($num),
- ]
- ],
- 'address' => $sub_address,
- ];
- // 收货人名称过短
- if (mb_strlen($address['name']) < static::NAME_MIN_LENGTH && $is_new_record) {
- throw new Exception('收货人名称过短');
- }
- $api = ApiService::getConnect($this->mall_id, $sku->supply_id);
- $is_valid = $api->availableCheck($data);
- if (isset($is_valid['ban']) && $is_new_record) {
- throw new Exception('下单失败,此商品不支持在当前地区销售');
- }
- // 邮费
- $freight = $api->orderBeforeCheck($data);
- if ($is_new_record && $freight === false) {
- throw new Exception('下单失败:' . $api->error);
- }
- if(!empty($freight['desc'])){
- throw new Exception('下单失败:'.$freight['desc']);
- }
- $freight_money = $freight['freight'] ?? 0;
- // 风控检测
- $setting = new SettingService(['mall_id' => $this->mall_id]);
- $result = $setting->checkDanger($total_price, $sku->sku_id, $num, $sku->supply_goods_id, $sku->supply_id);
- if(!$result) {
- MallGoodsModel::updateDown($this->mall_id, $goods_id);
- throw new Exception($setting->error);
- }
- // 计算邮费
- $freight = $this->getFreight($freight_money);
- $form->marketing['deduct']['shipping_fee'] = [
- 'name' => '运费',
- 'money' => $freight,
- ];
- foreach ($group_order_goods as $k => &$v) {
- if ($v['mch_order_info']) {
- // 标识
- $v['mch_order_info']['order_source'] = QiJuheEnum::PLUGIN_SIGN;
- // 邮费
- $v['mch_order_info']['shipping_type'] = ShippingTypeEnum::LOGISTICS; // 默认物流配送
- $v['mch_order_info']['shipping_money'] = $freight;
- // 收货地址
- $v['mch_order_info']['province'] = $address['province_id'];
- $v['mch_order_info']['city'] = $address['city_id'];
- $v['mch_order_info']['area'] = $address['district_id'];
- $v['mch_order_info']['town'] = $address['town_id'];
- $v['mch_order_info']['region_name'] = $address['province'] .' '. $address['city'] .' '. $address['district'].' '.$address['town'];
- $v['mch_order_info']['address'] = $address['detail'];
- $v['mch_order_info']['receiver_name'] = $address['name'];
- $v['mch_order_info']['mobile'] = $address['mobile'];
- }
- }
- // 计算总额
- $form['total_pay_money'] = bcadd($form['total_pay_money'], $freight, 2);
- }
- $form->group_order_goods = $group_order_goods;
- return $form;
- }
- public function validForm(BaseOrderForm $form, $is_new_record = false)
- {
- if ($form->type == 'buy_now') {
- $order_goods = $form->order_goods;
- } else {
- $order_goods = $form->group_order_goods[QiJuheEnum::PLUGIN_SIGN]['goods'];
- }
- if (empty($order_goods)) return $form;
- // 获取用户收货地址信息
- if (empty($extra['address'])) {
- $address = UserAddress::getOne([['id' => $form['address_id']], ['user_id' => $form['user_id']]], true);
- $extra['address'] = $address;
- } else {
- $address = $extra['address'];
- }
- $spu_list = [];
- $total_prices = [];
- $total_nums = [];
- $total_sku_nums = [];
- // 获取购买的AttrId
- foreach ($order_goods as $goods) {
- if ($form->type == 'buy_now') {
- $this->valid($goods['goods_id'], $goods['goods_attr_id'], $goods['num'], $goods, $is_new_record,
- $spu_list, $total_prices, $total_nums, $total_sku_nums);
- } else {
- foreach ($goods['goods_details'] as $goods_detail) {
- $this->valid($goods_detail['goods_id'], $goods_detail['goods_attr_id'], $goods_detail['num'], $goods_detail,
- $is_new_record, $spu_list, $total_prices, $total_nums, $total_sku_nums);
- }
- }
- }
- if (empty($spu_list)) return $form;
- // 订单加上聚合供应链标识
- $group_order_goods = $form->group_order_goods;
- $free_shopping_total_amount = 0;
- $free_shopping_goods_ids = [];
- // 未选择地址不进行计算运费
- if (!empty($address)) {
- $config = (new SettingService(['mall_id' => $form->mall_id]))->getSetting();
- $rate = !empty($sell) ? $sell['sell_agreement'] : 1.5;
- $rate = 1;
- $shopping_cart_free_amount = !empty($config['shopping_cart_free_amount']) ? $config['shopping_cart_free_amount'] : 59;
- $shopping_cart_free_amount = bcmul($shopping_cart_free_amount, $rate, 2);
- $freight_amount = 0;
- $freight_amount_list = [];
- // 特殊地址处理
- $address = static::formatAddress($address);
- // 提交的地址
- $sub_address = [
- 'consignee' => $address['name'],
- 'phone' => $address['mobile'],
- 'province' => $address['province'],
- 'city' => $address['city'],
- 'area' => $address['district'],
- 'street' => $address['town'],
- 'description' => $address['detail'],
- ];
- $sell = null;
- $source_goods = [];
- foreach ($spu_list as $supply_id => $i_spu_list) {
- // 库存检测
- self::validStock($form->mall_id, $supply_id, $total_sku_nums[$supply_id]);
- foreach ($i_spu_list as $source => $spus) {
- // 获取运费请求参数
- $data = [
- 'spu' => $spus,
- 'address' => $sub_address,
- ];
- // 收货人名称过短
- if (mb_strlen($address['name']) < static::NAME_MIN_LENGTH && $is_new_record) {
- throw new Exception('收货人名称过短');
- }
- $api = ApiService::getConnect($this->mall_id, $supply_id);
- $is_valid = $api->availableCheck($data);
- if (isset($is_valid['ban']) && $is_new_record) {
- throw new Exception('下单失败,此商品不支持在当前地区销售');
- }
- // 邮费
- $freight = $api->orderBeforeCheck($data);
- if ($freight === false) {
- throw new Exception('下单失败:' . $api->error);
- }
- if(!empty($freight['desc'])){
- throw new Exception('下单失败:'.$freight['desc']);
- }
- $freight_money = $freight['freight'] ?? 0;
- // 风控检测
- $setting = new SettingService(['mall_id' => $this->mall_id]);
- foreach ($spus as $spu) {
- $result = $setting->checkDanger($total_prices[$supply_id][$source], $spu['sku'], $spu['number'], $spu['shop_goods_id'], $supply_id);
- if(!$result) {
- MallGoodsModel::updateDown($this->mall_id, $spu['goods_id']);
- throw new Exception($setting->error);
- }
- // 供应链商品
- $s_goods = GoodsModel::findOne(['goods_id' => $spu['shop_goods_id'], 'mall_id' => $form->mall_id]);
- // 最低购买量
- if ($total_nums[$supply_id][$source][$spu['shop_goods_id']] < $s_goods->min_buy_qty) {
- $l_goods = Goods::findOne(['id' => $spu['goods_id']]);
- throw new Exception("商品 {$l_goods->goods_name} 起订量 $s_goods->min_buy_qty 件起");
- }
- if ($source == QiJuheEnum::FREE_SHIPPING_SOURCE && $s_goods->source_name == QiJuheEnum::FREE_SHIPPING_SOURCE_NAME) { // 优选供应链的
- // if ($source == QiJuheEnum::FREE_SHIPPING_SOURCE) { // 优选供应链的
- // $goodsInfo = $api->goodsInfo([$spu['shop_goods_id']]);
- // if (!empty($goodsInfo[0])) {
- $free_shopping_total_amount += $total_prices[$supply_id][$source]; // 取协议价
- // $free_shopping_goods_ids[] = $spu['goods_id'];
- // }
- if (empty($sell)) {
- $supply = SupplysModel::findOne(['id' => $supply_id]);
- $sell = Json::decode(!empty($supply->sell) ? $supply->sell : '[]');
- }
- }
- // 属于哪个供应链
- if (empty($source_goods[$source]) || !in_array($spu['goods_id'], $source_goods[$source])) {
- $source_goods[$source][] = $spu['goods_id'];
- }
- }
- if (!empty($config['is_enable_shopping_cart_settle']) && !empty($free_shopping_total_amount) &&
- $free_shopping_total_amount >= $shopping_cart_free_amount) {
- $freight_money = 0; // 强制免邮
- array_push($free_shopping_goods_ids, ...array_column($spus, 'goods_id'));
- }
- $freight_amount_list[QiJuheEnum::PLUGIN_SIGN . $source] = $freight_money ? $this->getFreight($freight_money) : 0;
- // 计算邮费
- $freight_amount += $freight_money ? $this->getFreight($freight_money) : 0;
- $free_shopping_total_amount = 0;
- }
- }
- // $free_shopping_total_amount = bcmul($free_shopping_total_amount, $rate, 2);
- $form->marketing['deduct']['shipping_fee'] = [
- 'name' => '运费',
- 'money' => $freight_amount,
- ];
- if ($is_new_record) { // 请求云众的时候需要将子供应链进行拆分
- // 从这里拆单
- $t_group_order_goods = [];
- foreach ($group_order_goods as $k => $tv) {
- if (strpos($k, QiJuheEnum::PLUGIN_SIGN) === 0) {
- foreach ($tv['goods'] as $goods_id => $good) {
- foreach ($source_goods as $source => $source_good) {
- if (in_array($goods_id, $source_good)) {
- $t_k = "{$k}{$source}";
- if (empty($t_group_order_goods[$t_k])) { // 如果有优惠,那么需要怎么处理?
- $tv['mch_order_info']['pay_money'] = 0;
- $tv['mch_order_info']['goods_price'] = 0;
- $tv['mch_order_info']['original_goods_price'] = 0;
- $t_group_order_goods[$t_k] = [
- 'mch_order_info' => $tv['mch_order_info'],
- 'goods' => []
- ];
- }
- foreach ($good['goods_details'] as $goods_detail) {
- $t_group_order_goods[$t_k]['mch_order_info']['pay_money'] += (float) $goods_detail['goods_price'];
- $t_group_order_goods[$t_k]['mch_order_info']['goods_price'] += (float) $goods_detail['goods_price'];
- $t_group_order_goods[$t_k]['mch_order_info']['original_goods_price']+= $goods_detail['original_goods_price'];
- }
- $t_group_order_goods[$t_k]['goods'][$goods_id] = $good;
- }
- }
- }
- } else {
- $t_group_order_goods[$k] = $tv;
- }
- }
- $group_order_goods = $t_group_order_goods;
- }
- foreach ($group_order_goods as $k => &$v) { // 如果是创建,那么就将所有商品合为一个订单
- if (($v['mch_order_info'] && strpos($k, QiJuheEnum::PLUGIN_SIGN) === 0) || $form->type == 'buy_now') {
- // 标识
- $v['mch_order_info']['order_source'] = QiJuheEnum::PLUGIN_SIGN;
- // 邮费
- $v['mch_order_info']['shipping_type'] = ShippingTypeEnum::LOGISTICS; // 默认物流配送
- $v['mch_order_info']['shipping_money'] = $form->type == 'buy_now' ? $freight_amount : ($freight_amount_list[$k] ?? 0); // 不同运费
- // 收货地址
- $v['mch_order_info']['province'] = $address['province_id'];
- $v['mch_order_info']['city'] = $address['city_id'];
- $v['mch_order_info']['area'] = $address['district_id'];
- $v['mch_order_info']['town'] = $address['town_id'];
- $v['mch_order_info']['region_name'] = $address['province'] .' '. $address['city'] .' '. $address['district'].' '.$address['town'];
- $v['mch_order_info']['address'] = $address['detail'];
- $v['mch_order_info']['receiver_name'] = $address['name'];
- $v['mch_order_info']['mobile'] = $address['mobile'];
- if (!empty($config['is_enable_shopping_cart_settle'])) {
- $v['mch_order_info']['extra_info'] = Json::encode([
- 'mall_info' => [
- 'mall_name' => $config['shopping_cart_mall_name'],
- 'mall_logo' => $config['shopping_cart_mall_logo'],
- ]
- ]);
- foreach ($v['goods'] as $goods_id => $good) {
- // 判断是否为满包邮
- foreach ($good['goods_details'] as $dk => $detail) {
- // 判断是否需要包邮
- if (in_array($goods_id, $free_shopping_goods_ids)) {
- $free_shipping_deduct_info = ['amount' => 0, 'money' => 0, 'tips' => "满{$shopping_cart_free_amount}包邮",
- 'name' => "满{$shopping_cart_free_amount}包邮", 'ids' => $free_shopping_goods_ids];//积分抵扣信息
- if (empty($detail['marketing']['deduct_currency'])) {
- $deduct_currency = ['free_shipping' => $free_shipping_deduct_info];
- } else {
- $deduct_currency = Json::decode($detail['marketing']['deduct_currency'], true);
- $deduct_currency['free_shipping'] = $free_shipping_deduct_info;
- }
- $v['goods'][$goods_id]['goods_details'][$dk]['marketing']['deduct_currency'] = Json::encode($deduct_currency);
- }
- }
- }
- }
- }
- }
- // 计算总额
- $form['total_pay_money'] = bcadd($form['total_pay_money'], $freight_amount, 2);
- }
- $form = $form->toArray();
- $form['group_order_goods'] = array_values($group_order_goods);
- return $form;
- }
- protected function valid($goods_id, $attr_id, $num, $goods, $is_new_record, &$spu_list, &$total_prices, &$total_nums, &$total_sku_nums)
- {
- $sku = GoodsSkuModel::getSku($goods_id, $attr_id);
- if (empty($sku)) {
- throw new Exception('下单商品SKU不存在,请重新下单: ' . $attr_id);
- }
- $t_goods = GoodsModel::findOne(['goods_id' => $sku->supply_goods_id, 'mall_id' => $sku->mall_id]);
- // 总价
- if (empty($total_prices[$sku->supply_id][$t_goods->source])) $total_prices[$sku->supply_id][$t_goods->source] = 0;
- $total_prices[$sku->supply_id][$t_goods->source] += $goods['goods_price'];
- if (empty($spu_list[$sku->supply_id][$t_goods->source])) $spu_list[$sku->supply_id][$t_goods->source] = [];
- $spu_list[$sku->supply_id][$t_goods->source][] = [
- 'sku' => $sku->sku_id,
- 'goods_id' => $goods_id,
- 'shop_goods_id' => $sku->supply_goods_id,
- 'number' => intval($num),
- ];
- // 累加数量
- if (empty($total_nums[$sku->supply_id][$t_goods->source][$sku->supply_goods_id]))
- $total_nums[$sku->supply_id][$t_goods->source][$sku->supply_goods_id] = 0;
- $total_nums[$sku->supply_id][$t_goods->source][$sku->supply_goods_id] += intval($num);
- $total_sku_nums[$sku->supply_id][$sku->supply_goods_id][$sku->sku_id] = intval($num);
- }
- protected static function validStock(int $mall_id, int $supply_id, array $third_goods_ids)
- {
- $ids = array_keys($third_goods_ids);
- $api = ApiService::getConnect($mall_id, $supply_id);
- $resp = $api->goodsInfo($ids);
- if (!empty($api->error)) throw new Exception($api->error);
- if (empty($resp) || count($resp) < count($ids)) throw new Exception('商品不存在');
- foreach ($resp as $item) {
- foreach ($item['skus'] as $sku) {
- if ($third_goods_ids[$item['id']][$sku['id']] > $sku['stock']) {
- throw new Exception("{$item['title']} - {$sku['title']} 库存不足");
- }
- }
- }
- }
- public static function createOrderV2($order_id)
- {
- // 订单详情
- $order = MallOrderModel::getOrder($order_id);
- if ($order && $order->order_source != QiJuheEnum::PLUGIN_SIGN && $order->order_source != AddonsEnum::ADDONS_NAME_CARD_COUPONS) return false;
- if (!$order->pay_status == StatusEnum::ENABLED) return false;
- if (empty($order->detail)) return false;
- foreach ($order->detail as $detail) {
- if($order->order_source == AddonsEnum::ADDONS_NAME_CARD_COUPONS) {
- $goods = Goods::findOne($detail->goods_id);
- if(!$goods || $goods['goods_source'] != QiJuheEnum::PLUGIN_SIGN) continue;
- }
- // skuId
- $sku = GoodsSkuModel::getSku($detail->goods_id, $detail->goods_attr_id);
- if (empty($sku)) return false;
- // 聚合商品信息
- $supply_goods = GoodsModel::find()->where(['goods_id' => $sku->supply_goods_id])->select('goods_id, supply_id, source')->one();
- if (empty($supply_goods)) return false;
- // 以平台分类
- $supply_orders[$sku->supply_id][] = [
- 'sku' => $sku->sku_id,
- 'number' => intval($detail->num),
- 'goods_id' => $supply_goods->goods_id,
- 'source' => $supply_goods->source,
- 'order_detail_id' => $detail['id'],
- ];
- }
- if (empty($supply_orders)) return false;
- $sku_arr = [];
- $order_model_arr = [];
- foreach ($supply_orders as $supply_id => $skus) {
- // 接口
- $api = ApiService::getConnect($order->mall_id, $supply_id);
- foreach ($skus as $sku) {
- // 创建订单
- $order_model = new OrderModel();
- $order_model->supply_id = $supply_id;
- $order_model->user_id = $order->user_id;
- $order_model->order_no = $order->order_no;
- $order_model->order_id = $order_id;
- $order_model->order_detail_id = $sku['order_detail_id'];
- $order_model->goods_id = $sku['goods_id'];
- $order_model->source = strval($sku['source']);
- $order_model->mall_id = $order->mall_id;
- $order_model->sku_id = $sku['sku'];
- $order_model->created_at = $order_model->updated_at = time();
- if (!$order_model->save()) {
- throw new Exception("聚合供应链订单:{$order->order_no}生成失败");
- return false;
- }
- $order_model_arr[] = $order_model;
- // spu
- $sku_arr[] = [
- 'sku' => $sku['sku'],
- 'number' => intval($sku['number']),
- ];
- }
- }
- // 地址
- $region = explode(' ', $order->region_name);
- $address = [
- 'province' => $region[0],
- 'city' => $region[1],
- 'district' => $region[2],
- 'town' => $region[3],
- ];
- // 格式化地址
- $address = static::formatAddress($address);
- // 提交的地址
- $sub_address = [
- 'consignee' => $order->receiver_name,
- 'phone' => $order->mobile,
- 'province' => $address['province'],
- 'city' => $address['city'],
- 'area' => $address['district'],
- 'street' => $address['town'],
- 'description' => $order->address,
- ];
- $data = [
- 'order_sn' => $order->order_no,
- 'spu' => $sku_arr,
- 'address' => $sub_address,
- 'remark' => !empty($order->remark) ? $order->remark : '',
- ];
- // 收货人名称过短
- if (mb_strlen($order->receiver_name) < static::NAME_MIN_LENGTH) {
- throw new Exception('收货人名称过短');
- }
- // 保留api提交数据
- OrderModel::updateAll(['order_json'=>Json::encode($data)],['order_no'=>$order->order_no]);
- // 推送订单
- $result = $api->createOreder($data);
- if (!$result) {
- // 修改状态
- foreach($order_model_arr as $order_model){
- $order_model->pushFail($api->error);
- }
- // 队列执行
- // Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, [
- // 'mall_id' => $order->mall_id,
- // ], OrderFailListener::class, 'async_handle');
- throw new Exception("聚合供应链订单:{$order->order_no}推送失败");
- }
- // 推送成功修改状态
- // $order_data = $api->getOrderInfo($order->order_no);
- foreach($order_model_arr as $order_model){
- $res = $order_model->payOk('', $result);
- if (!$res) {
- throw new Exception("聚合供应链订单:{$order->order_no}修改成功状态失败");
- }
- }
- }
- /**
- * 创建聚合订单
- *
- * @param integer $order_id 订单ID
- * @param string $order_sn 订单编号
- * @return void
- */
- public static function createOrder($order_id/* , $order_no */)
- {
- // 订单详情
- $order = MallOrderModel::getOrder($order_id);
- if ($order && $order->order_source != QiJuheEnum::PLUGIN_SIGN && $order->order_source != AddonsEnum::ADDONS_NAME_CARD_COUPONS) return false;
- if (!$order->pay_status == StatusEnum::ENABLED) return false;
- if (empty($order->detail)) return false;
- foreach ($order->detail as $detail) {
- if($order->order_source == AddonsEnum::ADDONS_NAME_CARD_COUPONS) {
- $goods = Goods::findOne($detail->goods_id);
- if(!$goods || $goods['goods_source'] != QiJuheEnum::PLUGIN_SIGN) continue;
- }
- // skuId
- $sku = GoodsSkuModel::getSku($detail->goods_id, $detail->goods_attr_id);
- if (empty($sku)) return false;
- // 聚合商品信息
- $supply_goods = GoodsModel::find()->where(['goods_id' => $sku->supply_goods_id])->select('goods_id, supply_id, source')->one();
- if (empty($supply_goods)) return false;
- // 以平台分类
- $supply_orders[$sku->supply_id][] = [
- 'sku' => $sku->sku_id,
- 'number' => intval($detail->num),
- 'goods_id' => $supply_goods->goods_id,
- 'source' => $supply_goods->source,
- 'order_detail_id' => $detail['id'],
- ];
- }
- if (empty($supply_orders)) return false;
- foreach ($supply_orders as $supply_id => $skus) {
- // 接口
- $api = ApiService::getConnect($order->mall_id, $supply_id);
- $order_model_arr = [];
- $sku_arr = [];
- foreach ($skus as $sku) {
- // 创建订单
- $order_model = new OrderModel();
- $order_model->supply_id = $supply_id;
- $order_model->user_id = $order->user_id;
- $order_model->order_no = $order->order_no;
- $order_model->order_id = $order_id;
- $order_model->order_detail_id = $sku['order_detail_id'];
- $order_model->goods_id = $sku['goods_id'];
- $order_model->source = strval($sku['source']);
- $order_model->mall_id = $order->mall_id;
- $order_model->sku_id = $sku['sku'];
- $order_model->created_at = $order_model->updated_at = time();
- if (!$order_model->save()) {
- throw new Exception("聚合供应链订单:{$order->order_no}生成失败");
- return false;
- }
- $order_model_arr[] = $order_model;
- // spu
- $sku_arr[] = [
- 'sku' => $sku['sku'],
- 'number' => intval($sku['number']),
- ];
- }
- // 地址
- $region = explode(' ', $order->region_name);
- $address = [
- 'province' => $region[0],
- 'city' => $region[1],
- 'district' => $region[2],
- 'town' => $region[3],
- ];
- // 格式化地址
- $address = static::formatAddress($address);
- // 提交的地址
- $sub_address = [
- 'consignee' => $order->receiver_name,
- 'phone' => $order->mobile,
- 'province' => $address['province'],
- 'city' => $address['city'],
- 'area' => $address['district'],
- 'street' => $address['town'],
- 'description' => $order->address,
- ];
- $data = [
- 'order_sn' => $order->order_no,
- 'spu' => $sku_arr,
- 'address' => $sub_address,
- ];
- // 收货人名称过短
- if (mb_strlen($order->receiver_name) < static::NAME_MIN_LENGTH) {
- throw new Exception('收货人名称过短');
- }
- // 保留api提交数据
- OrderModel::updateAll(['order_json'=>Json::encode($data)],['order_no'=>$order->order_no]);
- // 推送订单
- $result = $api->createOreder($data);
- if (!$result) {
- // 修改状态
- foreach($order_model_arr as $order_model){
- $order_model->pushFail($api->error);
- }
- // 队列执行
- // Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, [
- // 'mall_id' => $order->mall_id,
- // ], OrderFailListener::class, 'async_handle');
- throw new Exception("聚合供应链订单:{$order->order_no}推送失败");
- }
- // 推送成功修改状态
- // $order_data = $api->getOrderInfo($order->order_no);
- foreach($order_model_arr as $order_model){
- $res = $order_model->payOk('', $result);
- if (!$res) {
- throw new Exception("聚合供应链订单:{$order->order_no}修改成功状态失败");
- }
- }
- }
- }
- /**
- * 聚合平台交易完成(淘宝 jd确认收货 订单完成了)
- * 目前不需要修改系统订单状态,使用系统自带的收货完成
- *
- * @param string $order_no
- * @return void
- */
- public function orderSuccess($order_no)
- {
- $juhe_order = OrderModel::findOne(['order_no' => $order_no, 'mall_id' => $this->mall_id]);
- if(empty($juhe_order)) {
- }
- $mall_order = MallOrderModel::findOne(['order_no' => $order_no, 'mall_id' => $this->mall_id]);
- if(empty($sys_order)) {
- }
- }
- /**
- * 用户确认收货
- *
- * @param string $order_no
- * @return void
- */
- public static function orderDelivered($order_id)
- {
- $juhe_order = OrderModel::find()->where(['order_id' => $order_id])->select('id, mall_id, supply_id, order_data')->one();
- if (empty($juhe_order)) {
- return false;
- }
- $data = Json::decode($juhe_order->order_data);
- if (empty($data['Orders'])) {
- return false;
- }
- $api = ApiService::getConnect($juhe_order->mall_id, $juhe_order->supply_id);
- foreach ($data['Orders'] as $order) {
- $res = $api->orderReceive($order['id']);
- }
- }
- /**
- * 商家发货
- *
- * @param string $order_no
- * @param integer $sku
- * @return void
- */
- public function orderDelivery($order_no, $sku)
- {
- $juhe_order = OrderModel::findOne(['order_no' => $order_no, 'mall_id' => $this->mall_id]);
- if(empty($juhe_order)) {
- throw new Exception("聚合供应链订单{$order_no}不存在");
- }
- $mall_order = MallOrderModel::find()->where(['order_no' => $order_no, 'mall_id' => $this->mall_id])->select('id')->one();
- if(empty($mall_order)) {
- throw new Exception("商城订单{$order_no}不存在");
- }
- $res = MallOrderModel::delivery(['mall_id' => $this->mall_id, 'id' => $mall_order->id]);
- if ($res === false) {
- throw new Exception("商城订单商家发货{$order_no}" . MallOrderModel::$static_error);
- }
- }
- /**
- * 订单转换成普通订单
- *
- * @param integer $id
- * @return boolean
- */
- public function changeOrder(int $id)
- {
- $order = OrderModel::findOne(['id' => $id, 'mall_id' => $this->mall_id]);
- if (empty($order)) return $this->error('订单不存在');
- /**
- * @var MallOrderModel|null
- */
- $mall_order = $order->mallOrder;
- if (empty($mall_order)) return $this->error('商城订单不存在');
- return $mall_order->changeOrder();
- }
- /**
- * 批量补单
- *
- * @param array $ids
- * @return void
- */
- public function patchOrder(array $ids)
- {
- $error = [];
- $success = [];
- try {
- $juhe_order = OrderModel::find()->with('mallOrder')->where(['id' => $ids])->all();
- if (empty($juhe_order)) {
- throw new Exception('订单不存在');
- }
- foreach ($juhe_order as $order) {
- // 订单状态
- if (!in_array($order->status, [OrderEnum::PUSH_NOT, OrderEnum::PUSH_FAIL])) {
- $error[] = [
- 'order_no' => $order->order_no,
- 'msg' => '订单状态不正常',
- ];
- continue;
- }
- // 不是待发货状态,不允许补单
- if ($order->mallOrder->status != OrderStatusEnum::PAY || $order->mallOrder->is_feedback != OrderStatusEnum::NOT_FEEDBACK) {
- $error[] = [
- 'order_no' => $order->order_no,
- 'msg' => '订单未付款或者正在售后~',
- ];
- continue;
- }
- $api = ApiService::getConnect($order->mall_id, $order->supply_id);
- // 接口没有批量补单
- $result = $api->createOreder(Json::decode($order->order_json));
- if (!$result) {
- $order->pushFail($api->error);
- $error[] = [
- 'order_no' => $order->order_no,
- 'msg' => $order->order_no.'【'.$api->error.'】',
- ];
- continue;
- }
- // 补单成功
- $order->payOk('', $result);
- $success[] = [
- 'order_no' => $order->order_no,
- 'msg' => '成功',
- ];
- }
- } catch (Exception $e) {
- $error[] = $e->getMessage();
- }
- return compact('success', 'error');
- }
- /**
- * 计算聚合供应链邮费
- *
- * @param array $juhe_money 聚合供应链返回邮费数据
- * @return mixed
- */
- protected function getFreight($money)
- {
- if($money <= 0) return 0;
- return bcdiv($money, 100, 2);
- }
- /**
- * 中台发货,更新物流信息
- * @param $order_sn
- */
- public function updateLogistic($order_sn)
- {
- $orders = OrderModel::find()
- ->where(['order_no'=>$order_sn])
- // ->with(['mallOrder' => function ($q) {
- // return $q->select('id')->with(['detail' => function ($q) {
- // return $q->select('id, order_id,goods_id');
- // }]);
- // }])
- ->select('id, mall_id, order_no, order_id, supply_id,goods_id,order_detail_id')
- ->all();
- if(empty($orders)) return true;
- $order_list = [];
- foreach($orders as $order_item){
- $order_list[$order_item['supply_id']][] = $order_item;
- }
- foreach($order_list as $supply_id => $orders){
- $this->mall_id = $orders[0]['mall_id'];
- // 获取物流信息
- $api = ApiService::getConnect(['mall_id' => $this->mall_id, 'supply_id' => $supply_id]);
- $logistic = $api->orderLogistic($order_sn);
- try {
- if(empty($logistic)) throw new \Exception("获取物流信息异常");
- foreach($logistic as $express_order){
- $params = $this->getExpressParams($orders, $express_order);
- \Yii::$app->custom->logs('物流信息: ' . json_encode($params));
- $res = OrderExpress::delivery($params);
- if ($res === false) {
- // 这里选择不抛出错误(因为如果有多个发货,假设第一个已经发货就会进入来这里,抛出错误后导致其他的也发不了)
- $errorMsg = '商家已发货:'
- . 'OrderExpress::delivery订单发货失败: ' . OrderExpress::$static_error
- . ', 位于File:' . __FILE__
- . ', 位于Line:' . __LINE__
- . ', 参数:' . json_encode($params ?? [])
- . $order_sn;
- Yii::error($errorMsg);
- // throw new Exception('OrderExpress::delivery订单发货失败: ' . OrderExpress::$static_error);
- }
- }
- return true;
- } catch (Exception $e) {
- $errorMsg = '商家已发货:'
- . $e->getMessage()
- . ', 位于File:' . $e->getFile()
- . ', 位于Line:' . $e->getLine()
- . ', 参数:' . json_encode($params ?? [])
- . $order_sn;
- Yii::error($errorMsg);
- return false;
- }
- }
- }
- /**
- * 获取物流信息
- *
- * @param OrderModel $order
- * @param array $logistic
- * @return array
- */
- private function getExpressParams($orders, $express_order)
- {
- $params = [];
- $code = $express_order['company_code'];
- $express = ExpressModel::getExpress($code);
- if (!empty($express_order['order_items'])) {
- $params['id'] = $orders[0]['order_id'];
- foreach ($orders as $order) {
- foreach($express_order['order_items'] as $order_item){
- if($order_item['product_id'] == $order->goods_id){
- $params['order_detail_ids'][] = $order->order_detail_id;
- }
- }
- }
- $params['order_detail_ids'] = array_unique($params['order_detail_ids']);
- $params['shipping_type'] = 0;
- if (!empty($express)) {
- $params['shipping_type'] = 1;
- $params['express_id'] = $express->express_id;
- $params['express_name'] = $express->name;
- // 判断是否是顺丰物流,顺丰物流返回格式=SF1632145481624:5419,需要做切割处理
- if (strpos($express_order['express_no'], ':') !== false) {
- $arr_express_no = explode(':', $express_order['express_no']);
- $express_order['express_no'] = current($arr_express_no);
- }
- $params['express_no'] = $express_order['express_no'];
- }
- $params['mall_id'] = $this->mall_id;
- $params['mch_id'] = 0;
- $params['operator_id'] = 0;
- $params['operator_name'] = '';
- }
- return $params;
- }
- /**
- * 格式化部分区域地址
- *
- * @param array $address
- * @return array
- */
- protected static function formatAddress(array $address)
- {
- if ($address['city'] == '东莞市') {
- $address['town'] = $address['district'];
- $address['district'] = $address['city'];
- }
- if ($address['city'] == '中山市') {
- $address['town'] = $address['district'];
- $address['district'] = $address['city'];
- }
-
- if (($address['city'] == '长沙市') && ($address['district'] == '宁乡县')) {
- $address['district'] = '宁乡市';
- }
- return $address;
- }
- }
|