| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605 |
- <?php
- /**
- * InventoryForm.php
- * todo 文件描述
- * Created on 2024/3/26 13:37
- * @author: hankaige
- */
- namespace app\modules\admin\models;
- use app\models\District;
- use app\models\GoodsCat;
- use app\models\InventiryList;
- use app\models\InventoryOrder;
- use app\models\InventoryOrderGoods;
- use app\models\Order;
- use app\models\OrderDetail;
- use app\models\SortingList;
- use app\models\SortingOrder;
- use app\models\SortingOrderGoods;
- use app\models\User;
- use yii\base\Model;
- use yii\db\Exception;
- use yii\helpers\ArrayHelper;
- class InventoryForm extends Model
- {
- public $store_id;
- public $goods_name;
- public $cat_id;
- public $order_no;
- public $md_id;
- public $dateStart;
- public $dateEnd;
- public $status;
- public $id;
- public $inventory_id;
- public $sorting_id;
- public $driver_id;
- public $send_time;
- public $select_order = [];
- public function rules()
- {
- return [
- [
- [
- 'store_id',
- 'cat_id',
- 'md_id',
- 'status',
- 'sorting_id',
- 'driver_id',
- 'inventory_id'
- ],
- 'integer'
- ],
- [['dateStart','dateEnd','goods_name','order_no','send_time'],'string'],
- ['select_order','safe']
- ];
- }
- public function handleInventory()
- {
- // 获取搜索订单结果
- $orderList = $this->getOrderData();
- $t = \Yii::$app->db->beginTransaction();
- try {
- // 整理订单数据
- $goodsList = $this->handleData($orderList);
- if(empty($goodsList)){
- $t->rollBack();
- return ['code'=>1,'msg'=>'没有可生成备货单的订单'];
- }
- // 生成备货单 与 备货单订单表 以及 备货单商品表
- $inventoryId = $this->createInventory($orderList,$goodsList);
- // 生成分拣单
- $this->createSorting($orderList,$inventoryId);
- $t->commit();
- return [
- 'code' => 0,
- 'msg' => '备货单已生成'
- ];
- } catch (\Throwable $e) {
- $t->rollBack();
- \Yii::error('--------create-inventory-error---- ' . $this->store_id . ' ----auto-execute-error--------' . $e->getMessage() . $e->getFile() . $e->getLine());
- return [
- 'code' => 0,
- 'msg' => $e->getMessage()
- ];
- }
- }
- /**
- * 获取备货单列表
- * @return array
- * @author: hankaige
- * @Time: 2024/3/27 11:13
- */
- public function getInventoryList()
- {
- $query = InventiryList::find()->where([
- 'store_id' => $this->store_id,
- 'is_delete' => 0
- ])->orderBy('id desc');
- $result = pagination_make($query);
- foreach ($result['list'] as &$value) {
- $value['created_at'] = date('Y-m-d H:i:s',$value['created_at']);
- }
- return ['code'=>0,'data'=>$result];
- }
- /**
- * 备货单详情
- * @return array
- * @author: hankaige
- * @Time: 2024/3/27 11:23
- */
- public function getInventoryDetail()
- {
- $query = InventoryOrderGoods::find()->with(['goods'])->where([
- 'inventory_id'=>$this->id,
- 'is_delete'=>0
- ])->orderBy('id desc');
- $result['list'] = $query->asArray()->all();
- foreach ($result['list'] as &$value) {
- $value['created_at'] = date('Y-m-d H:i:s',$value['created_at']);
- $value['attr'] = json_decode($value['attr'],true);
- }
- return ['code'=>0,'data'=>$result];
- }
- /**
- * 分拣单列表
- * @return array
- * @author: hankaige
- * @Time: 2024/3/27 11:30
- */
- public function getSortingList()
- {
- $query = SortingList::find()->with(['md','driver'])->where([
- 'store_id'=>$this->store_id,
- 'is_delete'=>0,
- 'inventory_id' => $this->inventory_id
- ])->orderBy('id desc');
- if(!empty($thid->md_id)){
- $query->andWhere(['md_id'=>$this->md_id]);
- }
- switch($this->status){
- case 1:
- $query->andWhere(['driver_id'=>0]);
- break;
- case 2:
- $query->andWhere(['!=','driver_id',0]);
- break;
- default:
- break;
- }
- if(!empty($this->md_id)){
- $query->andWhere(['md_id'=>$this->md_id]);
- }
- $result = pagination_make($query);
- foreach ($result['list'] as &$value) {
- $value['created_at'] = date('Y-m-d H:i:s',$value['created_at']);
- $province = District::findOne($value['md']['province']);
- $city = District::findOne($value['md']['city']);
- $district = District::findOne($value['md']['district']);
- if ($province && $city && $district) {
- $value['md']['detail_address'] = $province->name . $city->name . $district->name . $value['md']['detail_address'];
- }
- }
- return ['code'=>0,'data'=>$result];
- }
- /**
- * 获取分拣单详情
- * @return array
- * @author: hankaige
- * @Time: 2024/3/27 11:30
- */
- public function getSortingDetail()
- {
- $query = SortingOrderGoods::find()->with(['goods'])->where([
- 'sorting_id'=>$this->id,
- 'is_delete'=>0
- ])->orderBy('id desc');
- $result = pagination_make($query,TRUE);
- foreach ($result['list'] as &$value) {
- $value['created_at'] = date('Y-m-d H:i:s',$value['created_at']);
- $value['attr'] = json_decode($value['attr'],true);
- }
- return ['code'=>0,'data'=>$result];
- }
- /**
- * 获取备货单的所有配送单数据
- * @return array
- * @author: hankaige
- * @Time: 2024/3/28 15:18
- */
- public function getSortingDetailAll()
- {
- $sortingList = SortingList::find()->with(['md','driver'])->where([
- 'store_id'=>$this->store_id,
- 'is_delete'=>0,
- 'inventory_id' => $this->id
- ])->asArray()->all();
- foreach($sortingList as &$item){
- $detail = SortingOrderGoods::find()->with(['goods'])->where([
- 'sorting_id'=>$item['id'],
- 'is_delete'=>0
- ])->asArray()->all();
- foreach ($detail as &$value) {
- $value['created_at'] = date('Y-m-d H:i:s',$value['created_at']);
- $value['attr'] = json_decode($value['attr'],true);
- }
- $item['detail'] = $detail;
- $province = District::findOne($item['md']['province']);
- $city = District::findOne($item['md']['city']);
- $district = District::findOne($item['md']['district']);
- if ($province && $city && $district) {
- $item['md']['detail_address'] = $province->name . $city->name . $district->name . $item['md']['detail_address'];
- }
- }
- return ['code'=>0,'data'=>$sortingList];
- }
- /**
- * 设置配送员
- * @return array
- * @author: hankaige
- * @Time: 2024/3/28 15:18
- */
- public function setDriver()
- {
- SortingList::updateAll(['driver_id'=>$this->driver_id],[
- 'store_id'=>$this->store_id,
- 'is_delete'=>0,
- 'id' => $this->sorting_id
- ]);
- return ['code'=>0,'msg'=>'设置成功'];
- }
- public function printTicket()
- {
- $sortingList = SortingList::find()->with(['md','driver','order'])->where([
- 'store_id'=>$this->store_id,
- 'is_delete'=>0,
- 'inventory_id' => $this->inventory_id
- ])->asArray()->all();
- foreach ($sortingList as &$item){
- $item['created_at'] = date('Y-m-d H:i:s',$item['created_at']);
- $province = District::findOne($item['md']['province']);
- $city = District::findOne($item['md']['city']);
- $district = District::findOne($item['md']['district']);
- if ($province && $city && $district) {
- $item['md']['detail_address'] = $province->name . $city->name . $district->name . $item['md']['detail_address'];
- }
- }
- return ['code'=>0,'data'=>$sortingList];
- }
- /**
- * 根据搜索条件获取订单列表
- * @return array|\yii\db\ActiveRecord[]
- * @author: hankaige
- * @Time: 2024/3/27 10:02
- */
- private function getOrderData(): array
- {
- // 先根据搜索条件获取订单
- $orderQuery = Order::find()->alias('o')
- ->leftJoin(['u' => User::tableName()], 'u.id = o.user_id')
- ->leftJoin(['od' => OrderDetail::tableName()], 'od.order_id=o.id')
- ->where([
- 'o.store_id' => $this->store_id,
- 'o.is_delete' => 0,
- 'o.is_offline' => 1,
- 'o.shop_peisong' => 0,
- // 没有生成过配送单的订单
- ]);
- // 只获取选中的订单
- if(!empty($this->select_order)){
- $orderQuery->andWhere(['o.id'=>$this->select_order]);
- }else{
- if (!empty($this->goods_name)) {
- $orderQuery->andWhere([
- 'like',
- 'od.goods_name',
- $this->goods_name
- ]);
- }
- if ($this->cat_id > 0) {
- // 获取所有绑定这个分类ID的商品ID
- $goodsID = GoodsCat::find()->where([
- 'is_delete' => 0,
- 'cat_id' => $this->cat_id
- ])->select('goods_id')->column();
- if (!empty($goodsID)) {
- $orderQuery->andWhere(['od.goods_id' => $goodsID]);
- }
- }
- // 发货时间
- if($this->send_time){
- $orderQuery->andWhere(['o.arrival_time' => strtotime($this->send_time)]);
- }
- if (!empty($this->order_no)) {
- $orderQuery->andWhere([
- 'like',
- 'o.order_no',
- $this->order_no
- ]);
- }
- if (!empty($this->md_id)) {
- $orderQuery->andWhere(['o.md_id' => $this->md_id]);
- }
- switch ($this->status) {
- case 0:
- $orderQuery->andWhere([
- '<>',
- 'o.trade_status',
- Order::ORDER_FLOW_CANCEL
- ])->andWhere([
- 'o.is_delete' => Order::IS_DELETE_FALSE,
- 'o.is_pay' => Order::IS_PAY_FALSE
- ]);
- break;
- case 1:
- $orderQuery->andWhere([
- 'o.trade_status' => Order::ORDER_FLOW_NO_SEND,
- 'o.is_delete' => Order::IS_DELETE_FALSE
- ])->andWhere([
- 'or',
- ['o.is_pay' => Order::IS_PAY_TRUE],
- ['o.pay_type' => Order::PAY_TYPE_COD]
- ]);
- break;
- case 2:
- $orderQuery->andWhere([
- 'o.trade_status' => Order::ORDER_FLOW_SEND,
- 'o.is_delete' => Order::IS_DELETE_FALSE
- ])->andWhere([
- 'or',
- ['o.is_pay' => Order::IS_PAY_TRUE],
- ['o.pay_type' => Order::PAY_TYPE_COD]
- ]);
- break;
- case 3:
- $orderQuery->andWhere([
- 'o.trade_status' => Order::ORDER_FLOW_CONFIRM,
- 'o.is_delete' => Order::IS_DELETE_FALSE
- ])->andWhere([
- 'or',
- ['o.is_pay' => Order::IS_PAY_TRUE],
- ['o.pay_type' => Order::PAY_TYPE_COD]
- ]);
- break;
- case 4:
- break;
- case 5:
- $orderQuery->andWhere([
- 'or',
- ['o.trade_status' => Order::ORDER_FLOW_CANCEL],
- ['o.is_delete' => Order::IS_DELETE_TRUE]
- ]);
- break;
- case 6:
- $orderQuery->andWhere([
- 'and',
- ['o.apply_delete' => Order::ORDER_APPLY_DELETE],
- [
- '!=',
- 'o.trade_status',
- Order::ORDER_FLOW_CANCEL
- ]
- ]);
- break;
- case 7:
- $orderQuery->andWhere([
- 'o.apply_delete' => Order::ORDER_APPLY_DELETE,
- 'o.trade_status' => Order::ORDER_FLOW_NO_SEND
- ]);
- break;
- default:
- if (empty($this->order_id)) {
- $orderQuery->andWhere([
- 'o.is_delete' => Order::IS_DELETE_FALSE
- ]);
- }
- break;
- }
- if ($this->dateStart) {
- $orderQuery->andWhere([
- '>=',
- 'o.created_at',
- strtotime($this->dateStart)
- ]);
- }
- if ($this->dateEnd) {
- $orderQuery->andWhere([
- '<=',
- 'o.created_at',
- strtotime($this->dateEnd)
- ]);
- }
- }
- return $orderQuery->select([
- 'o.*',
- 'u.nickname as de_name',
- 'u.platform',
- 'u.binding',
- 'u.avatar_url',
- 'od.delivery_type',
- 'od.attr',
- 'o.name user_name',
- 'o.mobile user_mobile',
- 'o.address user_address',
- 'od.order_transit_id'
- ])->all();
- }
- /**
- * 更具订单信息 汇总商品信息
- * @param $orderData
- * @return array
- * @author: hankaige
- * @Time: 2024/3/27 10:02
- */
- private function handleData($orderData): array
- {
- $goodsList = [];
- foreach ($orderData as $orderItem) {
- $goodsList = array_merge($goodsList, ArrayHelper::toArray($orderItem->orderDetail));
- }
- $result = [];
- foreach ($goodsList as $goodsItem) {
- $attr = json_decode($goodsItem['attr'], TRUE);
- // 不存在这个商品
- if (!in_array($goodsItem['goods_id'], array_column($result, 'goods_id'))) {
- $attrList = [
- 'attr_list' => $attr,
- 'num' => $goodsItem['num'],
- // 规格对应的数量
- ];
- $result[] = [
- 'goods_id' => $goodsItem['goods_id'],
- 'goods_name' => $goodsItem['goods_name'],
- 'num' => $goodsItem['num'],
- // 商品所有规格的总数量
- 'attr_list' => [$attrList]
- ];
- } else {
- // 选中已存在的商品
- foreach ($result as $key => $value) {
- if ($value['goods_id'] == $goodsItem['goods_id']) {
- $result[$key]['num'] += $goodsItem['num'];
- // 处理规格
- $hasAttr = false;
- foreach ($value['attr_list'] as $attrItemKey => $attrItem) {
- // 已存在的规格
- $oldAttrIds = array_column($attrItem['attr_list'], 'attr_id');
- // 当前商品的规格
- $attrIds = array_column($attr, 'attr_id');
- sort($oldAttrIds);
- sort($attrIds);
- // 规格存在相同规格
- if (!array_diff($oldAttrIds, $attrIds)) {
- $result[$key]['attr_list'][$attrItemKey]['num'] += $goodsItem['num'];
- $hasAttr = true;
- break;
- }
- }
- if(!$hasAttr){
- $result[$key]['attr_list'][] = [
- 'attr_list' => $attr,
- 'num' => $goodsItem['num']
- ];
- }
- }
- }
- }
- }
- return $result;
- }
- /**
- * 生成备货单 备货单商品 备货单订单
- * @param $orderList
- * @param $goodsList
- * @return int
- * @throws Exception
- * @author: hankaige
- * @Time: 2024/3/27 10:03
- */
- private function createInventory($orderList,$goodsList): int
- {
- // 生成备货单
- $inventoryModel = new InventiryList();
- $inventoryModel->store_id = $this->store_id;
- $inventoryModel->inventory_no = $inventoryModel::createOrderNo();
- $inventoryModel->goods_count = count($goodsList);
- $inventoryModel->order_count = count($orderList);
- if(!$inventoryModel->save()){
- throw new Exception('生成备货单失败');
- }
- // 生成备货商品
- $inventoryOrderGoods = new InventoryOrderGoods();
- foreach($goodsList as $goodsItem){
- $goods = clone $inventoryOrderGoods;
- $goods->inventory_id = $inventoryModel->id;
- $goods->goods_id = $goodsItem['goods_id'];
- $goods->goods_name = $goodsItem['goods_name'];
- $goods->attr = json_encode($goodsItem['attr_list']);
- $goods->num = $goodsItem['num'];
- if(!$goods->save()){
- throw new Exception('生成备货商品错误');
- }
- }
- // 生成备货单订单信息
- $inventoryOrder = new InventoryOrder();
- foreach ($orderList as $orderItem){
- $order = clone $inventoryOrder;
- $order->inventory_id = $inventoryModel->id;
- $order->order_id = $orderItem['id'];
- if(!$order->save()){
- throw new Exception('生成备货订单关联信息失败');
- }
- }
- // 返货备货单主ID
- return $inventoryModel->id;
- }
- /**
- * 处理生成分拣单
- * @param $orderList
- * @param $inventoryId
- * @throws Exception
- * @author: hankaige
- * @Time: 2024/3/27 10:39
- */
- private function createSorting($orderList,$inventoryId)
- {
- $newOrderList = [];
- foreach ($orderList as $orderItem){
- $newOrderList[$orderItem['md_id']][] = $orderItem;
- }
- // 循环整理后的订单信息 整理为商品的数据
- $newGoodsList = [];
- foreach($newOrderList as $mdId => $value){
- $newGoodsList[$mdId] = $this->handleData($value);
- }
- if(empty($newGoodsList)){
- throw new \Exception('商品信息出错了');
- }
- $sortingModel = new SortingList();
- $sortingOrderModel = new SortingOrder();
- $sortingOrderGoodsModel = new SortingOrderGoods();
- foreach($newGoodsList as $mdId => $goods){
- $model = clone $sortingModel;
- $model->store_id = $this->store_id;
- $model->inventory_id = $inventoryId;
- $model->sorting_no = $model::createOrderNo();
- $model->md_id = $mdId;
- $model->goods_count = count($goods);
- $model->order_count = count($newOrderList[$mdId]);
- if(!$model->save()){
- throw new Exception('生成分拣单失败');
- }
- foreach($newOrderList[$mdId] as $order){
- $modelOrder = clone $sortingOrderModel;
- $modelOrder->sorting_id = $model->id;
- $modelOrder->order_id = $order['id'];
- if(!$modelOrder->save()){
- throw new Exception('分拣单订单生成失败');
- }
- }
- foreach($goods as $goodsItem){
- $modelOrderGoods = clone $sortingOrderGoodsModel;
- $modelOrderGoods->sorting_id = $model->id;
- $modelOrderGoods->goods_id = $goodsItem['goods_id'];
- $modelOrderGoods->goods_name = $goodsItem['goods_name'];
- $modelOrderGoods->attr = json_encode($goodsItem['attr_list']);
- $modelOrderGoods->num = $goodsItem['num'];
- if(!$modelOrderGoods->save()){
- throw new Exception('分拣商品错误');
- }
- }
- }
- }
- }
|