cqp 4 maanden geleden
bovenliggende
commit
6d6be4ee24

+ 87 - 0
app/Http/Controllers/Api/OutBoundOrderController.php

@@ -0,0 +1,87 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Service\OutBoundOrderService;
+use Illuminate\Http\Request;
+
+class OutBoundOrderController extends BaseController
+{
+    public function add(Request $request)
+    {
+        $service = new OutBoundOrderService();
+        $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 edit(Request $request)
+    {
+        $service = new OutBoundOrderService();
+        $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 detail(Request $request)
+    {
+        $service = new OutBoundOrderService();
+        $userData = $request->userData->toArray();
+        list($status,$data) = $service->detail($request->all());
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function del(Request $request)
+    {
+        $service = new OutBoundOrderService();
+        $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 orderList(Request $request)
+    {
+        $service = new OutBoundOrderService();
+        $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);
+        }
+    }
+
+    public function outBoundGetProduct(Request $request)
+    {
+        $service = new OutBoundOrderService();
+        $userData = $request->userData->toArray();
+        list($status,$data) = $service->outBoundGetProduct($request->all(),$userData);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+}

+ 1 - 1
app/Http/Controllers/Api/ReturnExchangeOrderController.php

@@ -37,7 +37,7 @@ class ReturnExchangeOrderController extends BaseController
     {
         $service = new ReturnExchangeOrderService();
         $userData = $request->userData->toArray();
-        list($status,$data) = $service->detail($request->all());
+        list($status,$data) = $service->detail($request->all(),$userData);
 
         if($status){
             return $this->json_return(200,'',$data);

+ 13 - 0
app/Http/Controllers/Api/SalesOrderController.php

@@ -161,4 +161,17 @@ class SalesOrderController extends BaseController
             return $this->json_return(201,$data);
         }
     }
+
+    public function salesClickOut(Request $request)
+    {
+        $service = new SalesOrderService();
+        $userData = $request->userData->toArray();
+        list($status,$data) = $service->salesClickOut($request->all(),$userData);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
 }

+ 38 - 0
app/Model/OutBoundOrder.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace App\Model;
+
+class OutBoundOrder extends UseScopeBaseModel
+{
+    protected $table = "out_bound_order"; //指定表
+    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 = 'CK';
+    public static $name = [
+        self::State_minus_one => '已驳回',
+        self::STATE_ZERO => '待创建人确认',
+        self::STATE_ONE => '待审批人审核',
+        self::STATE_TWO => '审核通过',
+    ];
+
+    const range_function = '';
+    const is_check_function = '';
+
+    public static $wait_check = [
+        self::STATE_ZERO,
+        self::STATE_ONE
+    ];
+
+    const out_type_one = 1;
+    const out_type_two = 2;
+
+    public static $out_type = [
+        self::out_type_one,
+        self::out_type_two
+    ];
+}

+ 13 - 0
app/Model/OutBoundOrderInfo.php

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

+ 3 - 0
app/Model/SalesOrder.php

@@ -139,4 +139,7 @@ class SalesOrder extends UseScopeBaseModel
         self::Model_type_six => 'T9WM.',
         self::Model_type_seven => 'T9BT.',
     ];
+
+    const out_zero = 0;//未出库
+    const out_one = 1;//可出库
 }

+ 8 - 2
app/Service/CustomerService.php

@@ -521,7 +521,7 @@ class CustomerService extends Service
     public function customerCommonSearch($data,$user){
         $model = Customer::Clear($user,$data);
         $model = $model->where('del_time',0)
-            ->select('title','id','model_type','customer_intention','customer_from','customer_type','car_type','consulting_product','intention_product','progress_stage','address1','address2','crt_id','crt_time','mark','importance','company','company_short_name','depart_id','state_type','customer_state','pond_state','top_depart_id','fp_time','fp_top_depart_id')
+            ->select('title','id','model_type','customer_intention','customer_from','customer_type','car_type','consulting_product','intention_product','progress_stage','address1','address2','crt_id','crt_time','mark','importance','company','company_short_name','depart_id','state_type','customer_state','pond_state','top_depart_id','fp_time','fp_top_depart_id','enter_time')
             ->orderby('id', 'desc');
 
         if(! empty($data['title_t'])) {
@@ -591,6 +591,11 @@ class CustomerService extends Service
             $model->where('crt_time','>=',$return[0]);
             $model->where('crt_time','<=',$return[1]);
         }
+        if(! empty($data['enter_time'][0]) && ! empty($data['enter_time'][1])) {
+            $return = $this->changeDateToTimeStampAboutRange($data['enter_time']);
+            $model->where('enter_time','>=',$return[0]);
+            $model->where('enter_time','<=',$return[1]);
+        }
         if(! empty($data['crt_name'])){
             $id = (new RangeService())->crtNameSearch($data);
             $model->whereIn('crt_id',$id);
@@ -665,7 +670,7 @@ class CustomerService extends Service
         $model = Customer::Clear($user,$data);
         $model = $model->where('del_time',0)
             ->where('fp_time','>',0)
-            ->select('title','id','model_type','customer_intention','customer_from','customer_type','car_type','consulting_product','intention_product','progress_stage','address1','address2','crt_id','crt_time','mark','importance','company','company_short_name','depart_id','state_type','customer_state','pond_state','top_depart_id','fp_time','fp_top_depart_id')
+            ->select('title','id','model_type','customer_intention','customer_from','customer_type','car_type','consulting_product','intention_product','progress_stage','address1','address2','crt_id','crt_time','mark','importance','company','company_short_name','depart_id','state_type','customer_state','pond_state','top_depart_id','fp_time','fp_top_depart_id','enter_time')
             ->orderby('fp_time', 'desc');
 
         if(! empty($data['my_fz']) || ! empty($data['my_xt'])){
@@ -953,6 +958,7 @@ class CustomerService extends Service
             $data['data'][$key]['customer_state_title'] = $basic_map[$value['customer_state']] ?? '';
             $data['data'][$key]['depart_title'] = $depart_title[$value['depart_id']] ?? '';
             $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
+            $data['data'][$key]['enter_time'] = $value['enter_time'] ? date('Y-m-d',$value['enter_time']) : '';
             $data['data'][$key]['fp_time'] = $value['fp_time'] ? date('Y-m-d H:i:s',$value['fp_time']) : '';
             $data['data'][$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
             $customer_tmp = $customer_info_map[$value['id']] ?? [];

+ 1 - 1
app/Service/ExportFileService.php

@@ -1313,7 +1313,7 @@ class ExportFileService extends Service
 
         DB::table('customer')
             ->whereIn('id', $id)
-            ->select('title','id','model_type','customer_intention','customer_from','customer_type','car_type','consulting_product','intention_product','progress_stage','address1','address2','crt_id','crt_time','mark','importance','company','company_short_name','depart_id','state_type','customer_state','pond_state','top_depart_id','fp_time','fp_top_depart_id')
+            ->select('title','id','model_type','customer_intention','customer_from','customer_type','car_type','consulting_product','intention_product','progress_stage','address1','address2','crt_id','crt_time','mark','importance','company','company_short_name','depart_id','state_type','customer_state','pond_state','top_depart_id','fp_time','fp_top_depart_id','enter_time')
             ->orderBy('id','desc')
             ->chunk(200,function ($data) use(&$return,$user){
                 $data = Collect($data)->map(function ($object) {

+ 424 - 0
app/Service/OutBoundOrderService.php

@@ -0,0 +1,424 @@
+<?php
+
+namespace App\Service;
+
+use App\Model\Depart;
+use App\Model\Employee;
+use App\Model\OutBoundOrder;
+use App\Model\OutBoundOrderInfo;
+use App\Model\ReturnExchangeOrder;
+use App\Model\ReturnExchangeOrderProductInfo;
+use App\Model\SalesOrder;
+use App\Model\SalesOrderProductInfo;
+use App\Model\Storehouse;
+use Illuminate\Support\Facades\DB;
+
+class OutBoundOrderService extends Service
+{
+    public function edit($data,$user){
+        list($status,$msg) = $this->orderRule($data,$user,false);
+        if(!$status) return [$status,$msg];
+
+        try{
+            DB::beginTransaction();
+            $material_model = OutBoundOrder::where('order_number',$data['order_number'])->first();
+            $material_model->data_id = $data['data_id'];
+            $material_model->type = $data['type'];
+            $material_model->out_id = $data['out_id'];
+            $material_model->mark = $data['mark'] ?? "";
+            $material_model->storehouse_id = $data['storehouse_id'];
+            $material_model->save();
+
+            OutBoundOrderInfo::where('order_number',$data['order_number'])
+                ->where('del_time',0)
+                ->update(['del_time' => time()]);
+            if(! empty($data['product'])){
+                $sub = [];
+                foreach ($data['product'] as $value){
+                    $sub[] = [
+                        'invoice_id' => $material_model->id,
+                        'order_number' => $data['order_number'],
+                        'storehouse_id' => $data['storehouse_id'] ?? 0,
+                        'product_id' => $value['product_id'],
+                        'number' => $value['number'],
+                        'price' => $value['price'] ?? 0,
+                        'final_amount' => $value['final_amount'] ?? 0,
+                    ];
+                }
+                OutBoundOrderInfo::insert($sub);
+
+                //锁定库存
+                ProductInventoryService::changeLockNumber($user, $msg[0],$msg[1]);
+            }
+
+            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();
+            $material_model = new OutBoundOrder();
+            $material_model->order_number = $data['order_number'];
+            $material_model->data_id = $data['data_id'];
+            $material_model->type = $data['type'];
+            $material_model->out_id = $data['out_id'];
+            $material_model->depart_id = $data['depart_id'] ?? 0;
+            $material_model->top_depart_id = $data['top_depart_id'] ?? 0;
+            $material_model->mark = $data['mark'] ?? "";
+            $material_model->crt_id = $user['id'];
+            $material_model->storehouse_id = $data['storehouse_id'];
+            $material_model->save();
+
+            if(!empty($data['product'])){
+                $sub = [];
+                foreach ($data['product'] as $value){
+                    $sub[] = [
+                        'out_bound_id' => $material_model->id,
+                        'order_number' => $data['order_number'],
+                        'storehouse_id' => $data['storehouse_id'] ?? 0,
+                        'product_id' => $value['product_id'],
+                        'number' => $value['number'],
+                        'price' => $value['price'] ?? 0,
+                        'final_amount' => $value['final_amount'] ?? 0,
+                    ];
+                }
+                OutBoundOrderInfo::insert($sub);
+
+                //锁定库存
+                ProductInventoryService::changeLockNumber($user,$msg[0],[]);
+            }
+
+            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()];
+        }
+
+        if(! empty($data['check'])) {
+            list($status,$msg) = (new CheckService())->checkAll([
+                "id" => $material_model->id,
+                "order_number" => $data['order_number'],
+                "opt_case" => CheckService::sixteen,
+                "menu_id" => $data['menu_id']
+            ],$user);
+//            if(! $status) return [true, '保存成功,施工单确认失败,异常信息:' . $msg];
+        }
+
+        return [true, ["order" => ['order_number' => $data['order_number'], 'is_check_stock' => $data['is_check_stock']]]];
+    }
+
+    public function detail($data){
+        if($this->isEmpty($data,'order_number')) return [false,'请选择数据'];
+
+        $order = OutBoundOrder::where('order_number',$data['order_number'])
+            ->where('del_time',0)
+            ->first();
+        if(empty($order)) return [false, '出库单不存在或已被删除'];
+        $order = $order->toArray();
+        $order['storehouse_title'] = Storehouse::where('id',$order['storehouse_id'])->value('title');
+        $order['state_title'] = OutBoundOrder::$name[$order['state']] ?? '';
+
+        $emp_map = Employee::whereIn('id',array_unique(array_merge_recursive([$order['crt_id']],[$order['out_id']])))
+            ->pluck('emp_name','id')
+            ->toArray();
+        $info = OutBoundOrderInfo::where('del_time',0)
+            ->where('order_number',$data['order_number'])
+            ->get()->toArray();
+        $map = (new ProductService())->getProductDetail(array_column($info,'product_id'));
+        foreach ($info as $value){
+            $tmp = $map[$value['product_id']] ?? [];
+            $value['title'] = $tmp['title'] ?? "";
+            $value['code'] = $tmp['code'] ?? "";
+            $value['size'] = $tmp['size'] ?? "";
+            $value['unit'] = $tmp['unit'] ?? "";
+            $value['bar_code'] = $tmp['bar_code'] ?? "";
+            $order['product'][] = $value;
+        }
+        $order['out_name'] = $emp_map[$order['out_id']] ?? '';
+        $order['crt_name'] = $emp_map[$order['crt_id']] ?? '';
+        $order['crt_time'] = $order['crt_time'] ? date("Y-m-d H:i:s",$order['crt_time']): '';
+
+        //可见范围
+//        $return = (new RangeService())->RangeDetail($order['id'],SeeRange::type_three);
+//        $order['depart'] = $return[0] ?? [];
+//        $order['employee'] = $return[1] ?? [];
+
+        return [true, $order];
+    }
+
+    public function del($data, $user){
+        if($this->isEmpty($data,'order_number')) return [false,'请选择数据'];
+
+        $order = OutBoundOrder::where('order_number',$data['order_number'])
+            ->first();
+        if(empty($order)) return [false,'出库单不存在或已被删除'];
+        $order = $order->toArray();
+        if($order['state'] > OutBoundOrder::STATE_ZERO) return [false,'请确认出库单状态,删除失败'];
+
+        $product_save = $this->getSaveDetail($data['id']);
+        try{
+            DB::beginTransaction();
+            OutBoundOrder::where('order_number',$data['order_number'])->update([
+                'del_time'=>time()
+            ]);
+            OutBoundOrderInfo::where('order_number',$data['order_number'])->update([
+                'del_time'=>time()
+            ]);
+//            (new RangeService())->RangeDelete($order['id'],SeeRange::type_three);
+            //锁定库存释放
+            ProductInventoryService::changeLockNumber($user,[],$product_save);
+
+            DB::commit();
+        }catch (\Throwable $e){
+            DB::rollBack();
+            return [false,$e->getMessage()];
+        }
+
+        return [true,''];
+    }
+
+    public function getList($data,$user){
+        $model = OutBoundOrder::Clear($user,$data);
+        $model = $model->where('del_time',0)
+            ->select('id','order_number','data_id','type','crt_id','mark','state','crt_time','storehouse_id','top_depart_id','storehouse_id','out_id')
+            ->orderby('id', 'desc');
+        if(! empty($data['order_number'])) $model->where('order_number', 'LIKE', '%'.$data['order_number'].'%');
+        if(isset($data['state'])) $model->where('state',$data['state']);
+        if(! empty($data['crt_time'][0]) && ! empty($data['crt_time'][1])) {
+            $return = $this->changeDateToTimeStampAboutRange($data['crt_time']);
+            $model->whereBetween('crt_time',[$return[0],$return[1]]);
+        }
+
+        if(! empty($data['sale_order'])){
+            $sale_order_number = $data['sale_order'] ?? "";
+            $model2 = SalesOrder::Clear($user,$data);
+            $sale = $model2->where('del_time',0)
+                ->when(! empty($sale_order_number), function ($query) use ($sale_order_number) {
+                    return $query->where('order_number', 'LIKE', '%'.$sale_order_number.'%');
+                })
+                ->select('id')
+                ->get()->toArray();
+            $model->whereIn('data_id',array_unique(array_column($sale,'id')))
+                ->where('type', OutBoundOrder::out_type_one);
+        }
+
+        $list = $this->limit($model,'',$data);
+        $list = $this->fillListData($list);
+
+        return [true, $list];
+    }
+
+    public function fillListData($data){
+        if(empty($data['data'])) return $data;
+
+        $depart_id = array_unique(array_column($data['data'],'depart_id'));
+        $depart_map = Depart::whereIn('id',$depart_id)
+            ->pluck('title','id')
+            ->toArray();
+
+        $emp_id = array_unique(array_merge_recursive(array_column($data['data'],'crt_id'),array_column($data['data'],'out_id')));
+        $emp_map = Employee::whereIn('id',$emp_id)
+            ->pluck('emp_name','id')
+            ->toArray();
+
+        $sales = SalesOrder::whereIn('id',array_unique(array_column($data['data'],'sales_order_id')))->select('order_number','id','contact_order_no')->get()->toArray();
+        $sales = array_column($sales,null,'id');
+        $storehouse = Storehouse::whereIn('id',array_unique(array_column($data['data'],'storehouse_id')))
+            ->pluck('title','id')
+            ->toArray();
+        foreach ($data['data'] as $key => $value){
+            $data['data'][$key]['crt_time'] = $value['crt_time'] ? date("Y-m-d H:i:s",$value['crt_time']) : '';
+            $data['data'][$key]['depart_name'] = $depart_map[$value['depart_id']] ?? '';
+            $data['data'][$key]['crt_name'] = $emp_map[$value['crt_id']] ?? '';
+            $data['data'][$key]['out_name'] = $emp_map[$value['out_id']] ?? '';
+            $data['data'][$key]['state_title'] = OutBoundOrder::$name[$value['state']] ?? '';
+            $tmp = $sales[$value['sales_order_id']] ?? [];
+            $data['data'][$key]['sales_order_number'] = $tmp['order_number'] ?? '';
+            $data['data'][$key]['storehouse_title'] = $storehouse[$value['storehouse_id']] ?? '';
+        }
+
+        return $data;
+    }
+
+    public function orderRule(&$data, $user, $is_check = true){
+        if(empty($data['storehouse_id'])) return [false, '仓库不能为空'];
+        if(empty($data['product'])) return [false, '发货数据不能为空'];
+        if(empty($data['data_id'])) return [false, '发货数据源id不能为空'];
+        if(empty($data['type'])) return [false, '发货类型不能为空'];
+        if(empty($data['out_id'])) $data['out_id'] = $user['id'];
+
+        $product_submit = $product_id = [];
+        foreach ($data['product'] as $value){
+            if(empty($value['product_id'])) return [false, '发货产品不能为空'];
+            if(empty($value['number'])) return [false, '发货产品数量不能为空'];
+            $res = $this->checkNumber($value['number']);
+            if(! $res) return [false,'请输入正确的产品数量'];
+            if(! isset($value['price'])) return [false, '发货产品单价不能为空'];
+            if(! isset($value['final_amount'])) return [false, '发货产品总价值不能为空'];
+
+            $key = $value['product_id'] . ',' .$data['storehouse_id'];
+            if(isset($product_submit[$key])){
+                $product_submit[$key] += $value['number'];
+            }else{
+                $product_submit[$key] = $value['number'];
+            }
+            $product_id[] = $value['product_id'];
+        }
+
+        //剩余能发
+        $id = $data['id'] ?? 0;
+        if($data['type'] == OutBoundOrder::out_type_one) $s_product = $this->getSalesProduct(['out_bound_id' => $id, 'data_id' => $data['data_id']], $user);
+
+        //比较
+        foreach ($product_submit as $pro => $number){
+            $tmp = explode(',',$pro);
+            $p = $tmp[0];
+            if(! isset($s_product[$p])) return [false,'产品错误,合同中不存在该产品'];
+            $s_number = $s_product[$p];
+
+            if($number > $s_number) return [false,'发货产品数量不能超过合同产品数量'];
+        }
+
+        //已保存
+        $product_save = $this->getSaveDetail($id);
+
+        //校验库存
+        list($status,$msg) = (new ProductInventoryService())->compareStock($user,$product_id, $product_submit, $product_save);
+        if(! $status) return [false, $msg];
+
+        //所属部门 以及  顶级部门
+        if(empty($data['depart_id'])) {
+            $data['depart_id'] = $this->getDepart($user);
+            $data['top_depart_id'] = $user['depart_map'][$data['depart_id']] ?? 0;
+        }
+
+        $data['is_check_stock'] = $user['is_check_stock'];
+
+        if($is_check){
+            $order_number = (new OrderNoService())->createOrderNumber(OutBoundOrder::prefix);
+            if(empty($order_number)) return [false,'出库单号生成失败!'];
+            $data['order_number'] = $order_number;
+        }else{
+            if($this->isEmpty($data,'id')) return [false,'出库单ID不能为空!'];
+            if($this->isEmpty($data,'order_number')) return [false,'出库单号不能为空!'];
+        }
+
+        return [true, [$product_submit, $product_save]];
+    }
+
+    public function outBoundGetProduct($data, $user){
+        if(empty($data['data_id'])) return [false, '合同ID不能为空'];
+        $data_id = $data['data_id'];
+        $out_bound_id = $data['out_bound_id'] ?? 0;
+        if(empty($data['type'])) return [false, '出库类型不能为空'];
+        if(! in_array($data['type'], OutBoundOrder::$out_type)) return [false, '出库类型不存在'];
+
+        // 合同 发货
+        $return = [];
+        if($data['type'] == OutBoundOrder::out_type_one) $this->getSalesProduct($data, $user);
+
+        return [true, $return];
+    }
+
+    public function getSalesProduct($data, $user){
+        $return = [];
+        $data_id = $data['data_id'];
+        $out_bound_id = $data['out_bound_id'] ?? 0;
+        $product = SalesOrderProductInfo::where('del_time',0)
+            ->where('sales_order_id', $data_id)
+            ->select('product_id', 'number', 'final_amount','price')
+            ->get()->toArray();
+        $map = (new ProductService())->getProductDetail(array_column($product,'product_id'));
+
+        $product_map = [];
+        $save = OutBoundOrderInfo::where('del_time',0)
+            ->where('type', $data['type'])
+            ->where('id', $data_id)
+            ->when(! empty($out_bound_id), function ($query) use ($out_bound_id) {
+                return $query->where('out_bound_id', '<>', $out_bound_id);
+            })
+            ->select('product_id', 'number', 'final_amount')
+            ->get()->toArray();
+        foreach ($save as $value){
+            if(isset($product_map[$value['product_id']])){
+                $number = bcadd($value['number'], $product_map[$value['product_id']]);
+                $product_map[$value['product_id']] = $number;
+            }else{
+                $product_map[$value['product_id']] = $value['number'];
+            }
+        }
+
+        $product_map2 = [];
+        $return_id = ReturnExchangeOrder::where('del_time',0)
+            ->where('type', ReturnExchangeOrder::Order_type)
+            ->where('model_type', ReturnExchangeOrder::Model_type_one)
+            ->where('data_id', $data_id)
+            ->select('id')
+            ->get()->toArray();
+        $save2 = ReturnExchangeOrderProductInfo::where('del_time',0)
+            ->whereIn('return_exchange_id', array_column($return_id,'id'))
+            ->where('return_or_exchange',ReturnExchangeOrderProductInfo::type_one)
+            ->select('product_id', 'number', 'final_amount')
+            ->get()->toArray();
+        foreach ($save2 as $value){
+            if(isset($product_map2[$value['product_id']])){
+                $number = bcadd($value['number'], $product_map2[$value['product_id']]);
+                $product_map2[$value['product_id']] = $number;
+            }else{
+                $product_map2[$value['product_id']] = $value['number'];
+            }
+        }
+
+        foreach ($product as $value){
+            $p1 = $product_map[$value['product_id']] ?? 0;
+            $p2 = $product_map2[$value['product_id']] ?? 0;
+            $number = bcadd(bcsub($value['number'], $p1), $p2);
+            if($number <= 0) continue;
+
+            $tmp = $map[$value['product_id']] ?? [];
+            $return[] = [
+                'number' => $number,
+                'price' => $value['price'],
+                'final_amount' => bcmul($value['price'], $number,2),
+                'product_id' => $value['product_id'],
+                'title' => $tmp['title'] ?? "",
+                'code' => $tmp['code'] ?? "",
+                'size' => $tmp['size'] ?? "",
+                'unit' => $tmp['unit'] ?? "",
+            ];
+        }
+
+        return $return;
+    }
+
+    public function getSaveDetail($id){
+        $product_save = [];
+        if(empty($id)) return $product_save;
+
+        $sub = OutBoundOrderInfo::where('out_bound_id',$id)
+            ->where('del_time',0)
+            ->get()->toArray();
+        foreach ($sub as $value){
+            $key = $value['product_id'] . ',' . $value['storehouse_id'];
+            if(isset($product_save[$key])){
+                $product_save[$key] += $value['number'];
+            }else{
+                $product_save[$key] = $value['number'];
+            }
+        }
+
+        return $product_save;
+    }
+}

+ 2 - 0
app/Service/ProductInventoryService.php

@@ -11,6 +11,7 @@ use App\Model\Inventory;
 use App\Model\InvoiceOrder;
 use App\Model\InvoiceOrderInfo;
 use App\Model\OrderOperation;
+use App\Model\OutBoundOrder;
 use App\Model\Product;
 use App\Model\ProductCategory;
 use App\Model\ProductInventory;
@@ -321,6 +322,7 @@ class ProductInventoryService extends Service
         $array[InvoiceOrder::prefix] = '发货单';
         $array[PurchaseOrder::prefix] = '采购单';
         $array[Inventory::prefix] = '盘点单';
+        $array[OutBoundOrder::prefix] = '出库单';
 
         return $array;
     }

+ 48 - 32
app/Service/PurchaseOrderService.php

@@ -261,9 +261,51 @@ class PurchaseOrderService extends Service
             ->toArray();
         $order['purchase_title'] = $emp_map[$order['purchase_id']] ?? '';
 
-        $p_info = PurchaseOrderInfo::where('del_time',0)
+        // 填充产品
+        list($product, $activity_product) = $this->purchaseFillDetailProduct($order);
+        $order['product'] = $product;
+        $order['activity_product'] = $activity_product;
+
+        $file = PurchaseOrderFile::where('del_time',0)
             ->where('order_number',$data['order_number'])
             ->get()->toArray();
+        $fileUploadService = new FileUploadService();
+        foreach ($file as $value){
+            if($value['type'] == PurchaseOrderFile::type_one){
+                $tmp = [
+                    'url' => $value['file'],
+                    'name' => $value['name'],
+                    'show_url' => $fileUploadService->getFileShow($value['file']),
+                ];
+                $order['file'][] = $tmp;
+            }
+        }
+        $order['crt_name'] = $emp_map[$order['crt_id']] ?? '';
+        $order['crt_time'] = $order['crt_time'] ? date("Y-m-d H:i:s",$order['crt_time']): '';
+
+        $state_array = $this->getStateMake([$order]);
+        $order['state_title'] = $this->makeState($order,$state_array);
+
+        //可见范围
+        $return = (new RangeService())->RangeDetail($order['id'],SeeRange::type_five);
+        $order['depart'] = $return[0] ?? [];
+        $order['employee'] = $return[1] ?? [];
+
+        //对应的分社订货合同
+        $order['sales_order_number2'] = SalesOrder::where('del_time',0)->where('contact_order_no',$data['order_number'])->value('order_number') ?? "";
+
+        //回款信息
+        $this->purchaseFillDetailPayment($order);
+
+        return [true, $order];
+    }
+
+    public function purchaseFillDetailProduct($order){
+        $product = $activity_product = [];
+
+        $p_info = PurchaseOrderInfo::where('del_time',0)
+            ->where('order_number',$order['order_number'])
+            ->get()->toArray();
         $sports_bag_id = array_unique(array_column($p_info,'sports_bag_id'));
         $bag = SportsBag::whereIn('id',$sports_bag_id)->get()->toArray();
         $bag_pro = SportsBagProductInfo::where('del_time',0)->whereIn('sports_bag_id',$sports_bag_id)
@@ -314,42 +356,18 @@ class PurchaseOrderService extends Service
                 $value['unit'] = $tmp['unit'] ?? "";
                 $value['bar_code'] = $tmp['bar_code'] ?? "";
                 $value['basic_type_title'] = $basic_price[$value['basic_type_id']] ?? "";
-                $order['product'][] = $value;
+                $product[] = $value;
             }
         }
         foreach ($sports_bag_arr as $key => $value){
             $value['product'] = $sports_bag_pro[$key] ?? [];
-            $order['activity_product'][] = $value;
-        }
-
-        $file = PurchaseOrderFile::where('del_time',0)
-            ->where('order_number',$data['order_number'])
-            ->get()->toArray();
-        $fileUploadService = new FileUploadService();
-        foreach ($file as $value){
-            if($value['type'] == PurchaseOrderFile::type_one){
-                $tmp = [
-                    'url' => $value['file'],
-                    'name' => $value['name'],
-                    'show_url' => $fileUploadService->getFileShow($value['file']),
-                ];
-                $order['file'][] = $tmp;
-            }
+            $activity_product[] = $value;
         }
-        $order['crt_name'] = $emp_map[$order['crt_id']] ?? '';
-        $order['crt_time'] = $order['crt_time'] ? date("Y-m-d H:i:s",$order['crt_time']): '';
-
-        $state_array = $this->getStateMake([$order]);
-        $order['state_title'] = $this->makeState($order,$state_array);
-
-        //可见范围
-        $return = (new RangeService())->RangeDetail($order['id'],SeeRange::type_five);
-        $order['depart'] = $return[0] ?? [];
-        $order['employee'] = $return[1] ?? [];
 
-        //对应的分社订货合同
-        $order['sales_order_number2'] = SalesOrder::where('del_time',0)->where('contact_order_no',$data['order_number'])->value('order_number') ?? "";
+        return [$product, $activity_product];
+    }
 
+    public function purchaseFillDetailPayment(&$order){
         //退换货信息
         $order['return_exchange'] = (new ReturnExchangeOrderService())->getDifferentAmount($order['id'],ReturnExchangeOrder::Order_type2);
         $order['return_exchange_amount'] = 0;
@@ -366,8 +384,6 @@ class PurchaseOrderService extends Service
         //回款单信息 审核过的
 
         $order['not_payment_receipt_amount'] =  bcsub($order['purchase_total'],$order['payment_receipt_list']['not_confirm_receipt_amount'],2);
-
-        return [true, $order];
     }
 
     /**

+ 48 - 30
app/Service/ReturnExchangeOrderService.php

@@ -198,7 +198,7 @@ class ReturnExchangeOrderService extends Service
         return [true, ["order" => ['order_number' => $data['order_number'], 'is_check_stock' => $user['is_check_stock']]]];
     }
 
-    public function detail($data){
+    public function detail($data,$user){
         if(empty($data['id']) && empty($data['order_number'])) return [false,'请选择数据!'];
 
         if(! empty($data['id'])){
@@ -217,14 +217,6 @@ class ReturnExchangeOrderService extends Service
         $order['storehouse_title'] = "";
         if($order['storehouse_id'] > 0) $order['storehouse_title'] = Storehouse::where('id',$order['storehouse_id'])->value('title');
 
-        if($order['type'] == ReturnExchangeOrder::Order_type){
-            $sales = SalesOrder::where('id',$order['data_id'])->value('order_number');
-            $order['data_title'] = $sales;
-        }elseif($order['type'] == ReturnExchangeOrder::Order_type2){
-            $sales = PurchaseOrder::where('id',$order['data_id'])->value('order_number');
-            $order['data_title'] = $sales;
-        }
-
         $order['model_type_title'] = ReturnExchangeOrder::$model_type_name[$order['model_type']] ?? "";
 
         $order['product_one'] = $order['product_two'] = $order['depart'] = $order['employee'] = [];
@@ -260,6 +252,32 @@ class ReturnExchangeOrderService extends Service
         $order['depart'] = $return[0] ?? [];
         $order['employee'] = $return[1] ?? [];
 
+        $order['related_orders'] = [];
+        //关联订单信息
+        if($order['type'] == ReturnExchangeOrder::Order_type){
+            $sales = SalesOrder::where('id',$order['data_id'])->value('order_number');
+            $order['data_title'] = $sales;
+            list($status, $msg) = (new SalesOrderService())->detail(['id' => $order['data_id']], $user);
+            if($status){
+                $order['related_orders'] = [
+                    'product' => $msg['product'],
+                    'activity_product' => $msg['activity_product'],
+                    'payment_receipt_list' => $msg['payment_receipt_list'],
+                ];
+            }
+        }elseif($order['type'] == ReturnExchangeOrder::Order_type2){
+            $sales = PurchaseOrder::where('id',$order['data_id'])->value('order_number');
+            $order['data_title'] = $sales;
+            list($status, $msg) = (new PurchaseOrderService())->detail(['order_number' => $sales], $user);
+            if($status){
+                $order['related_orders'] = [
+                    'product' => $msg['product'],
+                    'activity_product' => $msg['activity_product'],
+                    'payment_receipt_list' => $msg['payment_receipt_list'],
+                ];
+            }
+        }
+
         return [true, $order];
     }
 
@@ -576,30 +594,30 @@ class ReturnExchangeOrderService extends Service
             }
 
             //换货
-            $product_id = [];
-            if($data['model_type'] == ReturnExchangeOrder::Model_type_two){
-                if(empty($data['product_two'])) return [false,'换货产品不能为空'];
-                foreach ($data['product_two'] as $value){
-                    if(empty($value['number'])) return [false,'换货产品数量不能为空'];
-                    $res = $this->checkNumber($value['number']);
-                    if(! $res) return [false,'请输入正确的换货产品数量'];
-
-                    $key = $value['product_id'] . ',' .$data['storehouse_id'];
-                    if(isset($product_submit_minus[$key])){
-                        $product_submit_minus[$key] += $value['number'];
-                    }else{
-                        $product_submit_minus[$key] = $value['number'];
-                    }
-                    $product_id[] = $value['product_id'];
-                }
-
-                //是否校验库存
-                ProductInventoryService::is_check($user,$data);
-
+//            $product_id = [];
+//            if($data['model_type'] == ReturnExchangeOrder::Model_type_two){
+//                if(empty($data['product_two'])) return [false,'换货产品不能为空'];
+//                foreach ($data['product_two'] as $value){
+//                    if(empty($value['number'])) return [false,'换货产品数量不能为空'];
+//                    $res = $this->checkNumber($value['number']);
+//                    if(! $res) return [false,'请输入正确的换货产品数量'];
+//
+//                    $key = $value['product_id'] . ',' .$data['storehouse_id'];
+//                    if(isset($product_submit_minus[$key])){
+//                        $product_submit_minus[$key] += $value['number'];
+//                    }else{
+//                        $product_submit_minus[$key] = $value['number'];
+//                    }
+//                    $product_id[] = $value['product_id'];
+//                }
+//
+//                //是否校验库存
+//                ProductInventoryService::is_check($user,$data);
+//
 //                $product_save_minus = $this->getSaveDetailMinus($id);
 //                list($status,$msg) = (new ProductInventoryService())->compareStock($user,$product_id, $product_submit_minus, $product_save_minus);
 //                if(! $status) return [false, $msg];
-            }
+//            }
         }
 
         if($is_check){

+ 49 - 16
app/Service/SalesOrderService.php

@@ -672,6 +672,30 @@ class SalesOrderService extends Service
             }
         }
 
+        // 填充产品
+        list($product, $activity_product) = $this->salesFillDetailProduct($sales);
+        $sales['product'] = $product;
+        $sales['activity_product'] = $activity_product;
+
+        $sales['crt_time'] = $sales['crt_time'] ? date("Y-m-d H:i:s",$sales['crt_time']): '';
+        $sales['dispatch_time_first'] = $sales['dispatch_time_first'] ? date("Y-m-d H:i:s",$sales['dispatch_time_first']): '';
+        $sales['dispatch_time_second'] = $sales['dispatch_time_second'] ? date("Y-m-d H:i:s",$sales['dispatch_time_second']): '';
+
+        //派单后数据 也就是可见范围
+        $return = (new RangeService())->RangeDetail($sales['id'],SeeRange::type_seven);
+        $sales['dispatch_depart_one'] = $return[0] ?? [];
+        $sales['dispatch_employee'] = $return[1] ?? [];
+        $sales['dispatch_depart_two'] = $return[2] ?? [];
+
+        //回款单信息 审核过的
+        $this->salesFillDetailPayment($sales);
+
+        return [true, $sales];
+    }
+
+    public function salesFillDetailProduct($sales){
+        $product = $activity_product = [];
+
         $sales_p_info = SalesOrderProductInfo::where('del_time',0)
             ->where('sales_order_id',$sales['id'])
             ->get()->toArray();
@@ -724,25 +748,20 @@ class SalesOrderService extends Service
                 $value['unit'] = $tmp['unit'] ?? "";
                 $value['bar_code'] = $tmp['bar_code'] ?? "";
                 $value['basic_type_title'] = $basic_price[$value['basic_type_id']] ?? "";
-                $sales['product'][] = $value;
+                $product[] = $value;
             }
         }
         foreach ($sports_bag_arr as $key => $value){
             $value['product'] = $sports_bag_pro[$key] ?? [];
-            $sales['activity_product'][] = $value;
+            $activity_product[] = $value;
         }
-        $sales['crt_time'] = $sales['crt_time'] ? date("Y-m-d H:i:s",$sales['crt_time']): '';
-        $sales['dispatch_time_first'] = $sales['dispatch_time_first'] ? date("Y-m-d H:i:s",$sales['dispatch_time_first']): '';
-        $sales['dispatch_time_second'] = $sales['dispatch_time_second'] ? date("Y-m-d H:i:s",$sales['dispatch_time_second']): '';
 
-        //派单后数据 也就是可见范围
-        $return = (new RangeService())->RangeDetail($data['id'],SeeRange::type_seven);
-        $sales['dispatch_depart_one'] = $return[0] ?? [];
-        $sales['dispatch_employee'] = $return[1] ?? [];
-        $sales['dispatch_depart_two'] = $return[2] ?? [];
+        return [$product, $activity_product];
+    }
 
+    public function salesFillDetailPayment(&$sales){
         //退换货信息
-        $sales['return_exchange'] = (new ReturnExchangeOrderService())->getDifferentAmount($data['id']);
+        $sales['return_exchange'] = (new ReturnExchangeOrderService())->getDifferentAmount($sales['id']);
         $sales['return_exchange_amount'] = 0;
         foreach ($sales['return_exchange'] as $value){
             if($value['state'] == ReturnExchangeOrder::State_two)  $sales['return_exchange_amount'] += $value['difference_amount'];
@@ -757,8 +776,6 @@ class SalesOrderService extends Service
         //回款单信息 审核过的
 
         $sales['not_payment_receipt_amount'] = bcsub($sales['contract_fee'],$sales['payment_receipt_list']['not_confirm_receipt_amount'],2);
-
-        return [true, $sales];
     }
 
     public function salesOrderCommon($data,$user){
@@ -2197,13 +2214,29 @@ class SalesOrderService extends Service
         return [true, array_values($return)];
     }
 
-    public function saveOutData($data, $user){
+    //销售点击出库
+    public function salesClickOut($data, $user){
         if(empty($data['id'])) return [false, '合同ID不能为空'];
-        if(empty($data['type'])) return [false, '出库类型不能为空'];
 
-        SalesOrder::where('del_time',0)
+        $sales = SalesOrder::where('del_time',0)
             ->where('id',$data['id'])
             ->first();
+        if(empty($sales)) return [false, '合同不存在或已被删除'];
+        $sales = $sales->toArray();
+        if($sales['state'] < SalesOrder::State_two) return [false, '合同未审核通过'];
+        if($sales['out_state'] > SalesOrder::out_zero) return [false, '合同已出库'];
 
+        try {
+            DB::beginTransaction();
+
+            SalesOrder::where('id',$sales['id'])->update(['out_state' => SalesOrder::out_one]);
+
+            DB::commit();
+        }catch (\Throwable $exception){
+            DB::rollBack();
+            return [false, $exception->getMessage()];
+        }
+
+        return [true, ''];
     }
 }

+ 1 - 1
config/header/16.php

@@ -63,7 +63,7 @@ return [
         'value' => '特殊备注',
     ],
     [
-        'key' => 'crt_time',
+        'key' => 'enter_time',
         'value' => '创建时间',
     ],
     [

+ 3 - 0
config/morequery.php

@@ -2,6 +2,9 @@
 
 return [
     "menu" => [
+        "api/outBoundOrderList" => 55,
+        "api/outBoundOrderEdit" => 55,
+        "api/outBoundOrderAdd" => 55,
         "api/customerList" => 16,
         "api/customerAdd" => 16,
         "api/customerEdit" => 16,

+ 9 - 0
routes/api.php

@@ -185,6 +185,14 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('invoiceOrderAdd', 'Api\InvoiceOrderController@invoiceOrderAdd')->middleware('OrderDeal');
     $route->any('invoiceOrderDel', 'Api\InvoiceOrderController@invoiceOrderDel');
 
+    //出库单
+    $route->any('outBoundOrderList', 'Api\OutBoundOrderController@getList');
+    $route->any('outBoundOrderEdit', 'Api\OutBoundOrderController@edit');
+    $route->any('outBoundOrderDetail', 'Api\OutBoundOrderController@detail');
+    $route->any('outBoundOrderAdd', 'Api\OutBoundOrderController@add')->middleware('OrderDeal');
+    $route->any('outBoundOrderDel', 'Api\OutBoundOrderController@del');
+    $route->any('outBoundGetProduct', 'Api\OutBoundOrderController@outBoundGetProduct');
+
     //收货单
     $route->any('takeOrderList', 'Api\TakeOrderController@takeOrderList');
     $route->any('takeOrderEdit', 'Api\TakeOrderController@takeOrderEdit');
@@ -207,6 +215,7 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('salesOrderBatchDispatchCompany', 'Api\SalesOrderController@salesOrderBatchDispatchCompany');
     $route->any('salesOrderGetBuildFee', 'Api\SalesOrderController@salesOrderGetBuildFee');
     $route->any('salesOrderClose', 'Api\SalesOrderController@salesOrderClose');
+    $route->any('salesClickOut', 'Api\SalesOrderController@salesClickOut');
 
     //施工单
     $route->any('constructionGet', 'Api\ConstructionController@constructionGet');