cqp 10 months ago
parent
commit
71a990b9c0

+ 74 - 0
app/Http/Controllers/Api/InventoryController.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Service\InventoryService;
+use Illuminate\Http\Request;
+
+class InventoryController extends BaseController
+{
+    public function inventoryAdd(Request $request)
+    {
+        $service = new InventoryService();
+        $userData = $request->userData->toArray();
+        list($status,$data) = $service->add($request->all(),$userData);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function inventoryEdit(Request $request)
+    {
+        $service = new InventoryService();
+        $userData = $request->userData->toArray();
+        list($status,$data) = $service->edit($request->all(),$userData);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function inventoryDetail(Request $request)
+    {
+        $service = new InventoryService();
+        $userData = $request->userData->toArray();
+        list($status,$data) = $service->detail($request->all(),$userData);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function inventoryDel(Request $request)
+    {
+        $service = new InventoryService();
+        $userData = $request->userData->toArray();
+        list($status,$data) = $service->del($request->all(),$userData);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function inventoryList(Request $request)
+    {
+        $service = new InventoryService();
+        $userData = $request->userData->toArray();
+        list($status,$data) = $service->getList($request->all(),$userData);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+}

+ 1 - 0
app/Http/Kernel.php

@@ -67,6 +67,7 @@ class Kernel extends HttpKernel
         'checkWx' => \App\Http\Middleware\CheckWx::class,
         'checkWeixin' => \App\Http\Middleware\CheckWeinxin::class,
         'OssFileDeal' => \App\Http\Middleware\OssFileDeal::class,
+        'OrderDeal' => \App\Http\Middleware\OrderDeal::class,
     ];
 
     /**

+ 50 - 0
app/Http/Middleware/OrderDeal.php

@@ -0,0 +1,50 @@
+<?php
+namespace App\Http\Middleware;
+
+use App\Model\OrderInventoryStock;
+use Closure;
+use Illuminate\Http\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+class OrderDeal
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @return mixed
+     */
+    public function handle(Request $request, Closure $next)
+    {
+        // 在这里可以添加请求前的操作,但通常我们只关心请求后的操作。
+        return $next($request);
+    }
+
+    /**
+     * Handle the request termination.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Illuminate\Http\Response  $response
+     * @return void
+     */
+    public function terminate(Request $request, Response $response)
+    {
+        $return = json_decode($response->content(),true);
+
+        if(isset($return['code']) && $return['code'] == 200){
+            if(! empty($return['data'])){
+                $result = $return['data'];
+
+                if(! empty($result['order'])){
+                    $insert = $result['order'];
+                    if(empty($insert['order_number'])) return;
+                    $model = new OrderInventoryStock();
+                    $model->order_number = $insert['order_number'];
+                    $model->is_check_stock = $insert['is_check_stock'];
+                    $model->save();
+                }
+            }
+        }
+    }
+}

+ 27 - 0
app/Model/Inventory.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Inventory extends UseScopeBaseModel
+{
+    protected $table = "inventory"; //指定表
+    const CREATED_AT = 'crt_time';
+    const UPDATED_AT = 'upd_time';
+    protected $dateFormat = 'U';
+    const State_minus_one = -1;//驳回
+    const STATE_ZERO = 0;//未审核
+    const STATE_ONE = 1;//待审核
+    const STATE_TWO = 2;//审核通过
+    const prefix = 'PD';
+    public static $name = [
+        self::State_minus_one => '驳回',
+        self::STATE_ZERO => '未审核',
+        self::STATE_ONE => '待审核',
+        self::STATE_TWO => '审核通过'
+    ];
+
+    const range_function = '';
+    const is_check_function = '';
+}

+ 14 - 0
app/Model/InventorySub.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+class InventorySub extends Model
+{
+    protected $table = "inventory_sub"; //指定表
+    const CREATED_AT = null;
+    const UPDATED_AT = null;
+    protected $dateFormat = 'U';
+
+}

+ 19 - 0
app/Model/OrderInventoryStock.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+class OrderInventoryStock extends Model
+{
+    protected $table = "order_inventory_stock"; //指定表
+    const CREATED_AT = 'crt_time';
+    const UPDATED_AT = 'upd_time';
+    protected $dateFormat = 'U';
+    const type_one = 1;//校验库存
+    const type_two = 2;//不校验证库存
+    public static $type_name = [
+        self::type_one => '是',
+        self::type_two => '否',
+    ];
+}

+ 2 - 2
app/Service/CheckService.php

@@ -1414,7 +1414,7 @@ class CheckService extends Service
             }else{
                 //锁定数量
                 $lock_number_tmp = 0;
-                if($lock && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
+                if($lock == ProductInventorySet::type_one && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
 
                 ProductInventory::where('product_id',$m->product_id)
                     ->where('storehouse_id',$m->storehouse_id)
@@ -1501,7 +1501,7 @@ class CheckService extends Service
             }else{
                 //锁定数量
                 $lock_number_tmp = 0;
-                if($lock && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
+                if($lock == ProductInventorySet::type_one && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
 
                 ProductInventory::where('product_id',$m->product_id)
                     ->where('storehouse_id',$m->storehouse_id)

+ 5 - 1
app/Service/ConstructionService.php

@@ -19,6 +19,7 @@ use App\Model\OaSubEmployee;
 use App\Model\OaSubReportEmployee;
 use App\Model\OaSubRule;
 use App\Model\Product;
+use App\Model\ProductInventorySet;
 use App\Model\ReturnExchangeOrder;
 use App\Model\ReturnExchangeOrderProductInfo;
 use App\Model\SalesOrder;
@@ -328,7 +329,7 @@ class ConstructionService extends Service
 //            if(! $status) return [true, '保存成功,施工单确认失败,异常信息:' . $msg];
         }
 
-        return [true, ['file' => ['new' => $new]]];
+        return [true, ['file' => ['new' => $new], "order" => ['order_number' => $data['order_number'], 'is_check_stock' => $data['is_check_stock']]]];
     }
 
     /**
@@ -711,10 +712,13 @@ class ConstructionService extends Service
         //是否校验库存
         ProductInventoryService::is_check($user,$data);
 
+        $data['is_check_stock'] = $user['is_check_stock'];
         if($data['model_type'] == Construction::Model_type_one){
             //到店安装 才校验库存
             list($status,$msg) = (new ProductInventoryService())->compareStock($user,$product_id, $product_submit, $product_save);
             if(! $status) return [false, $msg];
+        }else{
+            $data['is_check_stock'] = ProductInventorySet::type_two;
         }
 
         if($is_add){

+ 189 - 0
app/Service/ImportService.php

@@ -10,9 +10,12 @@ use App\Model\Customer;
 use App\Model\CustomerInfo;
 use App\Model\Depart;
 use App\Model\Employee;
+use App\Model\Inventory;
+use App\Model\InventorySub;
 use App\Model\LastJc;
 use App\Model\Product;
 use App\Model\ProductCategory;
+use App\Model\ProductInventorySet;
 use App\Model\ProductPriceDetail;
 use App\Model\SalesOrder;
 use App\Model\SalesOrderInfo;
@@ -32,6 +35,7 @@ class ImportService extends Service
         'salesOnline', //线上订单
         'btOnline', //补贴订单
         'lastJc', //上月结存
+        'inventory', // 盘点
     ];
 
     //写活的导入------------------- 暂时不好用
@@ -218,6 +222,17 @@ class ImportService extends Service
         return [true, $config_array,$filename];
     }
 
+    private function inventory($data,$user){
+        //生成下载文件
+        $filename =  "盘点单导入模板_" . time() . '.' . 'xlsx';
+
+        //获取配置文件
+        $config = "excel.inventory";
+        $config_array = config($config) ?? [];
+        if(empty($config_array)) return [false, '配置文件不存在',''];
+        return [true, $config_array,$filename];
+    }
+
     //导入入口
     public function importAll($data,$user){
 //        //不超时
@@ -1278,5 +1293,179 @@ class ImportService extends Service
 
         return [true, ''];
     }
+
+    public function inventoryImport($array, $user){
+        $head = $user['head']['id'] ?? 0;
+
+        // 去除表头
+        unset($array[0]);
+        if(empty($array)) return [false, '导入数据不能为空'];
+
+        $shop_name = $product_code = $counted_number = [];
+        foreach ($array as $key => $value){
+            $rowData = array_filter($value);
+            if (empty($rowData)) {
+                unset($array[$key]);
+            } elseif(empty($value[0]) || empty($value[1]) || empty($value[2])) {
+                if($key != 1){
+                    if(empty($value[2])) return [false, '带*号的字段项必填'];
+                } else{
+                    return [false, '带*号的字段项必填'];
+                }
+            }else{
+                foreach ($value as $k => $v){
+                    $value[$k] = trim($v);
+                }
+                if($shop_name && ! in_array($value[0],$shop_name)) $shop_name[] = $value[0];
+                if($counted_number && ! in_array($value[1],$counted_number)) $counted_number[] = $value[1];
+                if(! in_array($value[2],$product_code)) {
+                    $product_code[] = $value[2];
+                }else{
+                    return [false, '产品编号:' . $value[2] .'已存在'];
+                }
+                if(! is_numeric($value[3])) return [false, '* 盘点数量请填写正确的数值'];
+            }
+        }
+        if(count($shop_name) != 1) return [false, '只允许单门店盘点'];
+
+        $model = Product::ProductClear($user,[]);
+        $product_map = $model->whereIn('code',$product_code)
+            ->where('del_time',0)
+            ->pluck('id','code')
+            ->toArray();
+
+        $depart_map = Depart::whereIn('title',$shop_name)
+            ->where('del_time',0)
+            ->pluck('id','title')
+            ->toArray();
+        $storehouse_map = Storehouse::whereIn('top_depart_id',array_values($depart_map))
+            ->where('del_time',0)
+            ->pluck('id','top_depart_id')
+            ->toArray();
+
+        $employee = Employee::where('del_time',0)
+            ->whereIn('number',$counted_number)
+            ->pluck('number','id')
+            ->toArray();
+        $time = time();
+
+        $top_depart_id = $storehouse_id = $employee_id = 0;
+        $product_submit = $product_id = [];
+        foreach ($array as $value){
+            if($value[0]){
+                $depart_tmp = $depart_map[$value[0]] ?? 0;
+                if($depart_tmp <= 0) return [false, "门店:" . $value[0] . "不存在或已被删除"];
+                if(! $top_depart_id) $top_depart_id = $depart_tmp;
+                $storehouse_tmp = $storehouse_map[$depart_tmp] ?? 0;
+                if(! $storehouse_id) $storehouse_id = $storehouse_tmp;
+            }
+            if($value[1]){
+                $emp_tmp = $employee[$value[1]] ?? 0;
+                if(! $emp_tmp) return [false, "工号:" . $value[1] . "不存在或已被删除"];
+                if(! $employee_id) $employee_id = $emp_tmp;
+            }
+            $product_tmp = $product_map[$value[2]] ?? 0;
+            if($product_tmp <= 0) return [false, "产品编码:" . $value[2] . "不存在或已被删除"];
+
+            if(! $storehouse_id) return [false, '门店下仓库信息未找到'];
+
+            $key = $product_tmp . ',' . $storehouse_id;
+            if(! isset($product_submit[$key])) $product_submit[$key] = 0;
+
+            //总的产品id
+            $product_id[] = $value['product_id'];
+
+            $sub[] = [
+                'product_id' => $product_tmp,
+                'storehouse_id' => $storehouse_id,
+                'order_number' => "",
+                'counted_num' => $value[3],
+                'add_num' => 0,
+                'reduce_num' => 0,
+                'inventory_id' => $employee_id
+            ];
+        }
+
+        //库存校验
+        $set = ProductInventorySet::where('top_depart_id',$top_depart_id)->where('del_time',0)->first();
+        if(empty($set)) return [false, '门店是否校验库存设置缺失'];
+        $set = $set->toArray();
+        $is_check_stock = $set['param_one'] <= 0 ? ProductInventorySet::type_one : $set['param_one'];
+
+        //获取库存
+        $inventory_map = [];
+        $inventory = ProductInventoryService::getRealStock($product_id, $storehouse_id);
+        foreach ($inventory as $value){
+            $key = $value['product_id'] . ',' . $value['storehouse_id'];
+            $inventory_map[$key] = $value['real_number'];
+        }
+
+        $order_number = (new OrderNoService())->createOrderNumber(Inventory::prefix);
+        $product_submit_reduce = $product_reduce_id = [];
+        //盘点详情
+        foreach ($sub as $key => $value){
+            $sub[$key]['order_number'] = $order_number;
+            $keys = $value['product_id'] . ',' . $value['storehouse_id'];
+            if(isset($inventory_map[$keys])){
+                if($value['counted_num'] >= $inventory_map[$keys]){
+                    $num = bcsub($value['counted_num'], $inventory_map[$keys],2);
+                    $sub[$key]['add_num'] = $num;
+                }else{
+                    $num = bcsub($inventory_map[$keys], $value['counted_num'],2);
+                    $sub[$key]['reduce_num'] = $num;
+                }
+            }else{
+                if($value['counted_num'] >= 0){
+                    $sub[$key]['add_num'] = $value['counted_num'];
+                }else{
+                    $sub[$key]['reduce_num'] = $value['counted_num'];
+                }
+            }
+
+            if($sub[$key]['reduce_num'] != 0) {
+                $product_reduce_id[] = $value['product_id'];
+                $product_submit_reduce[$keys] = $sub[$key]['reduce_num'];
+            }
+        }
+
+        //校验是否存在产品盘点
+        list($status, $msg) = (new InventoryService())->issetProduct(['top_depart_id' => $top_depart_id], $product_submit);
+        if(! $status) return [false, $msg];
+
+        if(! empty($product_submit_reduce)){
+            //校验库存
+            list($status,$msg) = (new ProductInventoryService())->compareStock($user,$product_reduce_id, $product_submit_reduce);
+            if(! $status) return [false, $msg];
+        }
+
+        if(empty($sub)) return [false, '暂无需要写入的盘点数据'];
+
+        try{
+            DB::beginTransaction();
+
+            $inventory_model = new Inventory();
+            $inventory_model->order_number = $order_number;
+            $inventory_model->storehouse_id = $storehouse_id;
+            $inventory_model->counted_id = $user['id'];
+            $inventory_model->counted_time = $time;
+            $inventory_model->depart_id = $top_depart_id;
+            $inventory_model->top_depart_id = $top_depart_id;
+            $inventory_model->crt_id = $user['id'];
+            $inventory_model->save();
+
+            //写入数据
+            InventorySub::insert($sub);
+
+            DB::commit();
+        }catch (\Exception $exception){
+            DB::rollBack();
+            if (str_contains($exception->getMessage(), '1062') || str_contains($exception->getMessage(), 'Duplicate entry')) {
+                return [false, '网络波动,请重新操作!'];
+            }
+            return [false, $exception->getMessage() . $exception->getLine() . $exception->getCode()];
+        }
+
+        return [true, ["order" => ['order_number' => $order_number, 'is_check_stock' => $is_check_stock]]];
+    }
 }
 

+ 365 - 0
app/Service/InventoryService.php

@@ -0,0 +1,365 @@
+<?php
+
+namespace App\Service;
+
+use App\Model\Employee;
+use App\Model\Inventory;
+use App\Model\InventorySub;
+use App\Model\Product;
+use App\Model\Storehouse;
+use Illuminate\Support\Facades\DB;
+
+class InventoryService extends Service
+{
+    public function edit($data,$user){
+        list($status,$msg) = $this->orderRule($data, $user,false);
+        if(!$status) return [$status,$msg];
+
+        try{
+            DB::beginTransaction();
+            $inventory_model = Inventory::where('order_number',$data['order_number'])->first();
+            $inventory_model->counted_id = $data['counted_id'];
+            $inventory_model->counted_time = $data['counted_time'];
+            $inventory_model->mark = $data['mark'];
+            $inventory_model->save();
+
+            InventorySub::where('del_time',0)
+                ->where('order_number',$data['order_number'])
+                ->update(['del_time'=>time()]);
+
+            if(! empty($data['sub'])){
+                $sub = [];
+                foreach ($data['sub'] as $value){
+                    $sub[] = [
+                        'product_id' => $value['product_id'],
+                        'storehouse_id' => $data['storehouse_id'],
+                        'order_number' => $data['order_number'],
+                        'counted_num' => $value['counted_num'],
+                        'add_num' => $value['add_num'],
+                        'reduce_num' => $value['reduce_num'],
+                        'inventory_id' => $inventory_model->id
+                    ];
+                }
+                InventorySub::insert($sub);
+            }
+
+            DB::commit();
+        }catch (\Throwable $e){
+            DB::rollBack();
+            return [false,$e->getMessage()];
+        }
+
+        return [true, ''];
+    }
+
+    public function add($data,$user){
+        list($status,$msg) = $this->orderRule($data, $user);
+        if(!$status) return [$status,$msg];
+        try{
+            DB::beginTransaction();
+            $inventory_model = new Inventory();
+            $inventory_model->order_number = $data['order_number'];
+            $inventory_model->storehouse_id = $data['storehouse_id'];
+            $inventory_model->counted_id = $data['counted_id'];
+            $inventory_model->counted_time = $data['counted_time'];
+            $inventory_model->mark = $data['mark'] ?? '';
+            $inventory_model->depart_id = $data['depart_id'] ?? 0;
+            $inventory_model->top_depart_id = $data['top_depart_id'] ?? 0;
+            $inventory_model->crt_id = $user['id'];
+            $inventory_model->save();
+
+            if(! empty($data['sub'])){
+                $sub = [];
+                foreach ($data['sub'] as $value){
+                    $sub[] = [
+                        'product_id' => $value['product_id'],
+                        'storehouse_id' => $data['storehouse_id'],
+                        'order_number' => $data['order_number'],
+                        'counted_num' => $value['counted_num'],
+                        'add_num' => $value['add_num'],
+                        'reduce_num' => $value['reduce_num'],
+                        'inventory_id' => $inventory_model->id
+                    ];
+                }
+                InventorySub::insert($sub);
+            }
+
+            DB::commit();
+        }catch (\Throwable $exception){
+            DB::rollBack();
+            if (str_contains($exception->getMessage(), '1062') || str_contains($exception->getMessage(), 'Duplicate entry')) {
+                return [false, '网络波动,请重新操作!'];
+            }
+            return [false,$exception->getMessage()];
+        }
+
+        return [true, ["order" => ['order_number' => $data['order_number'], 'is_check_stock' => $user['is_check_stock']]]];
+    }
+
+    public function detail($data,$user){
+        if(empty($data['id']) && empty($data['order_number'])) return [false,'请选择数据!'];
+
+        if(! empty($data['id'])){
+            $inventory = Inventory::where('del_time',0)
+                ->where('id',$data['id'])
+                ->first();
+        }else{
+            $inventory = Inventory::where('del_time',0)
+                ->where('order_number',$data['order_number'])
+                ->first();
+            $data['id'] = empty($inventory->id) ? 0 : $inventory->id;
+        }
+        if(empty($inventory)) return [false,'盘点单不存在或已被删除'];
+        $inventory = $inventory->toArray();
+        $inventory['state_title'] = Inventory::$name[$inventory['state']] ?? '';
+
+        $emp_map = Employee::whereIn('id', [$inventory['crt_id'], $inventory['counted_id']])
+            ->pluck('emp_name','id')
+            ->toArray();
+        $inventory['crt_name'] = $emp_map[$inventory['crt_id']] ?? '';
+        $inventory['counted_name'] = $emp_map[$inventory['counted_id']] ?? '';
+        $inventory['counted_time'] = $inventory['counted_time'] ? date("Y-m-d", $inventory['counted_time']): '';
+        $inventory['crt_time'] = $inventory['crt_time'] ? date("Y-m-d H:i:s", $inventory['crt_time']): '';
+
+        $sub = InventorySub::where('del_time',0)
+            ->where('inventory_id', $data['id'])
+            ->select('product_id','counted_num','add_num','reduce_num')
+            ->get()->toArray();
+        $map = (new ProductService())->getProductDetail(array_column($sub,'product_id'));
+        foreach ($sub as $key => $value){
+            $tmp = $map[$value['product_id']] ?? [];
+            $sub[$key]['title'] = $tmp['title'] ?? "";
+            $sub[$key]['code'] = $tmp['code'] ?? "";
+        }
+        $inventory['sub'] = $sub;
+
+        return [true, $inventory];
+    }
+
+    public function del($data,$user){
+        if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
+        $inventory = Inventory::where('del_time',0)->where('id',$data['id'])->first();
+        if(empty($inventory)) return [false,'盘点单不存在或已被删除'];
+        $inventory = $inventory->toArray();
+        if($inventory['state'] > Inventory::STATE_ZERO) return [false,'请确认盘点单状态,操作失败'];
+
+        $time = time();
+        $product_save = $this->getSaveDetail($data['id']);
+        try {
+            DB::beginTransaction();
+
+            Inventory::where('id',$data['id'])->update([
+                'del_time'=> $time
+            ]);
+
+            InventorySub::where('del_time',0)->whereIn('inventory_id',$data['id'])->update([
+                'del_time'=> $time
+            ]);
+
+            //锁定库存释放
+            if(! empty($product_save)) ProductInventoryService::changeLockNumber($user,[],$product_save);
+
+            DB::commit();
+        }catch (\Exception $exception){
+            DB::rollBack();
+            return [false, $exception->getMessage()];
+        }
+
+        return [true, ''];
+    }
+
+    public function getList($data,$user){
+        $model = Inventory::Clear($user,$data);
+        $model = $model->where('del_time',0)
+            ->select('order_number','id','storehouse_id','state','counted_id','counted_time','inventory_id','crt_time')
+            ->orderby('id', 'desc');
+        if(! empty($data['crt_time'][0]) && ! empty($data['crt_time'][1])) $model->whereBetween('crt_time',[$data['crt_time'][0],$data['crt_time'][1]]);
+        if(! empty($data['order_number'])) $model->where('order_number', 'LIKE', '%'.$data['order_number'].'%');
+        if(! empty($data['storehouse_id'])) $model->where('storehouse_id', $data['storehouse_id']);
+        if(! empty($data['counted_name'])) {
+            $id = $this->forSearch($data);
+            $model->whereIn('counted_id',$id);
+        }
+        if(isset($data['state'])) $model->where('state', $data['state']);
+        if(! empty($data['product_code'])) {
+            $id = $this->forSearch($data);
+            $model->whereIn('id',$id);
+        }
+
+        $list = $this->limit($model,'',$data);
+        $list = $this->fillListData($list);
+
+        return [true, $list];
+    }
+
+    public function fillListData($data){
+        if(empty($data['data'])) return $data;
+
+        $storehouse_map = Storehouse::whereIn('id',array_column($data['data'],'storehouse_id'))
+            ->pluck('title','id')
+            ->toArray();
+
+        $emp_map = Employee::whereIn('id',array_unique(array_merge_recursive(array_column($data['data'],'counted_id'), array_column($data['data'],'crt_id'))))
+            ->pluck('emp_name','id')
+            ->toArray();
+
+        foreach ($data['data'] as $key => $value){
+            $data['data'][$key]['counted_time'] = $value['counted_time'] ? date("Y-m-d",$value['counted_time']) : '';
+            $data['data'][$key]['crt_time'] = $value['crt_time'] ? date("Y-m-d H:i:s",$value['crt_time']) : '';
+            $data['data'][$key]['storehouse_name'] = $storehouse_map[$value['storehouse_id']] ?? '';
+            $data['data'][$key]['counted_name'] = $emp_map[$value['counted_id']] ?? '';
+            $data['data'][$key]['state_name'] = Inventory::$name[$value['state']] ?? '';
+        }
+
+        return $data;
+    }
+
+    public function forSearch($data){
+        if(! empty($data['product_code'])){
+            $product = Product::where('code',  'LIKE', '%'.$data['product_code'].'%')
+                ->select('id')
+                ->get()->toArray();
+            $inventory_id = InventorySub::where('del_time',0)
+                ->whereIn('product_id', array_column($product,'id'))
+                ->select('inventory_id')
+                ->get()->toArray();
+            return array_column($inventory_id, 'inventory_id');
+        }
+
+        if(! empty($data['counted_name'])){
+            $employee = Employee::where('emp_name',  'LIKE', '%'.$data['counted_name'].'%')
+                ->select('id')
+                ->get()->toArray();
+            return array_column($employee, 'id');
+        }
+
+        return [];
+    }
+
+    public function orderRule(&$data, $user, $is_add = true){
+        if(empty($data['counted_id'])) return [false,'盘点人不能为空'];
+        if(empty($data['counted_time'])) return [false,'盘点日期不能为空'];
+        $data['counted_time'] = $this->changeDateToDate($data['counted_time']);
+        if(empty($data['storehouse_id'])) return [false,'仓库不能为空'];
+        if(empty($data['sub'])) return [false, '盘点明细不能为空'];
+        $product_submit = $product_submit_reduce = $product_id = [];
+        foreach ($data['sub'] as $value){
+            if(empty($value['product_id'])) return [false,"盘点单产品ID不为空"];
+            $bool = $this->checkNumber($value['counted_num']);
+            if(! $bool) return [false, '盘点数量不合法,请输入大于等于0的两位数值'];
+            $bool = $this->checkNumber($value['add_num']);
+            if(! $bool) return [false, '盘盈数量不合法,需是大于等于0的两位数值'];
+            $bool = $this->checkNumber($value['reduce_num']);
+            if(! $bool) return [false, '盘亏数量不合法,需是大于等于0的两位数值'];
+
+            $key = $value['product_id'] . ',' .$data['storehouse_id'];
+            if(! isset($product_submit[$key])) $product_submit[$key] = 0;
+
+            if($value['reduce_num'] > 0){
+                if(isset($product_submit_reduce[$key])){
+                    $product_submit_reduce[$key] += $value['reduce_num'];
+                }else{
+                    $product_submit_reduce[$key] = $value['reduce_num'];
+                }
+                $product_id[] = $value['product_id'];
+            }
+        }
+
+        //所属部门 以及  顶级部门
+        if(empty($data['depart_id'])) {
+            $data['depart_id'] = $this->getDepart($user);
+            $data['top_depart_id'] = $user['depart_map'][$data['depart_id']] ?? 0;
+        }
+
+        if($is_add){
+            $order_number = (new OrderNoService())->createOrderNumber(Inventory::prefix);
+            if(empty($order_number)) return [false,'盘点单号生成失败'];
+            $data['order_number'] = $order_number;
+        }else{
+            if(empty($data['order_number'])) return [false,'盘点单号不能为空'];
+            $model = Inventory::where('order_number',$data['order_number'])->where('del_time',0)->first();
+            if(empty($model)) return [false, '盘点单不存在或已被删除'];
+            $order = $model->toArray();
+            if($order['state'] != Inventory::STATE_ZERO) return [false, '请确认单据状态,编辑失败'];
+            if($order['storehouse_id'] != $data['storehouse_id']) return [false, '仓库不允许编辑'];
+        }
+
+        //校验是否存在产品盘点
+        list($status, $msg) = $this->issetProduct($data, $product_submit);
+        if(! $status) return [false, $msg];
+
+        $id = $data['id'] ?? 0;
+        $product_save_reduce = $this->getSaveDetail($id);
+
+        if(! empty($product_submit_reduce)){
+            //校验库存
+            list($status,$msg) = (new ProductInventoryService())->compareStock($user,$product_id, $product_submit_reduce, $product_save_reduce);
+            if(! $status) return [false, $msg];
+        }
+
+        return [true, ''];
+    }
+
+    /**
+     * 获取保存详情
+     * @param $id
+     * @return array
+     */
+    public function getSaveDetail($id){
+        $product_save = [];
+        if(empty($id)) return [];
+
+        $sub = InventorySub::where('inventory_id',$id)
+            ->where('del_time',0)
+            ->get()->toArray();
+        foreach ($sub as $value){
+            $key = $value['product_id'] . ',' . $value['storehouse_id'];
+            if($value['reduce_num'] > 0){//盘亏
+                if(isset($product_save[$key])){
+                    $product_save[$key] += $value['reduce_num'];
+                }else{
+                    $product_save[$key] = $value['reduce_num'];
+                }
+            }
+        }
+
+        return $product_save;
+    }
+
+    public function issetProduct($data, $product_submit){
+        $id = $data['id'] ?? 0;
+
+        $inventory = Inventory::where('del_time',0)
+            ->when(! empty($id), function ($query) use ($id) {
+                return $query->where('id','<>',$id);
+            })
+            ->where('top_depart_id',$data['top_depart_id'])
+            ->where('state','<',Inventory::STATE_TWO)
+            ->select('id')
+            ->get()->toArray();
+
+        $sub = InventorySub::where('del_time', 0)
+            ->whereIn('inventory_id', array_column($inventory,'id'))
+            ->select('product_id', 'storehouse_id')
+            ->get()->toArray();
+
+        $map = [];
+        $product = Product::whereIn('id', array_unique(array_column($sub,'product_id')))
+            ->select('id','title','code')
+            ->get()->toArray();
+        foreach ($product as $value){
+            $map[$value['id']] = $value;
+        }
+
+        foreach ($sub as $value){
+            $key = $value['product_id'] . ',' .$value['storehouse_id'];
+            if(isset($product_submit[$key])){
+                $pro_tmp = $map[$value['product_id']] ?? [];
+                $pro_str = $pro_tmp['title'] . "( ". $pro_tmp['code'] .")";
+                return [false, "产品:" . $pro_str . "在盘点单:" . $value['order_number'] . "已录入盘点"];
+            }
+        }
+
+        return [true, ''];
+    }
+}

+ 1 - 1
app/Service/InvoiceOrderService.php

@@ -133,7 +133,7 @@ class InvoiceOrderService extends Service
             return [false,$exception->getMessage()];
         }
 
-        return [true,''];
+        return [true, ["order" => ['order_number' => $data['order_number'], 'is_check_stock' => $user['is_check_stock']]]];
     }
 
     /**

+ 23 - 62
app/Service/ProductInventoryService.php

@@ -24,70 +24,25 @@ use Illuminate\Support\Facades\DB;
 class ProductInventoryService extends Service
 {
     //获取产品真实库存
-    public static function getRealStock($product_id = [],$data=[]){
-        if(empty($product_id)) return [];
+    public static function getRealStock($product_id = [], $storehouse_id = 0){
+        if(empty($product_id) || empty($storehouse_id)) return [];
         $array = ProductInventory::whereIn('product_id',$product_id)
-            ->where('number','>',0)
-            ->select('id','product_id','number','crt_time','lock_number')
+            ->where('storehouse_id', $storehouse_id)
             ->get()->toArray();
 
-        $map = [];
-        if(! empty($data['order_number'])){
-            if(strpos($data['order_number'],InvoiceOrder::prefix) !== false){
-                $id = InvoiceOrder::where('order_number',$data['order_number'])
-                    ->where('del_time',0)
-                    ->value('id');
-                $model = new InvoiceOrderInfo();
-            }else{
-                foreach (Construction::$prefix as $value){
-                    if(strpos($data['order_number'],$value) !== false){
-                        $model = new ConstructionProductInfo();
-                    }
-                }
-                $id = Construction::where('order_number',$data['order_number'])
-                    ->where('del_time',0)
-                    ->value('id');
-            }
-            if(! empty($model) && ! empty($id)){
-                $save = $model->where('del_time',0)
-                    ->where('id',$id)
-                    ->select('product_id','number')
-                    ->get()->toArray();
-                foreach ($save as $value){
-                    $key = $value['product_id'];
-                    if(isset($map[$key])){
-                        $map[$key] += $value['number'];
-                    }else{
-                        $map[$key] = $value['number'];
-                    }
-                }
-            }
-        }
-
         $return = [];
         if(! empty($array)){
-            //todo
-            $setting_map = Setting::where('setting_name','lock_number')
-                ->pluck('setting_value','setting_name')
-                ->toArray();
             foreach ($array as $value){
-                if(! empty($setting_map['lock_number'])){//真实库存
-                    $tmp = $map[$value['product_id']] ?? 0;//已保存数量
-                    $tmp_lock = ($value['lock_number'] > 0 ? $value['lock_number'] : 0) - $tmp;
-                    if($value['number'] > $tmp_lock) {
-                        $return[] = [
-                            'id' => $value['id'],
-                            'product_id' => $value['product_id'],
-                            'number' => $value['number'] - ($tmp_lock > 0 ? $tmp_lock : 0),
-                        ];
-                    }
-                }else{
-                    $return[] = [
-                        'id' => $value['id'],
-                        'product_id' => $value['product_id'],
-                        'number' => $value['number'],
-                    ];
-                }
+                $num = bcsub($value['num'], $value['lock_number'],2);
+
+                $return[] = [
+                    'id' => $value['id'],
+                    'product_id' => $value['product_id'],
+                    'storehouse_id' => $value['storehouse_id'],
+                    'number' => $value['number'],
+                    'lock_number' => $value['lock_number'],
+                    'real_number' => $num,
+                ];
             }
         }
 
@@ -159,9 +114,14 @@ class ProductInventoryService extends Service
             ->toArray();
 
         //产品字典
+        $map = [];
         $pro = Product::whereIn('id',$product_id)
-            ->pluck('title','id')
-            ->toArray();
+            ->select('title','id','code')
+            ->get()->toArray();
+        foreach ($pro as $value){
+            $map[$value['id']] = $value;
+        }
+
         foreach ($product_submit as $key => $value){
             $tmp = explode(',',$key);
             //产品ID
@@ -170,8 +130,9 @@ class ProductInventoryService extends Service
             $storehouse_id = $tmp[1];
             $storehouse_title = $store_map[$storehouse_id] ?? "";
             //产品名称
-            $pro_title = $pro[$product_id] ?? '';
-            if(! $pro_title) return [false,'异常产品数据'];
+            $pro_tmp = $map[$product_id] ?? [];
+            if(empty($pro_tmp)) return [false,'异常产品数据'];
+            $pro_title = $pro_tmp['title'] . "( ". $pro_tmp['code'] .")";
             if(! isset($stock[$key])) return [false,'当前仓库' . $storehouse_title .' 的产品:'. $pro_title .'暂无库存'];
             //产品库存
             $stock_product = $stock[$key];

+ 2 - 2
app/Service/ReturnExchangeOrderService.php

@@ -191,10 +191,10 @@ class ReturnExchangeOrderService extends Service
                 "opt_case" => CheckService::six,
                 "menu_id" => $data['menu_id']
             ],$user);
-            if(! $status) return [true, '保存成功,退换货单提交失败,异常信息:' . $msg];
+//            if(! $status) return [true, '保存成功,退换货单提交失败,异常信息:' . $msg];
         }
 
-        return [true,''];
+        return [true, ["order" => ['order_number' => $data['order_number'], 'is_check_stock' => $user['is_check_stock']]]];
     }
 
     public function detail($data){

+ 25 - 0
config/excel/inventory.php

@@ -0,0 +1,25 @@
+<?php
+/**
+ * '菜单ID' => [
+ *     '字段英文名' =》 '字段中文名'
+ * ]
+ */
+
+return [
+    [
+        'key' => 'depart',
+        'value' => '* 门店名称',
+    ],
+    [
+        'key' => 'counted_number',
+        'value' => '* 盘点人工号',
+    ],
+    [
+        'key' => 'code',
+        'value' => '* 产品编码',
+    ],
+    [
+        'key' => 'counted_num',
+        'value' => '* 盘点数量',
+    ],
+];

+ 11 - 3
routes/api.php

@@ -178,7 +178,7 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('invoiceOrderList', 'Api\InvoiceOrderController@invoiceOrderList');
     $route->any('invoiceOrderEdit', 'Api\InvoiceOrderController@invoiceOrderEdit');
     $route->any('invoiceOrderDetail', 'Api\InvoiceOrderController@invoiceOrderDetail');
-    $route->any('invoiceOrderAdd', 'Api\InvoiceOrderController@invoiceOrderAdd');
+    $route->any('invoiceOrderAdd', 'Api\InvoiceOrderController@invoiceOrderAdd')->middleware('OrderDeal');
     $route->any('invoiceOrderDel', 'Api\InvoiceOrderController@invoiceOrderDel');
 
     //收货单
@@ -206,7 +206,7 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('constructionList', 'Api\ConstructionController@constructionList');
     $route->any('constructionEdit', 'Api\ConstructionController@constructionEdit')->middleware('OssFileDeal');
     $route->any('constructionDetail', 'Api\ConstructionController@constructionDetail');
-    $route->any('constructionAdd', 'Api\ConstructionController@constructionAdd')->middleware('OssFileDeal');
+    $route->any('constructionAdd', 'Api\ConstructionController@constructionAdd')->middleware('OrderDeal')->middleware('OssFileDeal');
     $route->any('constructionDel', 'Api\ConstructionController@constructionDel')->middleware('OssFileDeal');
     $route->any('constructionPdf', 'Api\ConstructionController@constructionPdf');
     $route->any('constructionOperation', 'Api\ConstructionController@constructionOperation');
@@ -221,7 +221,7 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('ReturnExchangeOrderList', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderList');
     $route->any('ReturnExchangeOrderEdit', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderEdit');
     $route->any('ReturnExchangeOrderDetail', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderDetail');
-    $route->any('ReturnExchangeOrderAdd', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderAdd');
+    $route->any('ReturnExchangeOrderAdd', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderAdd')->middleware('OrderDeal');
     $route->any('ReturnExchangeOrderDel', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderDel');
 
     //活动包 组合活动包
@@ -254,6 +254,14 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('paymentReceiptDel', 'Api\PaymentReceiptController@paymentReceiptDel')->middleware('OssFileDeal');
     $route->any('paymentReceiptDetail', 'Api\PaymentReceiptController@paymentReceiptDetail');
 
+    //盘点单
+    $route->any('inventoryList', 'Api\InventoryController@inventoryList');
+    $route->any('inventoryEdit', 'Api\InventoryController@inventoryEdit');
+    $route->any('inventoryDetail', 'Api\InventoryController@inventoryDetail');
+    $route->any('inventoryAdd', 'Api\InventoryController@inventoryAdd')->middleware('OrderDeal');
+    $route->any('inventoryDel', 'Api\InventoryController@inventoryDel');
+    $route->any('inventoryImport', 'Api\InventoryController@inventoryImport')->middleware('OrderDeal');
+
     //排班设置
     $route->any('scheduleList', 'Api\ScheduleController@getList');
     $route->any('scheduleEdit', 'Api\ScheduleController@edit');

+ 9 - 2
routes/wx.php

@@ -55,7 +55,7 @@ Route::group(['middleware'=> ['checkWx']],function ($route){
     $route->any('constructionList', 'Api\ConstructionController@constructionList');
     $route->any('constructionEdit', 'Api\ConstructionController@constructionEdit')->middleware('OssFileDeal');
     $route->any('constructionDetail', 'Api\ConstructionController@constructionDetail');
-    $route->any('constructionAdd', 'Api\ConstructionController@constructionAdd')->middleware('OssFileDeal');
+    $route->any('constructionAdd', 'Api\ConstructionController@constructionAdd')->middleware('OrderDeal')->middleware('OssFileDeal');
     $route->any('constructionDel', 'Api\ConstructionController@constructionDel')->middleware('OssFileDeal');
     $route->any('deliveryNoteList', 'Api\ConstructionController@deliveryNoteList');
     $route->any('deliveryNoteDetail', 'Api\ConstructionController@deliveryNoteDetail');
@@ -79,9 +79,16 @@ Route::group(['middleware'=> ['checkWx']],function ($route){
     $route->any('ReturnExchangeOrderList', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderList');
     $route->any('ReturnExchangeOrderEdit', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderEdit');
     $route->any('ReturnExchangeOrderDetail', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderDetail');
-    $route->any('ReturnExchangeOrderAdd', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderAdd');
+    $route->any('ReturnExchangeOrderAdd', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderAdd')->middleware('OrderDeal');
     $route->any('ReturnExchangeOrderDel', 'Api\ReturnExchangeOrderController@ReturnExchangeOrderDel');
 
+    //盘点单
+    $route->any('inventoryList', 'Api\InventoryController@inventoryList');
+    $route->any('inventoryEdit', 'Api\InventoryController@inventoryEdit');
+    $route->any('inventoryDetail', 'Api\InventoryController@inventoryDetail');
+    $route->any('inventoryAdd', 'Api\InventoryController@inventoryAdd')->middleware('OrderDeal');
+    $route->any('inventoryDel', 'Api\InventoryController@inventoryDel');
+
     //排班设置
     $route->any('scheduleList', 'Api\ScheduleController@getList');
     $route->any('scheduleEdit', 'Api\ScheduleController@edit');