Explorar o código

Merge branch 'yang' of ssh://47.103.131.176:10022/var/git/bswas into yang

 Conflicts:
	app/Http/Controllers/TestController.php
zhouzhendong %!s(int64=4) %!d(string=hai) anos
pai
achega
2cde184b34
Modificáronse 100 ficheiros con 2980 adicións e 872 borrados
  1. 1 0
      .gitignore
  2. 0 0
      .htaccess
  3. 5 0
      app/CommodityMaterialBoxModel.php
  4. 13 0
      app/Components/ErrorPush.php
  5. 17 0
      app/ErrorTemp.php
  6. 1 0
      app/Events/SettlementBillCreateEvent.php
  7. 96 0
      app/Filters/RequirementFilters.php
  8. 84 0
      app/Http/Controllers/HandInStorageController.php
  9. 8 0
      app/Http/Controllers/HomeController.php
  10. 12 34
      app/Http/Controllers/LogisticController.php
  11. 66 0
      app/Http/Controllers/MaterialBoxModelController.php
  12. 4 0
      app/Http/Controllers/OrderIssueController.php
  13. 1 1
      app/Http/Controllers/RejectedBillController.php
  14. 100 0
      app/Http/Controllers/RequirementController.php
  15. 85 0
      app/Http/Controllers/RequirementUserController.php
  16. 56 73
      app/Http/Controllers/StationController.php
  17. 241 82
      app/Http/Controllers/StorageController.php
  18. 4 7
      app/Http/Controllers/StoreController.php
  19. 135 79
      app/Http/Controllers/TestController.php
  20. 1 1
      app/Http/Controllers/UnitController.php
  21. 72 6
      app/Http/Controllers/WaybillController.php
  22. 2 2
      app/Http/Controllers/api/email/SendEmailsController.php
  23. 14 6
      app/Http/Middleware/LogPostRequest.php
  24. 39 0
      app/Http/Requests/RequirementRequest.php
  25. 10 0
      app/Interfaces/ErrorPush.php
  26. 1 2
      app/Jobs/HandlePastBill.php
  27. 1 0
      app/Listeners/SettlementBillCreateListener.php
  28. 14 1
      app/Logistic.php
  29. 5 0
      app/MaterialBox.php
  30. 22 0
      app/MaterialBoxCommodity.php
  31. 7 1
      app/MaterialBoxModel.php
  32. 21 0
      app/OracleBasLotId.php
  33. 5 1
      app/OracleBasSKU.php
  34. 0 1
      app/OracleDOCASNHeader.php
  35. 2 1
      app/Owner.php
  36. 4 0
      app/OwnerFeeDetail.php
  37. 17 0
      app/OwnerLogisticFeeDetail.php
  38. 3 0
      app/OwnerMaterial.php
  39. 19 0
      app/OwnerStoreFeeDetail.php
  40. 19 1
      app/OwnerStoreOutFeeDetail.php
  41. 9 0
      app/OwnerWayBillFeeDetail.php
  42. 37 0
      app/Policies/RequirementPolicy.php
  43. 10 0
      app/Providers/AppServiceProvider.php
  44. 1 0
      app/Providers/AuthServiceProvider.php
  45. 79 0
      app/Requirement.php
  46. 18 0
      app/RequirementUser.php
  47. 6 22
      app/Services/BatchService.php
  48. 3 110
      app/Services/CacheShelfService.php
  49. 5 6
      app/Services/CommodityMaterialBoxModelService.php
  50. 77 36
      app/Services/DbOpenService.php
  51. 20 0
      app/Services/ErrorPushService.php
  52. 2 16
      app/Services/ForeignHaiRoboticsService.php
  53. 393 0
      app/Services/HandInStorageService.php
  54. 1 5
      app/Services/InventoryAccountService.php
  55. 5 1
      app/Services/LogisticSFService.php
  56. 39 0
      app/Services/MaterialBoxModelService.php
  57. 20 25
      app/Services/MaterialBoxService.php
  58. 1 0
      app/Services/OrderCommodityService.php
  59. 2 1
      app/Services/OrderPackageReceivedSyncService.php
  60. 21 16
      app/Services/OwnerPriceOperationService.php
  61. 13 0
      app/Services/RequirementService.php
  62. 13 0
      app/Services/RequirementUserService.php
  63. 70 2
      app/Services/StationService.php
  64. 21 43
      app/Services/StationTaskBatchService.php
  65. 16 23
      app/Services/StationTaskCommodityService.php
  66. 4 4
      app/Services/StationTaskMaterialBoxService.php
  67. 77 221
      app/Services/StorageService.php
  68. 0 1
      app/Services/common/BatchUpdateService.php
  69. 11 2
      app/Station.php
  70. 3 4
      app/Waybill.php
  71. 4 0
      ci/executeCommand.sh
  72. 1 1
      ci/judgePush.sh
  73. 1 1
      ci/scpUpdate.sh
  74. 10 8
      config/api_logistic.php
  75. 1 1
      config/users.php
  76. 12 0
      database/factories/RequirementFactory.php
  77. 12 0
      database/factories/RequirementUserFactory.php
  78. 34 0
      database/migrations/2021_07_13_163057_change_material_box_models_table.php
  79. 32 0
      database/migrations/2021_07_14_102919_change_waybills_add_column_merge_owner_id.php
  80. 34 0
      database/migrations/2021_07_14_151459_create_error_temps_table.php
  81. 39 0
      database/migrations/2021_07_15_173811_alert_order_type_column_in_waybills_table.php
  82. 32 0
      database/migrations/2021_07_16_093026_change_owners_add_model_sequence_column.php
  83. 34 0
      database/migrations/2021_07_19_113938_create_material_box_commodities_table.php
  84. 34 0
      database/migrations/2021_07_19_115331_change_stations_add_material_box_id.php
  85. 32 0
      database/migrations/2021_07_19_165143_change_logistics_table_add_tag_column.php
  86. 41 0
      database/migrations/2021_07_28_115218_create_requirements_table.php
  87. 33 0
      database/migrations/2021_07_28_115724_create_requirement_user_table.php
  88. 16 0
      database/seeds/RequirementSeeder.php
  89. 16 0
      database/seeds/RequirementUserSeeder.php
  90. 0 0
      nginx.htaccess
  91. 5 0
      package-lock.json
  92. 2 1
      package.json
  93. 18 7
      public/.htaccess
  94. 0 1
      public/index.php
  95. 3 0
      resources/js/marked.js
  96. 269 0
      resources/views/help.blade.php
  97. 27 3
      resources/views/inventory/stockInventory/inventoryMission.blade.php
  98. 21 1
      resources/views/maintenance/logistic/create.blade.php
  99. 30 11
      resources/views/maintenance/logistic/edit.blade.php
  100. 3 0
      resources/views/maintenance/logistic/index.blade.php

+ 1 - 0
.gitignore

@@ -32,3 +32,4 @@ yarn-error.log
 /serves/excelExportGo/logs
 /serves/excelExportGo/go_build_main_go.exe
 /laravel-echo-server.lock
+/database/data

+ 0 - 0
.htaccess


+ 5 - 0
app/CommodityMaterialBoxModel.php

@@ -16,4 +16,9 @@ class CommodityMaterialBoxModel extends Model
     protected $fillable=[
         "commodity_id","material_box_model_id","maximum"
     ];
+
+    public function materialBoxModel()
+    {
+        return $this->belongsTo(MaterialBoxModel::class,"material_box_model_id","id");
+    }
 }

+ 13 - 0
app/Components/ErrorPush.php

@@ -0,0 +1,13 @@
+<?php
+
+
+namespace App\Components;
+
+
+trait ErrorPush
+{
+    public function push(string $path, string $title, string $content)
+    {
+        app("ErrorPushService")->push($path,$title,$content);
+    }
+}

+ 17 - 0
app/ErrorTemp.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class ErrorTemp extends Model
+{
+    use ModelLogChanging;
+
+    protected $fillable=[
+        "position","title","content","created_at"
+    ];
+    public $timestamps=false;
+}

+ 1 - 0
app/Events/SettlementBillCreateEvent.php

@@ -26,6 +26,7 @@ class SettlementBillCreateEvent
     const OWNER_STORE_OUT_FEE_DETAIL = OwnerStoreOutFeeDetail::class;
     //物流费
     const OWNER_WAY_BILL_FEE_DETAIL = OwnerWayBillFeeDetail::class;
+
     public $createData;
 
     /**

+ 96 - 0
app/Filters/RequirementFilters.php

@@ -0,0 +1,96 @@
+<?php
+
+
+namespace App\Filters;
+
+use App\Order;
+use App\RequirementUser;
+use App\Services\UserService;
+use Illuminate\Http\Request;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Str;
+use phpDocumentor\Reflection\Types\Boolean;
+
+class RequirementFilters
+{
+    protected $request;
+    protected $queryBuilder;
+    protected $filters = [
+        'title',
+        'creator_id',
+        'worker_ids',
+        'began_at_start',
+        'began_at_end',
+        'finished_at_start',
+        'finished_at_end',
+        'created_at_start',
+        'created_at_end',
+    ];
+
+    public function __construct(Request $request)
+    {
+        $this->request = $request;
+    }
+
+    public function apply($builder)
+    {
+        $this->queryBuilder = $builder;
+        $filters = array_filter($this->request->only($this->filters));
+        foreach ($filters as $filter => $value) {
+            if (method_exists($this, $filter)) {
+                $this->$filter($value, $this->queryBuilder);
+            }
+        }
+        return $this->queryBuilder;
+    }
+
+    public function creator_id($creator_id)
+    {
+        $this->queryBuilder->where('user_id', $creator_id);
+    }
+
+    private function worker_ids($worker_ids)
+    {
+        if (strpos($worker_ids, ',') || strpos($worker_ids, ',') || strpos($worker_ids, ' ')) {
+            $arr = array_filter(preg_split('/[,, ]+/is', $worker_ids));
+            $this->queryBuilder->whereIn('id', RequirementUser::query()->select('requirement_id')->whereIn('user_id', $arr));
+        } else {
+            $this->queryBuilder->whereIn('id', RequirementUser::query()->select('requirement_id')->where('user_id', $worker_ids));
+        }
+    }
+
+    public function began_at_start($began_at_start)
+    {
+        $this->queryBuilder->where('begin_at', '>=', \Carbon\Carbon::parse($began_at_start)->startOfDay());
+    }
+
+    public function began_at_end($began_at_end)
+    {
+        $this->queryBuilder->where('begin_at', '<=', \Carbon\Carbon::parse($began_at_end)->endOfDay());
+    }
+
+    public function finished_at_start($finished_at_start)
+    {
+        $this->queryBuilder->where('finished_at', '>=', \Carbon\Carbon::parse($finished_at_start)->startOfDay());
+    }
+
+    public function finished_at_end($finished_at_end)
+    {
+        $this->queryBuilder->where('finished_at', '<=', \Carbon\Carbon::parse($finished_at_end)->endOfDay());
+    }
+
+    public function created_at_start($created_at_start)
+    {
+        $this->queryBuilder->where('created_at', '>=', \Carbon\Carbon::parse($created_at_start)->startOfDay());
+    }
+
+    public function created_at_end($created_at_end)
+    {
+        $this->queryBuilder->where('created_at', '<=', \Carbon\Carbon::parse($created_at_end)->endOfDay());
+    }
+
+    public function title($title)
+    {
+        $this->queryBuilder->where('title', 'like', $title.'%');
+    }
+}

+ 84 - 0
app/Http/Controllers/HandInStorageController.php

@@ -0,0 +1,84 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\AsyncResponse;
+use App\OracleDOCASNHeader;
+use App\Services\HandInStorageService;
+use Illuminate\Http\Request;
+
+class HandInStorageController extends Controller
+{
+    use AsyncResponse;
+    /**
+     * 搜索查詢asn
+     */
+    public function selectAsn(Request $request)
+    {
+        /** @var HandInStorageService $handInStorageService  */
+        $handInStorageService=app('HandInStorageService');
+        $asnno= $request->input('asnno');
+        $asns =$handInStorageService->selectAsn($asnno);
+        if ($asns->count()>0){
+            $this->success($asns);
+        }else{
+            $this->error('未搜索到ASN单');
+        }
+    }
+    /**
+     * @param $asnno
+     * 跳转到收货明细页面
+     */
+    public function receiveDetailPage($asnno,$customerid)
+    {
+        /** @var HandInStorageService $handInStorageService  */
+        $handInStorageService=app('HandInStorageService');
+        if (!$customerid||$customerid=='undefined')
+            $customerid=OracleDOCASNHeader::query()->where('asnno',$asnno)->value('customerid');
+        $qualityStatus=$handInStorageService->getQualityStatus();
+        $attributeLocations=$handInStorageService->getAttributeLocation();
+        return view('store.handInStorage.receiveDetailPage')
+            ->with(['asnno'=>$asnno,'customerid'=>$customerid,'qualityStatus'=>$qualityStatus,'attributeLocations'=>$attributeLocations]);
+    }
+
+    /**
+     * @param Request $request
+     * 查询富勒asn_detail(集合)
+     */
+    public function selectAsnDetails(Request $request)
+    {
+        $asnno= $request->input('asnno');
+        $asnDetails =app('HandInStorageService')->selectAsnDetails($asnno);
+        if ($asnDetails->count()>0)$this->success($asnDetails);
+        else $this->error('未搜索到ASN详情单');
+
+    }
+    /**
+     * @param Request $request
+     * 查询富勒bas_sku 并关联 bas_lotid
+     */
+    public function getBasSkuWithLot(Request $request): array
+    {
+        $customerid= $request->input('customerid');
+        $sku= $request->input('sku');
+        $asnno= $request->input('asnno');
+        $asnDetail=app('HandInStorageService')->getAsnDetail($asnno,$sku);
+        $basSku =app('HandInStorageService')->getBasSkuLotId($customerid,$sku);
+        if (isset($basSku)&&isset($asnDetail))return ['success'=>true,'basSku'=>$basSku,'asnDetail'=>$asnDetail];
+        else $this->error('无效条码');
+    }
+
+    public function fluxHandIn(Request $request)
+    {
+        $info=$request->input('info');
+//        dd($info);
+        if (!$info['customerid']||!$info['sku']||!$info['asnno']) $this->error('参数错误');
+        if ($info['amount']+$info['receivedqty']>$info['expectedqty'])$this->error('收货数大于预期数');
+        /** @var HandInStorageService $handInStorageService  */
+        $handInStorageService=app('HandInStorageService');
+        $handInStorageService->fluxHandIn($info);
+//        dd($result,"111");
+    }
+
+
+}

+ 8 - 0
app/Http/Controllers/HomeController.php

@@ -34,4 +34,12 @@ class HomeController extends Controller
     {
         return view('home');
     }
+
+    public function help()
+    {
+        $filePath = base_path('文档/SystemHandBook.md');
+        $read = @file_get_contents($filePath);
+        $read = str_replace(["\r","\n",'"'],["\\r",'\\n',"'"],$read);
+        return view("help",compact("read"));
+    }
 }

+ 12 - 34
app/Http/Controllers/LogisticController.php

@@ -7,8 +7,10 @@ use Exception;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Gate;
 use Illuminate\Support\Facades\Validator;
+use Illuminate\Support\Str;
 
 class LogisticController extends Controller
 {
@@ -24,23 +26,13 @@ class LogisticController extends Controller
         return view('maintenance.logistic.index',['logistics'=>$logistics]);
     }
 
-    /**
-     * Show the form for creating a new resource.
-     *
-     * @return Response
-     */
     public function create()
     {
         if(!Gate::allows('承运商-录入')){ return view("exception.authority");  }
         return view('maintenance.logistic.create');
     }
 
-    /**
-     * Store a newly created resource in storage.
-     *
-     * @param Request $request
-     * @return Response
-     */
+
     public function store(Request $request)
     {
         if(!Gate::allows('承运商-录入')){ return view("exception.authority");  }
@@ -70,26 +62,19 @@ class LogisticController extends Controller
             'delivery_fee' => ['nullable', 'numeric', 'min:0'],
         ]);
     }
-    /**
-     * Display the specified resource.
-     *
-     * @param Logistic $logistic
-     * @return Response
-     */
-    public function show(Logistic $logistic)
-    {
-        //
-    }
 
-    /**
-     * Show the form for editing the specified resource.
-     *
-     * @param Logistic $logistic
-     * @return Response
-     */
     public function edit(Logistic $logistic)
     {
         if(!Gate::allows('承运商-编辑')){ return view("exception.authority");  }
+        $logistic = $logistic->toArray();
+        if ($logistic["tag"]){
+            $tag = explode(",",$logistic["tag"]);
+            $map = array_flip(Logistic::TAGS);
+            foreach ($tag as &$t)$t = $map[$t];
+            $logistic["tag"] = implode(",",$tag);
+        }
+        $key = 'LogisticAll_'.implode("",["id","name","tag"]).Str::studly("物流");
+        Cache::pull($key);
         return view('maintenance.logistic.edit',['logistic'=>$logistic]);
     }
 
@@ -104,13 +89,6 @@ class LogisticController extends Controller
         return redirect('maintenance/logistic/')->with('successTip',"成功修改承运商“{$logistic['name']}”!");
     }
 
-    /**
-     * Remove the specified resource from storage.
-     *
-     * @param Logistic $logistic
-     * @return array|Response
-     * @throws Exception
-     */
     public function destroy(Logistic $logistic)
     {
         if(!Gate::allows('承运商-删除')){ return view("exception.authority");  }

+ 66 - 0
app/Http/Controllers/MaterialBoxModelController.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\AsyncResponse;
+use App\MaterialBoxModel;
+use App\Owner;
+use Illuminate\Support\Facades\Validator;
+
+class MaterialBoxModelController extends Controller
+{
+    use AsyncResponse;
+    public function index()
+    {
+        $models = MaterialBoxModel::query()->get();
+        return view("maintenance.materialBoxModel.index",compact("models"));
+    }
+
+    public function save()
+    {
+        $id = request("id");
+        $errors = Validator::make(request()->input(), [
+            'code'=>['required',$id?"unique:material_box_models,code,$id":"unique:material_box_models,code"],
+            'maximum_kind'=>['required',"integer","min:1"],
+            'description'=>['nullable'],
+        ],[
+            'integer'=>':attribute 非法参数',
+            'required'=>':attribute 必填',
+            'unique'=>':attribute 已存在',
+        ],[
+            'code'=>'编码',
+            'maximum_kind'=>'最大商品种类',
+            'description'=>'说明',
+        ]);
+        if ($errors->errors()->count())$this->success(["errors"=>$errors->errors()]);
+        if (!$id) $this->success(MaterialBoxModel::query()->create([
+                'code' => request("code"),
+                'maximum_kind' => request("maximum_kind"),
+                'description' => request("description"),
+            ]));
+        $model = MaterialBoxModel::query()->find($id);
+        if (!$model)$this->error("模型不存在");
+        $model->update(request()->only(["code",'maximum_kind',"description"]));
+        $this->success($model);
+    }
+
+    public function destroy()
+    {
+        $this->success(MaterialBoxModel::destroy(request("id")));
+    }
+
+    public function ownerSequence()
+    {
+        $owners = app("OwnerService")->getIntersectPermitting(["id","name","model_sequence"]);
+        $models = MaterialBoxModel::query()->get();
+        return view("maintenance.materialBoxModel.modelSequence",compact("owners","models"));
+    }
+
+    public function updateModelSequence()
+    {
+        $sequence = request("sequence");
+        $this->success(Owner::query()->where("id",request("id"))->update([
+            "model_sequence" => $sequence ?: null
+        ]));
+    }
+}

+ 4 - 0
app/Http/Controllers/OrderIssueController.php

@@ -321,6 +321,7 @@ class OrderIssueController extends Controller
         if (!Gate::allows('订单管理-问题件-编辑')) {
             return ['success'=>false,'fail_info' => '没有对应权限'];
         }
+
         if($request['column']=='final_status'  && $request['value'] == '已归档'){
             $orderIssues = OrderIssue::query()->where('id',$request['id'])->get();
             $service->archive($orderIssues);
@@ -331,6 +332,9 @@ class OrderIssueController extends Controller
                 ->where('id', $request->input('id'))
                 ->update([$request->input('column') => $request->input('value')]);
             app('LogService')->log(__METHOD__,'更新问题件',json_encode($request->getContent()));
+            if ($request->input('column') == 'order_issue_type_id') {
+                event(new AddOrUpdateOrderIssues([$request->input('id')]));
+            }
             return ['success' => true];
         } catch (Exception $e) {
             app('LogService')->log(__METHOD__,'更新问题件error',json_encode($request->getContent()).'||'.$e->getMessage().'||'.$e->getTraceAsString());

+ 1 - 1
app/Http/Controllers/RejectedBillController.php

@@ -151,7 +151,7 @@ class RejectedBillController extends Controller
     protected function validator(array $data,$isUpdate=false)
     {
         $mobileShouldBeRequired = 'required';
-        $logistic=Logistic::find($data['id_logistic_return']);
+        $logistic= isset($data['id_logistic_return']) ? Logistic::find($data['id_logistic_return']) : null;
         if($logistic){if(
             strstr($logistic['name'],'顺丰')
         ){

+ 100 - 0
app/Http/Controllers/RequirementController.php

@@ -0,0 +1,100 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Filters\RequirementFilters;
+use App\Http\Requests\RequirementRequest;
+use App\Requirement;
+use App\Role;
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Illuminate\Support\Facades\Auth;
+
+class RequirementController extends Controller
+{
+
+    public function index(Request $request, RequirementFilters $filters)
+    {
+        $requirements = Requirement::query()->filter($filters)
+            ->with(['creator', 'workers'])
+            ->orderByDesc('created_at')
+            ->paginate($request->paginate ?? 50);
+        $canCreateRequirementUsers = Role::query()->where('name', '创建需求')->first()->users;
+
+        $canWorkRequirementUsers = Role::query()->where('name', '执行需求')->first()->users;
+        $paginateParams = $request->paginateParams;
+        return view('requirement.index', compact('canWorkRequirementUsers', 'canCreateRequirementUsers', 'requirements', 'paginateParams'));
+    }
+
+    public function create(Requirement $requirement)
+    {
+        return view('requirement.create_and_edit', compact('requirement'));
+    }
+
+    public function store(RequirementRequest $request, Requirement $requirement)
+    {
+        $requirement->fill($request->all());
+        $requirement->user_id = Auth::id();
+        $requirement->status = '已发布';
+        $requirement->save();
+        return redirect()->route('requirements.index', $requirement->id)->with('success', '需求创建成功!');
+    }
+
+
+    public function show(Requirement $requirement)
+    {
+        $requirement->loadMissing(['creator', 'workers']);
+        $creators = Role::query()->where('name', '创建需求')->first()->users;
+        $workers = Role::query()->where('name', '执行需求')->first()->users;
+        return view('requirement.show', compact('requirement', 'creators', 'workers'));
+    }
+
+
+    public function edit(Requirement $requirement)
+    {
+        $requirement->loadMissing(['creator', 'workers']);
+        $creators = Role::query()->where('name', '创建需求')->first()->users;
+        $workers = Role::query()->where('name', '执行需求')->first()->users;
+        return view('requirement.create_and_edit', compact('requirement', 'creators', 'workers'));
+    }
+
+
+    public function update(Request $request, Requirement $requirement)
+    {
+        $requirement->update($request->all());
+        return redirect()->route('requirements.show', $requirement->id)->with('success', '编辑成功');
+    }
+
+
+    public function destroy(Requirement $requirement)
+    {
+        $this->authorize('destroy', $requirement);
+        $requirement->delete();
+        return redirect()->route('requirements.index', $requirement->id)->with('success', '删除需求成功!');
+
+    }
+
+    public function begin(Requirement $requirement)
+    {
+        $this->authorize('begin', $requirement);
+        $requirement->status = '已开始';
+        $requirement->began_at = now();
+        $requirement->save();
+        return redirect()->route('requirements.show', $requirement->id)->with('success', '需求已开始执行');
+    }
+
+    public function finish(Request $request, Requirement $requirement)
+    {
+        $requirement->status = '已完成';
+        if (count($request->users) > 0) {
+            $attachData = [];
+            foreach ($request->users as $worker) {
+                $attachData[$worker['name']] = ['score' => $worker['score']];
+            }
+            $requirement->workers()->sync($attachData);
+        }
+        $requirement->finished_at = now();
+        $requirement->save();
+        return redirect()->route('requirements.show', $requirement->id)->with('success', '需求已完成');
+    }
+}

+ 85 - 0
app/Http/Controllers/RequirementUserController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\RequirementUser;
+use Illuminate\Http\Request;
+
+class RequirementUserController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\RequirementUser  $requirementUser
+     * @return \Illuminate\Http\Response
+     */
+    public function show(RequirementUser $requirementUser)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\RequirementUser  $requirementUser
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(RequirementUser $requirementUser)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\RequirementUser  $requirementUser
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, RequirementUser $requirementUser)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\RequirementUser  $requirementUser
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(RequirementUser $requirementUser)
+    {
+        //
+    }
+}

+ 56 - 73
app/Http/Controllers/StationController.php

@@ -2,22 +2,17 @@
 
 namespace App\Http\Controllers;
 
+use App\Components\AsyncResponse;
 use App\Station;
 use App\StationTypeBinMonitor;
 use Illuminate\Database\Eloquent\Builder;
-use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\DB;
 
 class StationController extends Controller
 {
-    /**
-     * Display a listing of the resource.
-     *
-     * @return void
-     */
-    public function index()
-    {
+    use AsyncResponse;
 
-    }
     public function monitorIndex()
     {
         $stations = Station::query()->with('stationType:name','parent:name')->whereHas('stationType',function($query){
@@ -27,34 +22,8 @@ class StationController extends Controller
         return view('station.monitor.index',compact('stations'));
     }
 
-    /**
-     * Show the form for creating a new resource.
-     *
-     * @return \Illuminate\Http\Response
-     */
-    public function create()
-    {
-        //
-    }
-
-    /**
-     * Store a newly created resource in storage.
-     *
-     * @param  \Illuminate\Http\Request  $request
-     * @return \Illuminate\Http\Response
-     */
-    public function store(Request $request)
-    {
-        //
-    }
-
-    public function show(Station $station)
-    {
-        //
-    }
     public function monitorShow(Station $station)
     {
-//        $stationTypeBinMonitor = StationTypeBinMonitor::query()->where("station_id",$station->id)->first();
         $station->loadMissing([
             "stationTasks_today.stationTaskCommodities.commodity.barcodes",
             "stationTasks_today.stationTaskCommodities.stationTaskMaterialBox",
@@ -71,50 +40,64 @@ class StationController extends Controller
             ]);
             $station->load("stationTypeBinMonitor");
         }
-//        dd(
-//            data_get($station['stationTasks_today'],'*.id')
-//            ,data_get($station['stationTasks_today'],'*.stationTaskBatches.*.batch.code')
-//            ,data_get($station['stationTasks_today'],'*.stationTaskBatches.*.id')
-//            ,data_get($station['stationTasks_today'],'*.stationTaskBatches.*.batch.id')
-//            ,data_get(data_get($station['stationTasks_today'],'*.stationTaskCommodities')[7],'*.id')
-//            ,data_get(data_get($station['stationTasks_today'],'*.stationTaskCommodities')[9],'*.id')
-//        );
-//        $station=$station->toJson();
         return view('station.monitor.show',compact('station'));
     }
 
-    /**
-     * Show the form for editing the specified resource.
-     *
-     * @param  \App\Station  $station
-     * @return \Illuminate\Http\Response
-     */
-    public function edit(Station $station)
-    {
-        //
-    }
-
-    /**
-     * Update the specified resource in storage.
-     *
-     * @param  \Illuminate\Http\Request  $request
-     * @param  \App\Station  $station
-     * @return \Illuminate\Http\Response
-     */
-    public function update(Request $request, Station $station)
+    public function getVisual()
     {
-        //
+        $arr = \request("arr");
+        $cacheKey = "loadBoxMonitor_".$arr[0][0];
+        if (Cache::tags("loadBoxMonitor")->has($cacheKey))$this->success(Cache::tags("loadBoxMonitor")->get($cacheKey));
+        $res = [];
+        foreach ($arr as $item){
+            $query = DB::connection("mysql_haiRobotics")->table("ks_bin")->select("ks_bin_code");
+            foreach ($item as $value)$query->orWhere("ks_bin_space_code",'like',$value);
+            $codes = [];
+            $query->get()->each(function ($bin)use(&$codes){
+                $codes[] = "'".$bin->ks_bin_code."'";
+            });
+            if (!$codes){$res[] = 100;continue;}
+            $len = count($codes);
+            $codes = "(".implode(",",$codes).")";
+            $sql = <<<SQL
+SELECT COUNT(*) count FROM (SELECT SUM(QTY) qty FROM INV_LOT_LOC_ID WHERE
+TRACEID = '*' AND LOCATIONID IN {$codes} GROUP BY LOCATIONID) inv WHERE INV.qty!=0
+SQL;
+            $count = DB::connection("oracle")->selectOne(DB::raw($sql))->count;
+            $res[] = intval($count/$len*1000)/10;
+        }
+        Cache::tags("loadBoxMonitor")->put($cacheKey,$res,1800);
+        $this->success($res);
     }
 
-    /**
-     * Remove the specified resource from storage.
-     *
-     * @param  \App\Station  $station
-     * @return \Illuminate\Http\Response
-     */
-    public function destroy(Station $station)
+    public function getDetail()
     {
-        //
+        $arr = \request("arr");
+        $cacheKey = "loadBoxMonitorDetail_".$arr[0];
+        if (Cache::tags("loadBoxMonitor")->has($cacheKey))$this->success(Cache::tags("loadBoxMonitor")->get($cacheKey));
+        $ks = DB::connection("mysql_haiRobotics")->table("ks_bin")->select("ks_bin_code","ks_bin_space_code")
+            ->whereIn("ks_bin_space_code",$arr)->get();
+        $res = [];
+        $codes = [];
+        foreach ($ks as $k){
+            $res[$k->ks_bin_code] = $k->ks_bin_space_code;
+            $codes[] = $k->ks_bin_code;
+        }
+        $locations = [];
+        DB::connection("oracle")->table("INV_LOT_LOC_ID")->selectRaw("locationid,SUM(qty) qty")
+            ->where("traceid","*")
+            ->whereIn("locationid",$codes)->groupByRaw("locationid")->get()->each(function ($inv)use(&$locations,&$res){
+                $locations[] = [
+                    "location"  => $res[$inv->locationid],
+                    "status"    => $inv->qty>0,
+                ];
+                unset($res[$inv->locationid]);
+            });
+        if ($res)foreach ($res as $item)$locations[] = [
+            "location"  => $item,
+            "status"    => false,
+        ];
+        Cache::tags("loadBoxMonitor")->put($cacheKey,$locations,1800);
+        $this->success($locations);
     }
-
 }

+ 241 - 82
app/Http/Controllers/StorageController.php

@@ -6,12 +6,13 @@ use App\Commodity;
 use App\CommodityMaterialBoxModel;
 use App\Components\AsyncResponse;
 use App\MaterialBox;
+use App\MaterialBoxCommodity;
 use App\MaterialBoxModel;
 use App\Owner;
+use App\Services\LogService;
 use App\Station;
 use App\StationTask;
 use App\StationTaskMaterialBox;
-use App\Storage;
 use App\StoreItem;
 use App\TaskTransaction;
 use Illuminate\Database\Eloquent\Builder;
@@ -29,6 +30,7 @@ class StorageController extends Controller
 
     public function putShelf()
     {
+        $this->error("停用缓存架上架,联系管理员开启");
         $this->gate("入库管理-入库-缓存架入库");
         $asn = \request("asn");
         $ide = \request("ide");
@@ -36,16 +38,12 @@ class StorageController extends Controller
         $amount = (int)\request("amount");
         //check info
         if (!$asn || !$ide || !$barCode || !$amount)$this->error("信息不完整");
-        $fromLocation = app("MaterialBoxService")->getBoxLocation($ide);
-        if (!$fromLocation)$this->error("WAS无此库位信息");
-        $box = MaterialBox::query()->where("code",$ide)->first();
+        $box = MaterialBox::query()->with("station")->where("code",$ide)->first();
         if (!$box)$this->error("WAS无此料箱");
+        if (!$box->station)$this->error("WAS无此库位信息");
+        if (!app("StationService")->isCacheShelfLocation($box->station))$this->error("非缓存架库位");
+        $fromLocation = $box->station->code; //源库位
 
-        //库存相关信息
-        /** @var Station|\stdClass $station */
-        $station = Station::query()->firstOrCreate(["code"=>$fromLocation],[
-            'name' => $fromLocation, 'code' => $fromLocation, 'station_type_id' => 5
-        ]);
         $item = StoreItem::query()->whereHas("store",function (Builder $query){
             $query->where("asn_code",request("asn"));
         })->whereHas("commodity",function (Builder $query)use($barCode){
@@ -53,6 +51,7 @@ class StorageController extends Controller
                 $query->where("code",$barCode);
             });
         })->first();
+        if (!$item)$this->error("WAS无此ASN单信息");
         //get flux
         $tasks = app("StorageService")->getFluxTask($asn,$barCode,$amount);
         if (!$tasks)$this->error("该单无上架任务或不存在");
@@ -60,7 +59,7 @@ class StorageController extends Controller
         DB::beginTransaction(); //总体事务 回滚WAS错误操作
         try{
             //库存记录
-            if (!app("StorageService")->enterWarehouse($station->id, $box->id, $item->commodity_id ?? null, $amount, $box->material_box_model_id))$this->error("库存异常");
+            if (!app("StorageService")->enterWarehouse( $box->id, $item->commodity_id, $amount, $box->material_box_model_id))$this->error("库存异常");
 
             DB::connection("oracle")->transaction(function ()use($tasks,$ide){ //单体嵌套事务 回滚FLUX失败任务
                 foreach ($tasks as $task)if (!app("StorageService")->fluxPA($task,$ide)){
@@ -74,11 +73,10 @@ class StorageController extends Controller
             $this->error($e->getMessage());
         }
         //亮灯
-        app("CacheShelfService")->_stationCacheLightOn($fromLocation,$ide);
+        app("CacheShelfService")->lightUp($fromLocation,'1','0',["detail01"=>$ide,"qty01"=>$amount]);
 
-        $maximum = app("CommodityMaterialBoxModelService")->getMaximum($box->material_box_model_id,$item->commodity_id ?? null);
-        if ($maximum && $maximum<$amount)app("CommodityMaterialBoxModelService")->setMaximum($box->material_box_model_id,$item->commodity_id ?? null,$amount);
-        $this->success(["model" => $box->material_box_model_id,"commodity" => $item->commodity_id ?? null, "maximum" => $maximum]);
+        $maximum = app("CommodityMaterialBoxModelService")->getMaximum($box->material_box_model_id,$item->commodity_id);
+        $this->success(["model" => $box->material_box_model_id,"commodity" => $item->commodity_id, "maximum" => $maximum]);
     }
 
     public function setMaximum()
@@ -96,15 +94,10 @@ class StorageController extends Controller
         $item = app("StoreItemService")->getMaxAvailableDetail(request("asn"),request("barCode"));
         if (!$item)$this->error("无此单据记录");
         $models = CommodityMaterialBoxModel::query()->where("commodity_id",$item->commodity_id)->get();
-        if ($models->count()==0)$this->error("商品首入,请使用缓存架空箱入库");
-        foreach ($models as $model){
-            $result = app("StorageService")->getHalfBoxLocation($model,$item,request("asn"));
-            if ($result){
-                $result->maximum = $model->maximum-$result->amount;
-                $this->success($result);
-            }
-        }
-        $this->success(["need"=>$models[0]->maximum,"material_box_model_id"=>$models[0]->material_box_model_id,"commodity_id"=>$item->commodity_id]);
+        if ($models->count()==0)$this->success(["material_box_model_id"=>null]);
+        $map = [];
+        foreach ($models as $model)$map[$model->material_box_model_id] = $model;
+        $this->getMaterBoxModel($item,$map);
     }
 
     /**
@@ -131,13 +124,26 @@ sql;
         $boxes = request("boxes");
         //清理任务
         $data = '';
-        $occupy = Storage::query()->with("station:id,code")->whereIn("station_id",Station::query()->select("id")->whereIn("code",$boxes))->where("status",1)->get();
+        //剔除准备执行任务但没有真正开始执行的待定库位
+        $occupy = Station::query()->select("id")->whereIn("code",$boxes)->where("status",1)->get();
         foreach ($occupy as $item){
-            unset($boxes[array_search($item->station->code,$boxes)]);
-            $data .= '“'.$item->station->code.'”,';
+            unset($boxes[array_search($item->code,$boxes)]);
+            $data .= '“'.$item->code.'”,';
         }
         if ($occupy->count()>0){
-            $data .= "存在任务待处理,无法调取";
+            $data .= "存在任务待处理,无法调取  ";
+            $boxes = array_values($boxes);
+        }
+        //剔除存在任务的库位
+        $tasks = StationTaskMaterialBox::query()->with("station:id,code")
+            ->whereIn("station_id",Station::query()->select("id")->whereIn("code",$boxes))
+            ->whereNotIn("status",["完成","取消"])->get();
+        foreach ($tasks as $task){
+            unset($boxes[array_search($task->station->code,$boxes)]);
+            $data .= '“'.$task->station->code.'”,';
+        };
+        if ($tasks->count()>0){
+            $data .= "任务排队中,无法调取";
             $boxes = array_values($boxes);
         }
         //重新调取料箱
@@ -155,78 +161,87 @@ sql;
         $this->gate("入库管理-入库-半箱补货入库");
         $boxId = request("material_box_id");
         $modelId = request("material_box_model_id");
+        if (!$modelId)$this->error("商品未设定库存上限");
         //获取目标库位
         $station = app("StationService")->getMirrorMappingLocation(request("station"));
         if (!$station)$this->error("未知库位");
-        $occupyTask = StationTaskMaterialBox::query()->where("station_id",$station->id)->whereNotIn("status",["完成","取消"])->first();
-        if ($occupyTask)$this->error("库位存在任务未处理完成");
+        $isAvailable = app("StationService")->isAvailable($station);
+        if (!$isAvailable)$this->error("库存被占用或存在任务未处理");
         $amount = app("StorageService")->checkPutAmount(request("asn"),request("barCode"));
         if ($amount<request("amount"))$this->error("待上架数量不足,最大可上数量为{$amount}");
+
+        //发起取箱任务
+        $exe = function ($boxId)use($station){
+            DB::beginTransaction();
+            $collection = new Collection();
+            $task = StationTask::query()->create([
+                'status' => "待处理",
+                'station_id' => $station->id,
+            ]);
+            $collection->add(StationTaskMaterialBox::query()->create([
+                'station_id' => $station->id,
+                'material_box_id'=>$boxId,
+                'status'=>"待处理",
+                'type' => '取',
+                'station_task_id' => $task->id,
+            ]));
+            if (!app("ForeignHaiRoboticsService")->fetchGroup($station->code,$collection,'','立架出至缓存架'))$this->error("呼叫机器人失败");
+            //生成临时任务事务
+            TaskTransaction::query()->create([
+                "doc_code" => request("asn"),
+                "bar_code" => request("barCode"),
+                "fm_station_id" => $station->id,
+                "material_box_id" => $boxId,
+                "commodity_id" => request("commodity_id"),
+                "amount" => request("amount"),
+                "type" => "入库",
+                "user_id" => Auth::id(),
+                "mark" => 1
+            ]);
+            DB::commit();
+            //亮灯
+            app("CacheShelfService")->lightUp($station->code,'2','1');
+            app("StationService")->locationOccupy($station->code);//占用库位
+        };
+        if ($boxId && app("MaterialBoxService")->checkUsableBox($boxId))$this->success($exe($boxId));
+        $item = app("StoreItemService")->getMaxAvailableDetail(request("asn"),request("barCode"));
+        if (!$item)$this->error("无此单据记录");
+        $models = app("MaterialBoxModelService")->getModelSortedByOwner($item->store->owner_id);
+        $models->load(["commodity"=>function($query)use($item){
+            $query->where("commodity_id",$item->commodity_id);
+        }]);
         //获取料箱
-        if ($boxId && !app("MaterialBoxService")->checkUsableBox($boxId)){
+        if ($boxId){
             $blacklist = [$boxId];
             $boxId = null;
             //料箱存在且不可用
-            $models = CommodityMaterialBoxModel::query()->where("commodity_id",request("commodity_id"))->get();
-            $item = app("StoreItemService")->getMaxAvailableDetail(request("asn"),request("barCode"));
-            if (!$item)$this->error("无此单据记录");
+            /** @var \Illuminate\Database\Eloquent\Collection $models */
+
             foreach ($models as $model){
+                if (!$model->commodity)continue;
                 //料箱不可用寻找新料箱
-                $result = app("StorageService")->getHalfBoxLocation($model,$item,request("asn"),$blacklist);
+                $result = app("StorageService")->getHalfBoxLocation($model->commodity,$item,request("asn"),$blacklist);
                 while ($result){
                     //料箱可用并且数量符合本次半箱数量 跳出
                     if (app("MaterialBoxService")->checkUsableBox($result->material_box_id)
-                        && $model->maximum-$result->amount>=request("amount")){$boxId = $result->material_box_id;break;}
+                        && $model->maximum-$result->amount>=request("amount"))$this->success($exe($result->material_box_id));
                     else $blacklist[] = $result->material_box_id;
                     //否则黑名单此料箱继续查找 直至料箱为空
-                    $result = app("StorageService")->getHalfBoxLocation($model,$item,request("asn"),$blacklist);
+                    $result = app("StorageService")->getHalfBoxLocation($model->commodity,$item,request("asn"),$blacklist);
                 }
             }
         }
         //料箱不存在且该商品有过入库记录 拿取空箱
-        if (!$boxId){
-            if (!$modelId){
-                $box = null;
-                $models = CommodityMaterialBoxModel::query()->where("commodity_id",request("commodity_id"))->get();
-                foreach ($models as $model){
-                    $box = app("MaterialBoxService")->getAnEmptyBox([],$model->material_box_model_id);
-                    if($box)break;
-                }
-            }else $box = app("MaterialBoxService")->getAnEmptyBox([],$modelId);
-            if (!$box)$this->error("无可用料箱");
-            $boxId = $box->id;
-        }
-        //发起取箱任务
-        DB::beginTransaction();
-        $collection = new Collection();
-        $task = StationTask::query()->create([
-            'status' => "待处理",
-            'station_id' => $station->id,
-        ]);
-        $collection->add(StationTaskMaterialBox::query()->create([
-            'station_id' => $station->id,
-            'material_box_id'=>$boxId,
-            'status'=>"待处理",
-            'type' => '取',
-            'station_task_id' => $task->id,
-        ]));
-        if (!app("ForeignHaiRoboticsService")->fetchGroup($station->code,$collection,'','立架出至缓存架'))$this->error("呼叫机器人失败");
-        //生成临时任务事务
-        TaskTransaction::query()->create([
-            "doc_code" => request("asn"),
-            "bar_code" => request("barCode"),
-            "fm_station_id" => $station->id,
-            "material_box_id" => $boxId,
-            "commodity_id" => request("commodity_id"),
-            "amount" => request("amount"),
-            "type" => "入库",
-            "user_id" => Auth::id(),
-            "mark" => 1
-        ]);
-        DB::commit();
-        //亮灯
-        app("CacheShelfService")->stationLightUp($station->code,null,'2');
-        $this->success();
+        if (!$modelId){
+            $box = null;
+            foreach ($models as $model){
+                if (!$model->commodity)continue;
+                $box = app("MaterialBoxService")->getAnEmptyBox($model);
+                if($box)break;
+            }
+        }else $box = app("MaterialBoxService")->getAnEmptyBox(MaterialBoxModel::query()->find($modelId));
+        if (!$box)$this->error("无可用料箱");
+        $this->success($exe($box->id));
     }
 
     /**
@@ -244,7 +259,8 @@ sql;
             ->where("type","入库")->where("mark",1)->where("status",0)->first();
         if (!$task)$this->error("无任务存在");
         $task->update(["amount" => DB::raw("amount - {$amount}")]);
-        $storage = Storage::query()->where("material_box_id",$task->material_box_id)->first();
+        $storage = MaterialBoxCommodity::query()->where("material_box_id",$task->material_box_id)
+            ->where("commodity_id",$task->commodity_id)->first();
         $maximum = (($storage->amount ?? 0)+$task->amount)-$amount;
         CommodityMaterialBoxModel::query()->where("material_box_model_id",$task->materialBox->material_box_model_id)
             ->where("commodity_id",$task->commodity_id)->update(["maximum"=>$maximum]);
@@ -273,9 +289,9 @@ sql;
                 "name" => $inv->customerid,
             ]);
             $commodity = Commodity::query()->where("owner_id",$owner->id)->where("sku",$inv->sku)->first();
-            $s = \App\Storage::query()->where("material_box_id",$materialBox->id)
+            $s = MaterialBoxCommodity::query()->where("material_box_id",$materialBox->id)
                 ->where("commodity_id",$commodity->id)->first();
-            if (!$s)\App\Storage::query()->create([
+            if (!$s)MaterialBoxCommodity::query()->create([
                 "material_box_id" => $materialBox->id,
                 "commodity_id" => $commodity->id,
                 "amount" => $inv->qty,
@@ -304,4 +320,147 @@ sql;
     {
         return 'name';
     }
+
+    /**
+     * 库外箱绑定至库位
+     */
+    public function bindBox()
+    {
+        $location = request("location");
+        $box = request("ide");
+        if (!$location || !$box)$this->error("参数传递错误");
+        $task = StationTaskMaterialBox::query()->select("id")->where(function ($query)use($location,$box){
+            /** @var Builder $query */
+            $query->whereHas("station",function ($query)use($location){
+                /** @var Builder $query */
+                $query->where("code",$location);
+            })->orWhereHas("materialBox",function ($query)use($box){
+                /** @var Builder $query */
+                $query->where("code",$box);
+            });
+        })->whereNotIn("status",["完成","取消"])->first();
+        if ($task)$this->error("库位或料箱存在任务待执行,无法放置料箱");
+        $ks = DB::connection("mysql_haiRobotics")->table("ks_bin")->select(DB::raw("1"))
+            ->where("ks_bin_code",$box)->where("status",4)->first();
+        if (!$ks)$this->error("海柔料箱状态异常");
+        DB::beginTransaction();
+        try {
+            $station = Station::query()->where("code",$location)->where("status",0)->first();
+            $box = MaterialBox::query()->where("code",$box)->first();
+            if (!$station || !$box)$this->error("库位或料箱未在WAS记录");
+            $station->update(["material_box_id"=>$box->id]);
+            DB::commit();
+            $this->success();
+        }catch (\Exception $e){
+            DB::rollBack();
+            $this->error($e->getMessage());
+        }
+    }
+
+    public function bindModelIndex(){
+        $models = MaterialBoxModel::query()->get();
+        return view("store.inStorage.boxBindModel",compact("models"));
+    }
+
+    public function searchIde()
+    {
+        $ide = request("ide");
+        $box = MaterialBox::query()->where("code",$ide)->first();
+        if (!$box)$this->error("料箱不存在");
+        $this->success($box->material_box_model_id);
+    }
+
+    public function boxBindModel()
+    {
+        $this->success(MaterialBox::query()->where("code",request("ide"))
+            ->update(["material_box_model_id"=>request("material_box_model_id")]));
+    }
+
+    public function commodityBindModel()
+    {
+        $models = MaterialBoxModel::query()->get();
+        return view("store.inStorage.commodityBindModel",compact("models"));
+    }
+
+    public function getModels()
+    {
+        $this->success(MaterialBoxModel::query()->select("id","code","description","maximum_kind")->get());
+    }
+
+    /**
+     * 设定料箱最大
+     */
+    public function settingModelMaximum()
+    {
+        $insert = function ($commodityId){
+            $in = [];
+            $map = [];
+            $ids = [];
+            foreach (request("models") as $model){
+                $insert[] = [
+                    "commodity_id" => $commodityId,
+                    "material_box_model_id" => $model["id"],
+                    "maximum" => $model["maximum"]
+                ];
+                $map[$model["id"]] = $model;
+                $ids[] = $model["id"];
+            }
+            return array($in,$map,$ids);
+        };
+        if (request("commodityId")){
+            list($in,$map,$ids) = $insert(request("commodityId"));
+            if ($ids){
+                $map = array_flip($ids);
+                foreach (CommodityMaterialBoxModel::query()->whereIn("id",$ids)->lockForUpdate()->get() as $model){
+                    $index = $map[$model->id];
+                    if ($model->maximum != $in[$index]["maximum"])$model->update(["maximum"=>$in[$index]["maximum"]]);
+                    unset($in[$index]);
+                }
+                $in = array_values($in);
+            }
+            if ($in){
+                LogService::log(__CLASS__,__METHOD__,json_encode($in));
+                CommodityMaterialBoxModel::query()->insert($in);
+            }
+            $this->success();
+        }
+        $item = StoreItem::query()->whereHas("store",function (Builder $query){
+            $query->where("asn_code",request("asn"));
+        })->whereHas("commodity",function (Builder $query){
+            $query->whereHas("barcodes",function (Builder $query){
+                $query->where("code",request("barCode"));
+            });
+        })->first();
+        if (!$item)$this->error("商品不存在");
+        list($in,$map,$ids) = $insert($item->store->commodity_id);
+        LogService::log(__CLASS__,__METHOD__,json_encode($in));
+        CommodityMaterialBoxModel::query()->insert($in);
+        $this->getMaterBoxModel($item,$map);
+    }
+
+    private function getMaterBoxModel($item,$map)
+    {
+        $models = app("MaterialBoxModelService")->getModelSortedByOwner($item->store->owner_id);
+        foreach ($models as $model){
+            if (!isset($map[$model->id]))continue;
+            $result = app("StorageService")->getHalfBoxLocation($map[$model->id],$item,$item->store->asn_code);
+            if (!$result)continue;
+            $result->maximum = $model->maximum-$result->amount;
+            $this->success($result);
+        }
+        $this->success(["need"=>$models[0]->maximum,"material_box_model_id"=>$models[0]->material_box_model_id,"commodity_id"=>$item->commodity_id]);
+    }
+
+    /**
+     * 根据条码检索商品
+     */
+    public function searchBarCode()
+    {
+        $commodities = Commodity::query()->whereHas("barcodes",function (Builder $query){
+            $query->where("code",request("barCode"));
+        })->get();
+        if (!$commodities->count())$this->error("库内无此商品信息");
+        if ($commodities->count()>1)$commodities->load("owner");
+        $this->success($commodities);
+    }
 }

+ 4 - 7
app/Http/Controllers/StoreController.php

@@ -7,7 +7,6 @@ use App\Owner;
 use App\Services\common\BatchUpdateService;
 use App\Services\StoreService;
 use App\Station;
-use App\Storage;
 use App\Store;
 use App\StoreItem;
 use App\Warehouse;
@@ -440,11 +439,8 @@ class StoreController extends Controller
      */
     public function cacheRackStorage()
     {
-        $stations = Station::query()->select("id")->where("parent_id",6);
-        $storages = Storage::query()->with("station:id,code")->whereIn("station_id",$stations)->where(function (Builder $query){
-            $query->whereNotNull("material_box_id")->orWhere("status",1);
-        })->get();
-        return \view("store.inStorage.cacheRackStorage",compact("storages"));
+        $stations = Station::query()->where("parent_id",6)->get();
+        return \view("store.inStorage.cacheRackStorage",compact("stations"));
     }
 
     /**
@@ -452,6 +448,7 @@ class StoreController extends Controller
      */
     public function halfChestStorage()
     {
-        return \view("store.inStorage.halfChestStorage");
+        $stations = app("StationService")->getCacheShelf();
+        return \view("store.inStorage.halfChestStorage",compact("stations"));
     }
 }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 135 - 79
app/Http/Controllers/TestController.php


+ 1 - 1
app/Http/Controllers/UnitController.php

@@ -34,7 +34,7 @@ class UnitController extends Controller
 
         $obj = ["name"=>request("name"),"sequence"=>request("sequence") ?? 0];
         if (request("id")){
-            Unit::query()->update($obj);
+            Unit::query()->where("id",request("id"))->update($obj);
             $this->success();
         }
         $this->success(Unit::query()->create($obj));

+ 72 - 6
app/Http/Controllers/WaybillController.php

@@ -6,6 +6,7 @@ namespace App\Http\Controllers;
 use App\CarType;
 use App\Components\AsyncResponse;
 use App\Logistic;
+use App\Owner;
 use App\Region;
 use App\Services\CarTypeService;
 use App\Services\LogisticService;
@@ -73,6 +74,7 @@ class WaybillController extends Controller
         $type=$request->type ?? "";
         if ($type==='ZF')$type='直发车';
         if ($type==='ZX')$type='专线';
+        if ($type==='DBWL')$type='德邦物流';
         return view('transport.waybill.create',['owners'=>$ownerService->getIntersectPermitting(),'type'=>$type]);
     }
 
@@ -87,7 +89,6 @@ class WaybillController extends Controller
 
     public function edit($id,LogisticService $logisticService,CarTypeService $carTypeService,UnitService $unitService)
     {
-        //if(!Gate::allows('运输管理-编辑')){ return redirect(url('denied'));  }
         $waybill = app('waybillService')->find($id);
         if ($waybill->order_id){
             /** @var Waybill $waybill */
@@ -97,6 +98,7 @@ class WaybillController extends Controller
             /** @var Waybill $waybill */
             $waybill->load("owner");
         }
+        if ($waybill->merge_owner)$waybill->merge_owner = implode(",",array_column(Owner::query()->select("name")->whereIn("id",explode(",",$waybill->merge_owner))->get()->toArray(),"name"));
         /** @var \stdClass $waybill */
         if (!$waybill)return view("exception.default",["code"=>"500","message"=>"数据已被删除或丢失"]);
         if ($waybill->deliver_at){
@@ -107,7 +109,10 @@ class WaybillController extends Controller
         $units=$unitService->getSelection();
         $carTypes=$carTypeService->getSelection();
         $deliveryType = app('DeliveryTypeService')->getSelection();
-        return view('transport.waybill.edit',['waybill'=>$waybill,'logistics'=>$logisticService->getSelection(["id","name"],"物流"),'cities'=>$cities,'units'=>$units,'carTypes'=>$carTypes,'deliveryTypes'=>$deliveryType]);
+        return view('transport.waybill.edit',['waybill'=>$waybill,'logistics'=>$logisticService->getSelection(["id","name","tag"],"物流"),'cities'=>$cities,'units'=>$units,'carTypes'=>$carTypes,
+            'deliveryTypes'=>$deliveryType,'orderTypes' =>collect(config('api_logistic.DB.prod.orderType')),'transportTypes' => collect(config('api_logistic.DB.prod.transportType'))
+            ,'payTypes' => collect(config('api_logistic.DB.prod.payType')),'backSignBills' => collect(config('api_logistic.DB.prod.backSignBill')),'packageServices' => collect(config('api_logistic.DB.prod.packageService'))
+        ]);
     }
 
     public function update(Request $request, $id,WaybillPriceModelService $waybillPriceModelService,
@@ -172,10 +177,10 @@ class WaybillController extends Controller
             'user_id'=>Auth::id(),
         ]);
         //todo 若是德邦物流 请求API创建快递单号
-        $logistic_ids = Logistic::query()->where('name','like', '德邦%')->pluck('id')->toArray();
+        $logistic_ids = Logistic::query()->where('name','like', '德邦%')->where('type','=','物流')->pluck('id')->toArray();
         if (in_array($request['logistic_id'], $logistic_ids)){
-            $row = app('DbOpenService')->getDbOrderNo(['id' => $id]);
-            if ($row == 'false') $msg = '-- 生成德邦快递单号失败,请核实参数重新调度';
+            $res = app('DbOpenService')->getDbOrderNo(['id' => $id]);
+            $msg =  $res['msg']? "【申请德邦物流单号:".$res['msg']."】"  :'';
         }
         return redirect('transport/waybill/index')->with('successTip','运单“'.$waybill->waybill_number.'”调度成功 '. ($msg??''));
     }
@@ -291,12 +296,17 @@ class WaybillController extends Controller
         $validatorData=["logistic_id"=>$logistic_id,"destination_city_id"=>$destination_city_id,
             'carrier_weight'=>$carrier_weight[0],"carrier_weight_unit_id"=>$carrier_weight_unit_id[0],
             "carrier_weight_other"=>$carrier_weight[1],"carrier_weight_unit_id_other"=>$carrier_weight_unit_id[1]];
-        if (in_array($logistic_id,[14,15,28,29])){
+        if ($logistic_id == 15){
             $flag = 1;
             $validatorData['cargo_name'] = $request->input('cargo_name');
             $validatorData['total_number'] = $request->input('total_number');
             $validatorData['total_weight'] = $request->input('total_weight');
             $validatorData['deliveryType_id'] = $request->input('deliveryType_id');
+            $validatorData['order_type'] = $request->input('order_type');
+            $validatorData['transport_type'] = $request->input('transport_type');
+            $validatorData['pay_type'] = $request->input('pay_type');
+            $validatorData['back_sign_bill'] = $request->input('back_sign_bill');
+            $validatorData['package_service'] = $request->input('package_service');
         }else $flag = 0;
         $errors=Validator::make($validatorData,[
             'logistic_id'=>'required|integer',
@@ -309,6 +319,11 @@ class WaybillController extends Controller
             'total_number' => $flag ? 'required|min:0|numeric|max:999999' : '',
             'total_weight' => $flag ? 'required|min:0|numeric|max:999999' : '',
             'deliveryType_id' => $flag ? 'required' : '',
+            'order_type' => $flag ? 'required' : '',
+            'transport_type' => $flag ? 'required' : '',
+            'pay_type' => $flag ? 'required' : '',
+            'back_sign_bill' => $flag ? 'required' : '',
+            'package_service' => $flag ? 'required' : '',
         ],[
             'required'=>':attribute 为必填项',
             'max'=>':attribute 字符过多或输入值过大',
@@ -328,6 +343,10 @@ class WaybillController extends Controller
             'total_number' =>  '总包裹数',
             'total_weight' =>  '总重量',
             'deliveryType_id' => '送货方式',
+            'order_type' => '下单模式',
+            'transport_type' => '运输方式/产品类型',
+            'pay_type' => '支付方式',
+            'back_sign_bill' => '签收回单',
         ])->errors();
         if (count($errors)>0)return ['error'=>$errors];
         $result=$this->checkWaybillPriceModel($logistic_id,$destination_city_id,$carrier_weight,$carrier_weight_unit_id);
@@ -804,6 +823,7 @@ class WaybillController extends Controller
             'carrier_weight_unit_id'=>'sometimes|required_with:carrier_weight',
             'carrier_weight_other'=>'sometimes|nullable|min:0|numeric|max:999999',
             'carrier_weight_unit_id_other'=>'sometimes|required_with:carrier_weight_other',
+            'deliver_at_date'=>'required',
         ];
         if ($request->type == '专线'){
             $rule['origination_city_id']='required|integer';
@@ -838,6 +858,7 @@ class WaybillController extends Controller
             'carrier_weight_other'=>'承运商计数二',
             'warehouse_weight_unit_id_other'=>'仓库技数单位二',
             'carrier_weight_unit_id_other'=>'承运商计数单位二',
+            'deliver_at_date'=>'发货日期',
         ]);
         return $validator;
     }
@@ -1001,4 +1022,49 @@ class WaybillController extends Controller
         return ['success'=>true,'data'=>$total_pick_up_fee];
     }
 
+    /**
+     * 运单合并
+     */
+    public function waybillMerge(Request $request)
+    {
+        $this->gate("运输管理-编辑");
+        $ids = $request->input("ids");
+        if (!$ids || count($ids)<2)$this->error("至少选择两条记录");
+        /** @var Collection $waybills */
+        $waybills = Waybill::query()->with("order")->whereIn("id",$ids)->orderBy("order_id")->get();
+        if ($waybills->count()<2)$this->error("运单不存在");
+        $waybill = $waybills->first();
+        $destroys = [];
+        $owner = [$waybill->owner_id];
+        for ($i=1;$i<$waybills->count();$i++){
+            //信息一致性校验
+            $identical = ($waybill->order && ($waybills[$i]->order->consignee_name!=$waybill->order->consignee_name
+                        || $waybills[$i]->order->consignee_phone!=$waybill->order->consignee_phone
+                        || $waybills[$i]->order->address!=$waybill->order->address)) ||
+                (!$waybill->order && ($waybills[$i]->recipient!=$waybill->recipient
+                    || $waybills[$i]->recipient_mobile!=$waybill->recipient_mobile
+                    || $waybills[$i]->destination!=$waybill->destination));
+            if (array_search($waybills[$i]->status,["未审核","已审核"])===false
+                || $identical)$this->error("信息不一致,无法进行合并");
+            $destroys[] = $waybills[$i]->id;
+            $waybill->source_bill .= $waybills[$i]->source_bill ? ",".$waybills[$i]->source_bill : '';
+            $waybill->wms_bill_number .= $waybills[$i]->wms_bill_number ? ",".$waybills[$i]->wms_bill_number : '';
+            $waybill->charge += (double)$waybills[$i]->charge;
+            $waybill->collect_fee += (double)$waybills[$i]->collect_fee;
+            $waybill->other_fee += (double)$waybills[$i]->other_fee;
+            $waybill->warehouse_weight_other += (double)$waybills[$i]->warehouse_weight_other;
+            $waybill->warehouse_weight += (double)$waybills[$i]->warehouse_weight;
+            $owner[] = $waybills[$i]->owner_id;
+        }
+        $owner = array_unique($owner);
+        if (count($owner)>1)$waybill->merge_owner = implode(',',$owner);
+        $waybill->update();
+        Waybill::destroy($destroys);
+        WaybillAuditLog::query()->create([
+            'waybill_id'=>$waybill->id,
+            'audit_stage'=>'合并运单',
+            'user_id'=>Auth::id(),
+        ]);
+        $this->success($waybill->waybill_number);
+    }
 }

+ 2 - 2
app/Http/Controllers/api/email/SendEmailsController.php

@@ -19,12 +19,12 @@ class SendEmailsController extends Controller
                 'description'=>$request['description'],
             ];
         }else{
-            $email=User::query()->where('name','ldaaww')->pluck('email');
+            $email=User::query()->where('name','zhouzhendong')->pluck('email');
             $load=[
                 'title'=>'上传代码邮件通知',
                 'description'=>'开发者上传代码成功,如需部署请做后续操作',
             ];
         }
-        event(new GitPushedEvent($email,$load));
+        if ($email)event(new GitPushedEvent($email,$load));
     }
 }

+ 14 - 6
app/Http/Middleware/LogPostRequest.php

@@ -2,11 +2,14 @@
 
 namespace App\Http\Middleware;
 
+use App\Components\ErrorPush;
 use App\Services\LogService;
 use Closure;
+use Illuminate\Support\Facades\Auth;
 
 class LogPostRequest
 {
+    use ErrorPush;
     /**
      * Handle an incoming request.
      *
@@ -16,12 +19,17 @@ class LogPostRequest
      */
     public function handle($request, Closure $next)
     {
-        if($request->method()!='GET'){
-            LogService::log($request->fullUrl(),$request->method(),
-                '请求:'.json_encode($request->all())
-                .'请求头:'.json_encode($request->headers->all())
-            );
+        try {
+            if($request->method()!='GET'){
+                LogService::log($request->fullUrl(),$request->method(),
+                    '请求:'.json_encode($request->all())
+                    .'请求头:'.json_encode($request->headers->all())
+                );
+            }
+            return $next($request);
+        }catch (\Exception $e){
+            $this->push(__METHOD__."->".__LINE__,"路径跳转捕获",$e->getMessage()."  请求用户:".Auth::id()."  request对象:".json_encode($request));
+            return view("exception.404");
         }
-        return $next($request);
     }
 }

+ 39 - 0
app/Http/Requests/RequirementRequest.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Http\Requests;
+
+
+class RequirementRequest extends Request
+{
+    public function rules()
+    {
+        switch($this->method())
+        {
+            case 'POST':
+            case 'PUT':
+            case 'PATCH':
+            {
+                return [
+                    'content'       => 'required|min:3',
+                    'title'       => 'required|min:3',
+                    'score' => 'required|numeric',
+                ];
+            }
+            case 'GET':
+            case 'DELETE':
+            default:
+            {
+                return [];
+            }
+        }
+    }
+
+    public function messages()
+    {
+        return [
+            'content.min' => '内容至少为3个字符',
+            'title.min' => '内容至少为3个字符',
+            'score.numeric' => '分数必须为数字',
+        ];
+    }
+}

+ 10 - 0
app/Interfaces/ErrorPush.php

@@ -0,0 +1,10 @@
+<?php
+
+
+namespace App\Interfaces;
+
+
+interface ErrorPush
+{
+    public function push(string $path, string $title, string $content): bool;
+}

+ 1 - 2
app/Jobs/HandlePastBill.php

@@ -7,11 +7,10 @@ use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Foundation\Bus\Dispatchable;
 use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
 
 class HandlePastBill implements ShouldQueue
 {
-    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+    use Dispatchable, InteractsWithQueue, Queueable;
 
     protected $arr;
     /**

+ 1 - 0
app/Listeners/SettlementBillCreateListener.php

@@ -31,6 +31,7 @@ class SettlementBillCreateListener implements ShouldQueue
         $createData = $event->createData;
         /** @var Model $modelName */
         $modelName = $event->modelName;
+        $modelName::uDelete($createData);
         $modelName::query()->updateOrCreate($createData);
     }
 }

+ 14 - 1
app/Logistic.php

@@ -17,8 +17,13 @@ class Logistic extends Model
     use ModelLogChanging;
     use SoftDeletes;
     use ModelTimeFormat;
-    protected $fillable = ['name','code',"type","mobile","remark","delivery_fee","is_bunched","english_name",'belong_company'];
+    protected $fillable = ['name','code',"type","mobile","remark","delivery_fee","is_bunched","english_name",'belong_company',"tag"];
 
+    const TAGS=[
+        0 => "专线",
+        1 => "直发车",
+        2 => "德邦",
+    ];
 
     static function nameById($id){
         $logistic=Logistic::where('id',$id)->first();
@@ -29,4 +34,12 @@ class Logistic extends Model
     {
         return $this->belongsToMany(OwnerPriceExpress::class,"owner_price_express_logistic","logistic_id","owner_price_express_id");
     }
+
+    public function getTagAttribute($value):string
+    {
+        if ($value==="" || $value===null)return "";
+        $tag = explode(",",$value);
+        foreach ($tag as &$t)$t = self::TAGS[$t];
+        return implode(",",$tag);
+    }
 }

+ 5 - 0
app/MaterialBox.php

@@ -5,6 +5,7 @@ namespace App;
 use Illuminate\Database\Eloquent\Model;
 
 use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\HasOne;
 
 class MaterialBox extends Model
 {
@@ -33,6 +34,10 @@ class MaterialBox extends Model
         parent::__construct($attributes);
     }
 
+    public function station():HasOne
+    {
+        return $this->hasOne(Station::class);
+    }
     public function getStatusAttribute($value)
     {
         if(!$value)return '';

+ 22 - 0
app/MaterialBoxCommodity.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+
+class MaterialBoxCommodity extends Model
+{
+    use ModelLogChanging;
+
+    protected $fillable=[
+        "material_box_id","commodity_id","amount"
+    ];
+
+    public function materialBox():BelongsTo
+    {
+        return $this->belongsTo(MaterialBox::class);
+    }
+}

+ 7 - 1
app/MaterialBoxModel.php

@@ -5,12 +5,18 @@ namespace App;
 use Illuminate\Database\Eloquent\Model;
 
 use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\HasOne;
 
 class MaterialBoxModel extends Model
 {
     use ModelLogChanging;
 
     protected $fillable=[
-        "code"
+        "code","description","maximum_kind"
     ];
+
+    public function commodity():HasOne
+    {
+        return $this->hasOne(CommodityMaterialBoxModel::class);
+    }
 }

+ 21 - 0
app/OracleBasLotId.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+use App\Traits\ModelLogChanging;
+
+/**
+ * DB:      FLUX/WMS_USER
+ * TABLE:   BAS_LOTID
+ * EXPLAIN: 批次属性规则表
+ */
+class OracleBasLotId extends Model
+{
+    use ModelTimeFormat;
+    use ModelLogChanging;
+
+    protected $connection="oracle";
+    protected $table="BAS_LOTID";
+}

+ 5 - 1
app/OracleBasSKU.php

@@ -9,7 +9,6 @@ use Illuminate\Database\Eloquent\Model;
  * EXPLAIN: 商品
  */
 use App\Traits\ModelTimeFormat;
-
 use App\Traits\ModelLogChanging;
 
 class OracleBasSKU extends Model
@@ -26,4 +25,9 @@ class OracleBasSKU extends Model
      *         Descr_C 商品名称
      *
      * */
+    public function lotId()
+    {
+        return $this->hasOne(OracleBasLotId::class,'lotid','lotid')
+            ->select('lotid','lotkey01','lotkey02','lotkey03','lotkey04','lotkey05','lotkey08');
+    }
 }

+ 0 - 1
app/OracleDOCASNHeader.php

@@ -4,7 +4,6 @@ namespace App;
 
 use App\Traits\ModelTimeFormat;
 use Illuminate\Database\Eloquent\Model;
-
 use App\Traits\ModelLogChanging;
 
 class OracleDOCASNHeader extends Model

+ 2 - 1
app/Owner.php

@@ -37,7 +37,8 @@ class Owner extends Model
         "user_workgroup_id",    //仓库小组(工作组)
         "relevance",            //关联模型的JSON数组
         'subjection',           //主体公司
-        'is_tax_exist'          //是否必填税率
+        'is_tax_exist',         //是否必填税率
+        'model_sequence'        //调箱序列(优先级匹配)
     ];
     //relevance说明 0:仓储 1:作业 2:快递 3:物流 4:直发 5:系统 存储示例:["0","1"]存在仓储与作业计费
     protected $casts = [

+ 4 - 0
app/OwnerFeeDetail.php

@@ -59,6 +59,10 @@ class OwnerFeeDetail extends Model
     {   //出库单
         return $this->belongsTo(Order::class,"outer_id","id");
     }
+    public function store()
+    {   //入库单
+        return $this->belongsTo(Store::class,"outer_id","id");
+    }
     public function items()
     {   //快递费子项
         return $this->hasMany(OwnerFeeDetailLogistic::class,"owner_fee_detail_id","id");

+ 17 - 0
app/OwnerLogisticFeeDetail.php

@@ -41,4 +41,21 @@ class OwnerLogisticFeeDetail extends Model
     {
         return $this->belongsTo(Logistic::class);
     }
+
+    /**
+     * 根据参数条件删除
+     * @param $data
+     */
+    public static function uDelete($data)
+    {
+        self::query()
+            ->where('owner_fee_detail_id', $data['owner_fee_detail_id'])
+            ->where('logistic_bill', $data['logistic_bill'])
+            ->where('initial_weight', $data['initial_weight'])
+            ->where('additional_weight', $data['additional_weight'])
+            ->where('logistic_id', $data['logistic_id'])
+            ->where('owner_id', $data['owner_id'])
+            ->where('additional_weigh_weight', $data['additional_weigh_weight'])
+            ->delete();
+    }
 }

+ 3 - 0
app/OwnerMaterial.php

@@ -38,6 +38,9 @@ class OwnerMaterial extends Model
     public function getSpecificationAttribute($value){
         return str_replace(array("\r\n","\n","\r","\"","&quot;"),' ',$value);
     }
+    public function getSpecialAttribute($value){
+        return str_replace(array("\r\n","\n","\r","\"","&quot;"),' ',$value);
+    }
 
     public function scopeFilter($query,$filters)
     {

+ 19 - 0
app/OwnerStoreFeeDetail.php

@@ -52,4 +52,23 @@ class OwnerStoreFeeDetail extends Model
     {
         return $this->belongsTo(Commodity::class);
     }
+
+
+    /**
+     * 根据参数条件删除
+     * @param $data
+     */
+    public static function uDelete($data)
+    {
+        self::query()
+            ->where('owner_fee_detail_id', $data['owner_fee_detail_id'])
+            ->where('unit_id', $data['unit_id'])
+            ->where('owner_id', $data['owner_id'])
+            ->where('commodity_id', $data['commodity_id'])
+            ->where('sku', $data['sku'])
+            ->where('barcode', $data['barcode'])
+            ->where('work_name', $data['work_name'])
+            ->where('asn_code', $data['asn_code'])
+            ->delete();
+    }
 }

+ 19 - 1
app/OwnerStoreOutFeeDetail.php

@@ -27,7 +27,7 @@ class OwnerStoreOutFeeDetail extends Model
         'barcode',//商品条码
         'work_name',//作业名称
         'fee',//费用
-        ];
+    ];
 
     public function ownerFeeDetail(): BelongsTo
     {
@@ -48,4 +48,22 @@ class OwnerStoreOutFeeDetail extends Model
     {
         return $this->belongsTo(Unit::class);
     }
+
+    /**
+     * 根据参数条件删除
+     * @param $data
+     */
+    public static function uDelete($data)
+    {
+        self::query()
+            ->where('owner_fee_detail_id',$data['owner_fee_detail_id'])
+            ->where('commodity_id',$data['commodity_id'])
+            ->where('owner_id',$data['owner_id'])
+            ->where('source_bill',$data['source_bill'])
+            ->where('unit_id',$data['unit_id'])
+            ->where('sku',$data['sku'])
+            ->where('barcode',$data['barcode'])
+            ->where('work_name',$data['work_name'])
+            ->delete();
+    }
 }

+ 9 - 0
app/OwnerWayBillFeeDetail.php

@@ -37,4 +37,13 @@ class OwnerWayBillFeeDetail extends Model
     {
         return $this->belongsTo(Unit::class);
     }
+
+    /**
+     * 根据参数条件删除
+     * @param $data
+     */
+    public static function uDelete($data)
+    {
+
+    }
 }

+ 37 - 0
app/Policies/RequirementPolicy.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Policies;
+
+use App\User;
+use Illuminate\Auth\Access\HandlesAuthorization;
+
+class RequirementPolicy
+{
+    use HandlesAuthorization;
+
+    /**
+     * Create a new policy instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    public function update(User $user, \App\Requirement $requirement)
+    {
+        // return $owner_sundry_fee_detail->user_id == $user->id;
+        return true;
+    }
+
+    public function destroy(User $user, \App\Requirement $requirement)
+    {
+        return $requirement->status != '已完成';
+    }
+
+    public function begin(User $user ,\App\Requirement $requirement)
+    {
+        return $requirement->status == '已发布';
+    }
+}

+ 10 - 0
app/Providers/AppServiceProvider.php

@@ -158,6 +158,11 @@ use App\Services\OwnerWayBillFeeDetailService;
 use App\Services\SettlementIndemnityFeeService;
 use App\Services\DbOpenService;
 use App\Services\DeliveryTypeService;
+use App\Services\ErrorPushService;
+use App\Services\MaterialBoxModelService;
+use App\Services\HandInStorageService;
+use App\Services\RequirementService;
+use App\Services\RequirementUserService;
 
 class AppServiceProvider extends ServiceProvider
 {
@@ -247,11 +252,13 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('DemandService',DemandService::class);
         app()->singleton('DepositoryService',DepositoryService::class);
         app()->singleton('DischargeTaskService',DischargeTaskService::class);
+        app()->singleton('ErrorPushService',ErrorPushService::class);
         app()->singleton('FacilitatorService',FacilitatorService::class);
         app()->singleton('FeatureService',FeatureService::class);
         app()->singleton('ForeignHaiRoboticsService',ForeignHaiRoboticsService::class);
         app()->singleton('ForeignZhenCangService',ForeignZhenCangService::class);
         app()->singleton('GoodScanWeightService',GoodScanWeightService::class);
+        app()->singleton('HandInStorageService',HandInStorageService::class);
         app()->singleton('HaoChuangWeightService',HaoChuangWeightService::class);
         app()->singleton('HengLiWeightService',HengLiWeightService::class);
         app()->singleton('InventoryAccountMissionService', InventoryAccountMissionService::class);
@@ -270,6 +277,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('LogisticYTOService', LogisticYTOService::class);
         app()->singleton('LogisticZopService', LogisticZopService::class);
         app()->singleton('LogisticZopService', LogisticZopService::class);
+        app()->singleton('MaterialBoxModelService',MaterialBoxModelService::class);
         app()->singleton('MaterialBoxService', MaterialBoxService::class);
         app()->singleton('MenuService',MenuService::class);
         app()->singleton('NewOrderCountingRecordService',NewOrderCountingRecordService::class);
@@ -339,6 +347,8 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('RejectedBillItemService', RejectedBillItemService::class);
         app()->singleton('RejectedBillService', RejectedBillService::class);
         app()->singleton('RejectedService', RejectedService::class);
+        app()->singleton('RequirementService',RequirementService::class);
+        app()->singleton('RequirementUserService',RequirementUserService::class);
         app()->singleton('RoleService',RoleService::class);
         app()->singleton('SettlementBillsAreaFeeService',SettlementBillsAreaFeeService::class);
         app()->singleton('SettlementIndemnityFeeService',SettlementIndemnityFeeService::class);

+ 1 - 0
app/Providers/AuthServiceProvider.php

@@ -23,6 +23,7 @@ class AuthServiceProvider extends ServiceProvider
      */
     protected $policies = [
 		 \App\OwnerSundryFeeDetail::class => \App\Policies\OwnerSundryFeeDetailPolicy::class,
+		 \App\Requirement::class => \App\Policies\RequirementPolicy::class,
         // 'App\Model' => 'App\Policies\ModelPolicy',
         CustomerLog::class => CustomerLogPolice::class,
 

+ 79 - 0
app/Requirement.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
+
+class Requirement extends Model
+{
+    use ModelLogChanging;
+
+    use \App\Traits\ModelTimeFormat;
+
+    use \Illuminate\Database\Eloquent\SoftDeletes;
+
+    //
+    public $fillable = [
+        'user_id',//状态
+        'content', //内容
+        'title', //标题
+        'score', //分数
+        'status',//状态
+        'began_at',//开始时间
+        'finished_at',//完成时间
+    ];
+
+    public $dates = [
+        'began_at',//开始时间
+        'finished_at',//完成时间
+    ];
+
+    static public $enums=[
+        'status'=>[
+            ''=>0,
+            '已发布'=>1,
+            '已开始'=>2,
+            '已完成'=>3,
+        ],
+    ];
+    function __construct(array $attributes = [])
+    {
+        foreach (self::$enums as &$enum) {
+            $enum=$enum+array_flip($enum);
+        }
+        parent::__construct($attributes);
+    }
+
+    public function getStatusAttribute($value)
+    {
+        if(!$value)return '';
+        return self::$enums['status'][$value];
+    }
+    public function setStatusAttribute($value)
+    {
+        if(!$value)return 0;
+        $this->attributes['status']=self::$enums['status'][$value];
+    }
+
+
+    public function creator(): BelongsTo
+    {
+        return $this->belongsTo(User::class,'user_id','id');
+    }
+
+    public function workers(): BelongsToMany
+    {
+        return $this->belongsToMany(User::class)
+            ->using(RequirementUser::class)
+            ->withPivot(['score']);
+    }
+
+    public function scopeFilter($query, $filters)
+    {
+        return $filters->apply($query);
+    }
+}

+ 18 - 0
app/RequirementUser.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App;
+
+
+use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\Pivot;
+
+class RequirementUser extends Pivot
+{
+    use ModelLogChanging;
+
+    public $fillable = ['score'];
+
+    public $incrementing = true;
+
+    public $timestamps = false;
+}

+ 6 - 22
app/Services/BatchService.php

@@ -75,28 +75,16 @@ class BatchService
             $this->instant($this->stationTaskCommodityService,'StationTaskCommodityService');
             $this->instant($this->stationTaskMaterialBoxService,'StationTaskMaterialBoxService');
 
-            $stationTaskBatches=null;
             $stationTasks=null;
-            app('LogService')->log('海柔','assignTasks2',json_encode($batches));
             $batches_shouldProcess = $this->stationRuleBatchService->getBatches_shouldProcess($batches); //按规则过滤需要的波次
             if($batches_shouldProcess->isEmpty()) return;
-//            $stationTaskMaterialBoxes_occupied = $this->stationTaskMaterialBoxService->getOccupied_byBatches($batches_shouldProcess); //过滤料箱被占用的波次
-//            app('LogService')->log('海柔','assignTasks2.5',json_encode($stationTaskMaterialBoxes_occupied));
-//            if($stationTaskMaterialBoxes_occupied->isNotEmpty()) {
-//                foreach ($batches_shouldProcess as $batch){
-//                    Cache::tags(['波次防重叠'.$batch['id']])->flush();
-//                }
-//                BatchTaskJob::dispatch($batches_shouldProcess)
-//                    ->delay(now()->addMinutes(1));    //因为料箱被占用了,所以将任务推迟1分钟后尝试
-//                return;
-//            }
+
             app('LogService')->log('海柔','assignTasks3',json_encode($batches_shouldProcess));
-            DB::transaction(function ()use($batches,&$stationTaskBatches,&$batches_shouldProcess,&$stationTasks){
+            DB::transaction(function ()use($batches,&$batches_shouldProcess,&$stationTasks){
                 $stationTasks =  $this->stationTaskService->create($batches_shouldProcess->count()); //生成总任务
-                $stationTaskBatches=$this->stationTaskBatchService->createByBatches($batches_shouldProcess,$stationTasks); //注册波次任务
-                $stationTaskMaterialBoxes=$this->stationTaskMaterialBoxService->createByBatches($batches_shouldProcess,$stationTasks); //注册料箱任务
-                $stationTaskCommodities=$this->stationTaskCommodityService->createByBatches($batches_shouldProcess,$stationTasks); //注册商品任务
-                app('LogService')->log('海柔','assignTasks4',json_encode($batches_shouldProcess));
+                $this->stationTaskBatchService->createByBatches($batches_shouldProcess,$stationTasks); //注册波次任务
+                $this->stationTaskMaterialBoxService->createByBatches($batches_shouldProcess,$stationTasks); //注册料箱任务
+                $this->stationTaskCommodityService->createByBatches($batches_shouldProcess,$stationTasks); //注册商品任务
             });
             foreach ($stationTasks as &$stationTask){
                 $stationTask->loadMissing([
@@ -106,19 +94,15 @@ class BatchService
                     "stationTaskMaterialBoxes.materialBox",
                 ]);
             }
-            app('LogService')->log('海柔','assignTasks5',json_encode($stationTasks,true).json_encode($batches_shouldProcess));
             $jsonStationTasks=json_encode($stationTasks,true);
             broadcast(new BroadcastToStation(BroadcastToStation::ALL_STATION, $jsonStationTasks));
-            app('LogService')->log('海柔','assignTasks6',$jsonStationTasks.json_encode($batches_shouldProcess));
-//            $ran=$this->stationTaskBatchService->runMany($stationTaskBatches);//执行波次任务
         }catch(Exception $e){
-            app('LogService')->log('海柔','assignTasks7',json_encode($batches));
             $batchesJson='';
             foreach ($batches as $batch){
                 $batchesJson.=json_encode($batch);
                 Cache::tags(['波次防重叠'.$batch['id']])->flush();
             }
-            app('LogService')->log('海柔','assignTasks8',json_encode($batches));
+            app('LogService')->log('海柔','注册任务失败',$e->getMessage()." | ".json_encode($batches));
             throw new ErrorException('注册任务失败: '. $batchesJson . $e->getMessage().json_encode($e->getTrace()));
         }
     }

+ 3 - 110
app/Services/CacheShelfService.php

@@ -7,13 +7,9 @@ use App\Exceptions\ErrorException;
 use App\MaterialBox;
 use App\Station;
 use App\StationTask;
-use App\StationTaskChild;
 use App\StationTaskChildren;
 use App\StationTaskMaterialBox;
-use App\StationType;
-use App\Storage;
 use App\Traits\ServiceAppAop;
-use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Http;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Collection;
@@ -60,7 +56,6 @@ class   CacheShelfService
         }])->where('code', $locCode)->first();
         //站存在 站为缓存架2 站为蓝灯状态
         if (app("StationService")->isHalfBoxLocation($station)){
-            if (!Storage::query()->where("station_id",$station->id)->whereNotNull("material_box_id")->first())return ['success' => false, 'errMsg' => "任务执行中,不允许灭灯"];
             if (!app("StorageService")->checkStorage($station)){
                 $this->lightUp($station->code,'0','1',["title"=>"上架失败,联系管理员"]);
                 return ['success' => false,'errMsg' => '上架任务失败'];
@@ -126,94 +121,7 @@ class   CacheShelfService
      */
     public function bindMaterialBox($stationCode, $materialBoxCode): array
     {
-        $station = Station::query()->with('storage')->where('code', $stationCode)->first();
-
-        if (!$station) {
-            $arr = [];
-            preg_match('/^HAI([\w]+)/', $stationCode, $arr);
-            $parentCode = $arr[1] ?? '';
-            $stationType = StationType::query()->where('name', '缓存架')->first();
-            $parentStation = Station::query()->firstOrCreate(['code' => $parentCode], ['station_type_id' => $stationType['id']]);
-            $station = Station::query()->firstOrCreate(['code' => $stationCode, 'parent_id' => $parentStation['id']], ['name' => $stationCode, 'station_type_id' => $stationType['id']]);
-        }
-
-        $materialBox = MaterialBox::query()->firstOrCreate(['code' => $materialBoxCode]);
-
-        $storage = $station->storage ?? Storage::query()->firstOrCreate(['station_id' => $station['id']]);
-
-        $result = $this->_stationCacheLightOn($station['code'],$materialBoxCode);
-        if($result['code'] == 200){
-            $storage->update(['material_box_id' => $materialBox['id'],'status' => 1]);
-            return ['success' => true];
-        }
-        return ['success' => false,'message' => $result['errMsg']];
-    }
-
-
-    /**
-     * 控制格口亮灯
-     * @param $locCode
-     * @param null $materialCode
-     * @param string $title
-     * @param string $color
-     * @return mixed
-     */
-    public function _stationCacheLightOn($locCode, $materialCode = null, $title = 'title', string $color = '1')
-    {
-        $params = [
-            "areaCode" => "1004",
-            'locCode' => $locCode,
-            'PTLAction' => 1,
-            'PTLSettings' => ['color' => $color, 'frequency' => 1],
-            "displayInfo" => [
-                "detail01" => $materialCode,
-                "detail02" => "detail02",
-                "detail03" => "detail03",
-                "qrCode" => "qrCode",
-                "qty00" => "11",
-                "qty01" => 1,
-                "qty02" => 2,
-                "title" => $title,
-                "uomDesc01" => "uo",
-                "uomDesc02" => "uo"
-            ],
-        ];
-        $response = Http::post(config('api.haiq.storage.light'), $params);
-        return json_decode($response->body());
-    }
-
-    /**
-     * 站亮灯
-     *
-     * @param string $stationCode
-     * @param string|null $materialCode
-     * @param string $color             explain: 0-red 1-green 2-blue 3-yellow
-     * @param string $frequency         explain: 0-常亮 1-一次 2-两次 3-三次 4-四次 5-五次 (均为/秒)
-     * @param string $title
-     * @return mixed
-     */
-    public function stationLightUp(string $stationCode,?string $materialCode = null, string $color = '1', string $frequency = '0', $title = '')
-    {
-        $params = [
-            "areaCode" => "1004",
-            'locCode' => $stationCode,
-            'PTLAction' => 1,
-            'PTLSettings' => ['color' => $color, 'frequency'  => $frequency],
-            "displayInfo" => [
-                "detail01" => $materialCode,
-                "detail02" => "detail02",
-                "detail03" => "detail03",
-                "qrCode" => "qrCode",
-                "qty00" => "11",
-                "qty01" => 1,
-                "qty02" => 2,
-                "title" => $title,
-                "uomDesc01" => "uo",
-                "uomDesc02" => "uo"
-            ],
-        ];
-        $response = Http::post(config('api.haiq.storage.light'), $params);
-        return json_decode($response->body());
+        return ['success' => false,'message' => "接口废弃"];
     }
 
     /**
@@ -293,21 +201,6 @@ class   CacheShelfService
         }
     }
 
-    /**
-     * 根据立库任务完成对storage进行修改
-     * @param StationTaskMaterialBox $stationTaskMaterial
-     */
-    public function putStationTaskMaterialBoxProcess(StationTaskMaterialBox $stationTaskMaterial)
-    {
-        $this->instant($this->stationTaskMaterialBoxService, 'StationTaskMaterialBoxService');
-
-        $storage = Storage::query()->where('material_box_id', $stationTaskMaterial['material_box_id'])->where('status',1)->first();
-        if($storage)$storage->update(['status' => 0, 'material_box_id' => null]);
-
-        $this->_stationCacheLightOff($stationTaskMaterial->station->code ?? null);  //海柔格口灭灯
-        $this->_stationCacheBroadCast($stationTaskMaterial->station->code ?? null, 0);    //通知缓存架任务完成
-    }
-
     /**
      * 取消任务
      * @param $stationCode
@@ -320,7 +213,7 @@ class   CacheShelfService
 
         if (!$station) return ['success' => false, 'message' => '传入参数异常,找不到对应的缓存架记录'];
 
-        $stationTaskMaterialBox = StationTaskMaterialBox::query()->where('material_box_id',$station['storage']['material_box_id'])->first();
+        $stationTaskMaterialBox = StationTaskMaterialBox::query()->where('material_box_id',$station['material_box_id'])->first();
         if($stationTaskMaterialBox ){
             if($stationTaskMaterialBox->status == '处理中')
                 return ['success' => false, 'message' => '当前缓存架任务正在处理中'];
@@ -329,7 +222,7 @@ class   CacheShelfService
             }
         }
 
-        $station->storage->update(['status' => 0,'material_box_id' => null]);
+        $station->update(['status' => 0,'material_box_id' => null]);
 
         return ['success' => true];
     }

+ 5 - 6
app/Services/CommodityMaterialBoxModelService.php

@@ -1,4 +1,4 @@
-<?php 
+<?php
 
 namespace App\Services;
 
@@ -14,14 +14,13 @@ class CommodityMaterialBoxModelService
     /**
      * 获取最大限值
      *
-     * @param integer|null $modelId
-     * @param integer|null $commodityId
+     * @param integer $modelId
+     * @param integer $commodityId
      *
      * @return int|null
      */
-    public function getMaximum($modelId, $commodityId):?int
+    public function getMaximum(int $modelId, int $commodityId):?int
     {
-        if (!$modelId || !$commodityId)return null;
         $model = CommodityMaterialBoxModel::query()->select("maximum")->where("commodity_id",$commodityId)
             ->where("material_box_model_id",$modelId)->first();
         return (int)$model->maximum ?? null;
@@ -48,4 +47,4 @@ class CommodityMaterialBoxModelService
         ]);else $model->update(["maximum" => $maximum]);
         return true;
     }
-}
+}

+ 77 - 36
app/Services/DbOpenService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Log;
 use App\OracleDOCOrderHeader;
 use App\OrderLogistic;
 use App\Traits\ServiceAppAop;
@@ -24,10 +25,10 @@ class DbOpenService
     {
         //获取系统无快递单号订单信息
         $order_info = Waybill::query()
-            ->with(['owner:id,name,phone_number', 'orderByCode', 'orderByCode.shop:id,name',
-                'orderByCode.warehouse:id,province_id,city_id,county_id,address',
-                'orderByCode.warehouse.province:id,name', 'orderByCode.warehouse.city:id,name',
-                'orderByCode.warehouse.county:id,name', 'deliveryType:id,name'])
+            ->with(['owner:id,name,phone_number', 'order', 'order.shop:id,name',
+                'order.warehouse:id,province_id,city_id,county_id,address',
+                'order.warehouse.province:id,name', 'order.warehouse.city:id,name',
+                'order.warehouse.county:id,name', 'deliveryType:id,name'])
             ->where('id', '=', $params['id'])
             ->first();
         //请求德邦API 生成新订单
@@ -38,40 +39,40 @@ class DbOpenService
             "Accept" => "application/json"
         ];
         if ($order_info) {
-            if (empty($order_info->orderByCode)) return false;
-            $res = $model->isExist($order_info->orderByCode->id);
+            if (empty($order_info->order) || empty($order_info->owner) || empty($order_info->order->shop)) return ['code' => 0, 'msg' => '订单关联信息错误,请核实'];
+            $res = $model->isExist($order_info->order->id);
             if (!$res || $res->status == 0 ?? 0) {
                 $data = [
-                    'logisticID' => config('api_logistic.DB.prod.sign') . date("YmdHis") . mt_rand(1000, 9999) . $order_info->orderByCode->id,
-                    'custOrderNo' => $order_info->orderByCode->client_code ?? '',
+                    'logisticID' => config('api_logistic.DB.prod.sign') . date("YmdHis") . mt_rand(1000, 9999) . $order_info->order->id,
+                    'custOrderNo' => $order_info->order->client_code ?? '',
                     // 'mailNo' => '',  // 不传会创建新的 运单号
                     'needTraceInfo' => config('api_logistic.DB.prod.needTraceInfo'),
                     'companyCode' => config('api_logistic.DB.prod.company_code'),
-                    'orderType' => config('api_logistic.DB.prod.orderType'),
-                    'transportType' => config('api_logistic.DB.prod.transportType'),
+                    'orderType' => $order_info->order_type,
+                    'transportType' => $order_info->transport_type,
                     'customerCode' => config('api_logistic.DB.prod.customer_Code'),
                     'sender' => [
-                        'companyName' => $order_info->orderByCode->shop->name ?? '',
+                        'companyName' => $order_info->order->shop->name ?? '',
                         'businessNetworkNo' => '',
                         'name' => $order_info->owner->name ?? '',
                         'mobile' => $order_info->owner->phone_number ?? '',
                         'phone' => $order_info->owner->phone_number ?? '',
-                        'province' => $order_info->orderByCode->warehouse->province->name ?? '',
-                        'city' => $order_info->orderByCode->warehouse->city->name ?? '',
-                        'country' => $order_info->orderByCode->warehouse->county->name ?? '',
+                        'province' => $order_info->order->warehouse->province->name ?? '',
+                        'city' => $order_info->order->warehouse->city->name ?? '',
+                        'country' => $order_info->order->warehouse->county->name ?? '',
                         'town' => '',
-                        'address' => $order_info->orderByCode->warehouse->address ?? '',
+                        'address' => $order_info->order->warehouse->address ?? '',
                     ],
                     'receiver' => [
                         'toNetworkNo' => '',
-                        'name' => $order_info->orderByCode->consignee_name ?? '',
-                        'phone' => $order_info->orderByCode->consignee_phone ?? '',
-                        'mobile' => $order_info->orderByCode->consignee_phone ?? '',
-                        'province' => $order_info->orderByCode->province ?? '',
-                        'city' => $order_info->orderByCode->city ?? "",
-                        'county' => $order_info->orderByCode->district ?? '',
+                        'name' => $order_info->order->consignee_name ?? '',
+                        'phone' => $order_info->order->consignee_phone ?? '',
+                        'mobile' => $order_info->order->consignee_phone ?? '',
+                        'province' => $order_info->order->province ?? '',
+                        'city' => $order_info->order->city ?? "",
+                        'county' => $order_info->order->district ?? '',
                         'town' => '',
-                        'address' => $order_info->orderByCode->address ?? '',
+                        'address' => $order_info->order->address ?? '',
                         'companyName' => ''
                     ],
                     'packageInfo' => [
@@ -79,25 +80,25 @@ class DbOpenService
                         'totalNumber' => $order_info->total_number ?? '',
                         'totalWeight' => $order_info->total_weight ?? '',
                         'totalVolume' => '',
-                        'packageService' => '',
+                        'packageService' => $order_info->package_service ?? '',
                         'deliveryType' => $order_info->deliveryType->name ?? '',
                     ],
                     'gmtCommit' => date('Y-m-d H:i:s'),
-                    'payType' => config('api_logistic.DB.prod.payType'),
+                    'payType' => $order_info->pay_type,
                     'addServices' => [
                         'insuranceValue' => '',
                         'codType' => '',
                         'reciveLoanAccount' => '',
                         'accountName' => '',
                         'codValue' => '',
-                        'backSignBill' => config('api_logistic.DB.prod.backSignBill')
+                        'backSignBill' => $order_info->back_sign_bill
                     ],
                     'smsNotify' => config('api_logistic.DB.prod.smsNotify'),
                     'sendStartTime' => date("Y-m-d H:i:s"),
                     'sendEndTime' => $order_info->deliver_at ?? date("Y-m-d H:i:s", strtotime('+1 day')),
                     'originalWaybillNumber' => $order_info->wms_bill_number ?? '',
                     'remark' => $order_info->dispatch_remark ?? '',
-                    'isOut' => '',
+                    'isOut' => 'N',
                     'passwordSigning' => config('api_logistic.DB.prod.passwordSigning'),
                     'isdispatched' => '',
                     'ispresaleorder' => '',
@@ -116,28 +117,68 @@ class DbOpenService
                 unset($data);
                 if (array_key_exists('result', $return)) {
                     //请求成功  快递单号 $return['mailNo']   请求编号 $return['uniquerRequestNumber']
+                    //返回日志记录
+                    $id = $params['id'];
+                    $order_no = $order_info->wms_bill_number;
+                    $mail_no = $return['mailNo']??'';
                     $add_data = [
-                        'order_id' => $order_info->orderByCode->id,
+                        'order_id' => $order_info->order->id,
                         'status' => $return['result'] == 'true' ? 1 : 0,
-                        'code' => $return['mailNo'] ?? '',
+                        'code' => $mail_no ?? '',
                         'uniquer_request_number' => $return['uniquerRequestNumber'],
                         'reason' => $return['reason'] ?? '',
                         'created_at' => date('Y-m-d H:i:s')
                     ];
                     $roe = OrderLogistic::query()->insertGetId($add_data);
-                    //成功
-                    if ($return['result'] == 'true' && $roe) {
-                        $order_no = $order_info->wms_bill_number;
-                        $mail_no = $return['mailNo'];
-                        $row = DB::connection('oracle')->transaction(function () use ($order_no, $mail_no) {
-                            OracleDOCOrderHeader::query()->where('orderno', $order_no)->update(['edittime' => Carbon::now(), 'soreference5' => $mail_no]);
+                    if ($roe && $return['result'] == 'true') {
+                        DB::connection('mysql')->transaction(function () use ($id, $order_no, $mail_no) {
+                            $update_data = [
+                                'type' => '德邦物流',
+                                'waybill_number' => $mail_no,
+                                'updated_at' => date('Y-m-d H:i:s')
+                            ];
+                            Waybill::query()->where('id', '=', $id)->update($update_data);
+                            DB::connection('oracle')->transaction(function () use ($order_no, $mail_no) {
+                                OracleDOCOrderHeader::query()->where('orderno', $order_no)->update(['edittime' => Carbon::now(), 'soreference5' => $mail_no]);
+                            });
                             LogService::log(__METHOD__, "申请快递单号回传WMS", ['orderno' => $order_no, 'soreference5' => $mail_no, 'edittime' => date('Y-m-d H:i:s')]);
                         });
-                        if ($row) return true;
+                        return ['code' => 1, 'msg' => '申请德邦物流单号成功'];
                     }
                 }
+                LogService::log(__METHOD__, "申请快递单号回传WMS", ['orderno' => $order_no, 'content'=> $return]);
+                return ['code' => 0, 'msg' => $return['reason']];
             }
+            elseif($res->status == 1 ?? 0 ) return ['code' => 1, 'msg'=> '德邦快递单号已存在'];
         }
-        return false;
+        return ['code' => 0, 'msg' => '订单信息错误,请核实'];
+    }
+
+    /**
+     * 根据 德邦运单号 获取 订单物流轨迹
+     * @param array $params
+     * @return array
+     */
+    public function getOrderStatus($params = [])
+    {
+        if ( ($params['mailNo']??'') == '') return ['code' => 0 , 'msg' => '德邦运单号不能为空'];
+        $uri = "http://dpsanbox.deppon.com/sandbox-web/standard-order/newTraceQuery.action";
+        $header = [
+            'Content-Type' => 'application/x-www-form-urlencoded;charset=utf-8',
+            "Accept" => "application/json"
+        ];
+        $data = [
+            'mailNo' => $params['mailNo']??''
+        ];
+        $param = json_encode($data, true);
+        $dd["params"] = $param;
+        $dd["timestamp"] = (integer)getMillisecond();
+        $dd["digest"] = base64_encode(md5($param . config('api_logistic.DB.prod.app_key') . $dd['timestamp']));
+        $dd["companyCode"] = config('api_logistic.DB.prod.company_code');
+        $return = httpPost($uri, $dd, $header);
+        if (array_key_exists('result', $return) && $return['result'] == 'true' && array_key_exists('resultCode', $return) && $return['resultCode'] == '1000'){
+           return ['code'=> 1, 'msg'=> '正在加载中。。。', 'data' => $return['responseParam']];
+        }
+        return ['code' => 0, 'msg' => '暂无物流信息'];
     }
 }

+ 20 - 0
app/Services/ErrorPushService.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Services;
+
+use App\ErrorTemp;
+use App\Interfaces\ErrorPush;
+
+class ErrorPushService implements ErrorPush
+{
+    public function push(string $path, string $title, string $content): bool
+    {
+        ErrorTemp::query()->create([
+            "position" => $path,
+            "title" => $title,
+            "content" => $content,
+            "created_at" => date("Y-m-d H:i:s")
+        ]);
+        return true;
+    }
+}

+ 2 - 16
app/Services/ForeignHaiRoboticsService.php

@@ -409,20 +409,6 @@ class ForeignHaiRoboticsService
         return true;
     }
 
-//    public function markHasPut($taskCode,$binCode):bool{
-//        try{
-//            //标记料箱进入位置
-////            $taskMaterialBoxesService->markDone();//
-//        }catch (\Exception $e){
-//            switch ($e->getCode()){
-//                case 'taskBinNotMatch';
-//                case 'taskGetFailed';
-//            }
-//        }
-//
-//    }
-
-
     public function excepted($taskCode='',$binCode='', $msg=''):bool{
         try{
             throw new ErrorException(
@@ -510,13 +496,13 @@ class ForeignHaiRoboticsService
      *
      * @throws
      */
-    public function paddingCacheShelf($stations)
+    public function paddingCacheShelf(Collection $stations):?bool
     {
         $collection = new Collection();
         $stationCollection = new Collection();
         $blacklist = [];
         foreach ($stations as $station){
-            $box = app("MaterialBoxService")->getAnEmptyBox($blacklist);
+            $box = app("MaterialBoxService")->getAnEmptyBoxSortedByOwner(null,$blacklist);
             if (!$box)break;
             $task = StationTask::query()->create([
                 'status' => "待处理",

+ 393 - 0
app/Services/HandInStorageService.php

@@ -0,0 +1,393 @@
+<?php
+
+namespace App\Services;
+
+use App\OracleBasCode;
+use App\OracleBasSKU;
+use App\OracleDOCASNDetail;
+use App\OracleDOCASNHeader;
+use App\OracleInvLotAtt;
+use App\Traits\ServiceAppAop;
+use App\ValueStore;
+use Carbon\Carbon;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\DB;
+
+class HandInStorageService
+{
+    use ServiceAppAop;
+
+    /**
+     * @param $asn
+     * @return Builder[]|Collection
+     * 获取富勒asn_header
+     *
+     */
+    public function selectAsn($asn)
+    {
+        if ($asn) return OracleDOCASNHeader::query()
+            ->with('asnStatus')
+            ->select(['asnno','asnreference1','asnstatus','addtime','customerid'])
+            ->where('asnno',$asn)
+            ->get();
+
+        return OracleDOCASNHeader::query()
+            ->select(['asnno','asnreference1','asnstatus','addtime','customerid'])
+            ->with('asnStatus')
+            ->where('asnstatus','00')
+            ->orderByDesc('addtime')
+            ->limit(50)
+            ->get();
+    }
+
+    /**
+     * @param $asnno
+     * @return Builder[]|Collection
+     * 获取富勒asn_detail (集合)
+     */
+    public function selectAsnDetails($asnno)
+    {
+        return OracleDOCASNDetail::query()
+            ->select(['sku','expectedqty','skudescrc','asnlineno','asnno','receivedqty'])
+            ->where('asnno',$asnno)
+            ->get();
+    }
+
+    /**
+     * @param $asnno
+     * @param $sku
+     * @return Builder|Model|object|null
+     *
+     */
+    public function getAsnDetail($asnno,$sku)
+    {
+        return OracleDOCASNDetail::query()
+            ->select(['sku','expectedqty','skudescrc','asnlineno','asnno','receivedqty'])
+            ->where('asnno',$asnno)
+            ->where('sku',$sku)
+            ->first();
+    }
+
+    /**
+     * @return mixed
+     * 获取质量状态
+     */
+    public function getQualityStatus()
+    {
+        return Cache::remember('BAS_CODE_QLT_STS', 600, function () {
+            return OracleBasCode::query()->select(['codeid','code','codename_c'])
+                ->where('codeid','QLT_STS')
+                ->get();
+        });
+    }
+
+    /**
+     * @return mixed
+     * 获取属性仓
+     */
+    public function getAttributeLocation()
+    {
+        return Cache::remember('BAS_CODE_CUS_UDFPC', 600, function () {
+            return OracleBasCode::query()->select(['codeid','code','codename_c'])
+                ->where('codeid','CUS_UDFPC')
+                ->get();
+        });
+    }
+
+    /**
+     * @param $customerid
+     * @param $sku
+     * @return mixed
+     * 根据customerid和sku 查询商品关联的批次属性规则
+     */
+    public function getBasSkuLotId($customerid,$sku)
+    {
+        return Cache::remember('bas_sku_lot_'.$customerid.'_'.$sku, 600, function ()use($customerid,$sku) {
+            return OracleBasSKU::query()->select(['customerid','sku','lotid'])
+                ->where('customerid',$customerid)
+                ->where('sku',$sku)
+                ->with('lotId')
+                ->first();
+        });
+    }
+
+    /**
+     * @throws \Throwable
+     */
+    public function fluxHandIn(array $info)
+    {
+        $lotatt=array_filter($info,function ($key){
+            return strpos($key,'lotatt')===0;
+        },ARRAY_FILTER_USE_KEY);
+        $invlotatt=[];
+        for ($i=1;$i<=8;$i++){$invlotatt["lotatt0{$i}"]=null;}
+        foreach ($invlotatt as $key=>&$item){
+            foreach ($lotatt as $key1=>$item1){
+                if ($key===$key1) $item=$item1;
+            }
+        }
+        $who= 'WAS'.(Auth::user() ? '-'.Auth::user()["name"] : '');
+        $time=Carbon::now()->toDateTimeString();
+//        return DB::connection("oracle")->transaction(function ()use ($info,$invlotatt,$who,$time){
+            //flux 批次号
+//            $lotNum=$this->getOrCreateLotNum($info,$invlotatt,$who,$time);
+//            if (!$lotNum) return false;
+            //flux 创建入库事务
+//            $actTransactionLog=$this->setFluxActTransactionLog($info,$lotNum,$who,$time);
+//            if (!$actTransactionLog)return false;
+            //flux 创建上架任务
+//            $this->setFluxTskTaskListPA($info,$invlotatt, $actTransactionLog, $who, $time);
+            //flux 完善库存余量
+//            $this->updateFluxInv($info,$lotNum,$who,$time,$actTransactionLog);
+            //flux 更新asn_detail 和 asn_header 状态
+            $re=$this->updateFluxAsn($info,$invlotatt,$time,$who);
+            dd($re);
+//            return true;
+//        });
+
+    }
+
+    /**
+     * @throws \Throwable
+     */
+    public function updateFluxAsn(array $info, array $invlotatt, $time, $who): bool
+    {
+        $db=DB::connection("oracle");
+        $asn=OracleDOCASNHeader::query()
+            ->withCount('asnDetails')
+            ->with('asnDetails')
+            ->where('asnno',$info['asnno'])
+            ->first();
+        if (!$asn||!$asn->asnDetails||!$asn->asn_details_count) return false;
+        $asnDetails=$asn->asnDetails;
+        $receiveAsn=null;
+        foreach ($asnDetails as $asnDetail){
+            if ($asnDetail['asnno']==$info['asnno'] &&
+                $asnDetail['asnlineno']==$info['asnlineno'] &&
+                $asnDetail['customerid']==$info['customerid'] &&
+                $asnDetail['sku']==$info['sku']) $receiveAsn=$asnDetail;
+        }
+        return $db->transaction(function ()use($db,$info,$receiveAsn,$invlotatt,$time,$who){
+            if ($receiveAsn && (int)$receiveAsn['receivedqty']+(int)$info['amount']<(int)$receiveAsn['expectedqty']){
+                //asn_detail 收货数量+已收数量<预期数量
+                $db->update(DB::raw("UPDATE DOC_ASN_DETAILS SET linestatus = '30',edittime = TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),editwho = ?,
+             lotatt01=?,lotatt02=?,lotatt03=?,lotatt04=?,lotatt05=?,lotatt06=?,lotatt07=?,lotatt08=? WHERE asnno = ?"),
+                    [$time,$who,$invlotatt['lotatt01'],$invlotatt['lotatt02'],$invlotatt['lotatt03'],$invlotatt['lotatt04'],
+                        $invlotatt['lotatt05'],$invlotatt['lotatt06'],$invlotatt['lotatt07'],$invlotatt['lotatt08'],$info['asnno']]);
+                //asn_header 部分收货状态
+                $db->update(DB::raw("UPDATE DOC_ASN_HEADER SET asnstatus = '30',edittime = TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),editwho = ? WHERE asnno = ?"),
+                    [$time,$who,$info['asnno']]);
+            }elseif ($receiveAsn && (int)$receiveAsn['receivedqty']+(int)$info['amount']==(int)$receiveAsn['expectedqty']){
+                //asn_detail 收货数量+已收数量=预期数量
+                $db->update(DB::raw("UPDATE DOC_ASN_DETAILS SET linestatus = '40',edittime = TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),editwho = ?,
+             lotatt01=?,lotatt02=?,lotatt03=?,lotatt04=?,lotatt05=?,lotatt06=?,lotatt07=?,lotatt08=? WHERE asnno = ?"),
+                    [$time,$who,$invlotatt['lotatt01'],$invlotatt['lotatt02'],$invlotatt['lotatt03'],$invlotatt['lotatt04'],
+                        $invlotatt['lotatt05'],$invlotatt['lotatt06'],$invlotatt['lotatt07'],$invlotatt['lotatt08'],$info['asnno']]);
+                //当asn_detail 所有状态都为完全收货是  asn_header 状态修改为 完全收货(asnstatus=40)
+                if (OracleDOCASNDetail::query()->where('asnno',$info['asnno'])->where('linestatus',40)->count()==$asn->asn_details_count){
+                    $db->update(DB::raw("UPDATE DOC_ASN_HEADER SET asnstatus = '40',edittime = TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),editwho = ? WHERE asnno = ?"),
+                        [$time,$who,$info['asnno']]);
+                }
+            }
+            return true;
+        });
+    }
+    /**
+     * @throws \Throwable
+     */
+    public function updateFluxInv(array $info, $lotNum, $who, $time, array $actTransactionLog)
+    {
+        $db = DB::connection("oracle");
+        $db->transaction(function ()use ($db,$info,$lotNum,$actTransactionLog,$who,$time){
+            //更新 inv_lot 批次 库存表
+            $invLot=$db->selectOne(DB::raw("SELECT * FROM INV_LOT WHERE lotnum = ? AND customerid = ? AND sku = ? "),[
+                $lotNum,$info['customerid'],$info['sku']
+            ]);
+            if ($invLot)$db->update(DB::raw("UPDATE INV_LOT SET qty = qty+?,edittime=?,editwho=? WHERE lotnum = ? AND customerid = ? AND sku = ?"),[
+                (int)$info['amount'],$time,$who,$lotNum,$info['customerid'],$info['sku'],
+            ]);
+            else $db->insert(DB::raw("INSERT INTO INV_LOT VALUES(?,?,?,?,0,0,0,0,0,0,0,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?)"),[
+                $lotNum,$info['customerid'],$info['sku'],$info['amount'],$time,$who, $time,$who
+            ]);
+            //更新 inv_lot_loc_id 批次/库位/跟踪号 库存表
+            $invLotId = $db->selectOne(DB::raw("SELECT * FROM inv_lot_loc_id WHERE lotnum = ? AND locationid = ? AND customerid = ? AND sku = ? AND traceid = ? FOR UPDATE"),[
+                $lotNum,$actTransactionLog['location'],$actTransactionLog['customerid'],$actTransactionLog['sku'],$actTransactionLog['trackid']
+            ]);
+
+            if ($info['location']){ //存在目标库位
+                $invLotIdHasPreLocation = $db->selectOne(DB::raw("SELECT * FROM inv_lot_loc_id WHERE lotnum = ? AND locationid = ? AND customerid = ? AND sku = ? AND traceid = ? FOR UPDATE"),[
+                    $lotNum,$info['location'],$actTransactionLog['customerid'],$actTransactionLog['sku'],$actTransactionLog['trackid']
+                ]);
+
+                if ($invLotIdHasPreLocation)$db->update(DB::raw("UPDATE inv_lot_loc_id SET qtypa = qtypa+?,edittime=?,editwho=? WHERE lotnum = ? AND locationid = ? AND traceid = ?"),[
+                    (int)$info['amount'],$time,$who,$lotNum,$info['location'],$actTransactionLog['trackid']
+                ]);
+                else $db->insert(DB::raw("INSERT INTO inv_lot_loc_id VALUES(?,?,?,?,?,?,0,0,0,0,0,0,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,0,0,0,0,0,'*',?,null)"),[
+                    $lotNum,$info['location'],$actTransactionLog['trackid'],$actTransactionLog['customerid'],$actTransactionLog['sku'],0,$time,$who,$time,$who,(int)$info['amount']
+                ]);
+
+                if ($invLotId)$db->update(DB::raw("UPDATE inv_lot_loc_id SET qty = qty+?,qtymvout = qtymvout+?,edittime=?,editwho=? WHERE lotnum = ? AND locationid = ? AND traceid = ?"),[
+                    (int)$info['amount'],(int)$info['amount'],$time,$who,$lotNum,$actTransactionLog['location'],$actTransactionLog['trackid']
+                ]);
+                else $db->insert(DB::raw("INSERT INTO inv_lot_loc_id VALUES(?,?,?,?,?,?,0,0,0,0,?,0,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,0,0,0,0,0,'*',0,null)"),[
+                    $lotNum,$actTransactionLog['location'],$actTransactionLog['trackid'],$actTransactionLog['customerid'],$actTransactionLog['sku'],(int)$info['amount'],(int)$info['amount'],
+                    $time,$who,$time,$who,
+                ]);
+
+            }else{
+                if ($invLotId)$db->update(DB::raw("UPDATE inv_lot_loc_id SET qty = qty+?,edittime=?,editwho=? WHERE lotnum = ? AND locationid = ? AND traceid = ?"),[
+                    (int)$info['amount'],$time,$who,$lotNum,$actTransactionLog['location'],$actTransactionLog['trackid']
+                ]);
+                else $db->insert(DB::raw("INSERT INTO inv_lot_loc_id VALUES(?,?,?,?,?,?,0,0,0,0,0,0,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,0,0,0,0,0,'*',0,null)"),[
+                    $lotNum,$actTransactionLog['location'],$actTransactionLog['trackid'],$actTransactionLog['customerid'],$actTransactionLog['sku'],(int)$info['amount'],$time,$who,$time,$who,
+                ]);
+            }
+        });
+    }
+
+    /**
+     * @throws \Throwable
+     */
+    public function setFluxTskTaskListPA(array $info, array $invlotatt, $actTransactionLog, $who, $time)
+    {
+        $db = DB::connection("oracle");
+        $db->transaction(function ()use ($db,$info,$invlotatt,$actTransactionLog,$who,$time){
+            $sql = <<<sql
+INSERT INTO TSK_TASKLISTS VALUES(?,'1','PA',?,?,'ASN',?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,null,null,?,?,?,?,?,?,?,?,null,null,null,null,
+    0,0,0,0,null,?,null,null,null,?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),null,null,?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),'N',null,null,
+    ?,?,?,'N',null,?,'*',null,null,null,'N',null,null)
+sql;
+            $db->insert(DB::raw($sql),[
+                $actTransactionLog['tsid'],$actTransactionLog['customerid'],$actTransactionLog['sku'],$actTransactionLog['docno'],$actTransactionLog['doclineno'],
+                $actTransactionLog['lotNum'],$actTransactionLog['packid'],'EA',$info['amount'],$info['amount'],$actTransactionLog['location'],$actTransactionLog['location'],
+                $actTransactionLog['trackid'],$actTransactionLog['lotNum'],$actTransactionLog['packid'],'EA',$info['amount'],$info['amount'],
+                $info['location'],$info['location'],$actTransactionLog['trackid'],'00','Putaway Task','3',$invlotatt['lotatt01'],$invlotatt['lotatt02'],$invlotatt['lotatt03'],$invlotatt['lotatt04'],
+                $invlotatt['lotatt05'],$invlotatt['lotatt06'],$invlotatt['lotatt07'],$invlotatt['lotatt08'],$actTransactionLog['trid'],$who,$time,null,null,null,null,
+                $actTransactionLog['userdefine1'],$actTransactionLog['userdefine2'],$actTransactionLog['userdefine3'],$actTransactionLog['warehouseid']
+            ]);
+        });
+    }
+
+    /**
+     * @param array $info
+     * @param $lotNum
+     * @param $who
+     * @param $time
+     * @return mixed
+     * @throws \Throwable
+     * 创建入库事务
+     */
+    public function setFluxActTransactionLog(array $info,$lotNum,$who,$time)
+    {
+        $db = DB::connection("oracle");
+        return $db->transaction(function ()use ($db,$info,$lotNum,$time,$who){
+            if ($info['trackNumber'])$trackNumber=$info['trackNumber'];
+            else $trackNumber=substr(md5($time),0,30);
+            $asnHeader=OracleDOCASNHeader::query()->where('asnno',$info['asnno'])->first();
+            $asnDetail=OracleDOCASNDetail::query()->where('asnno',$info['asnno'])->where('sku',$info['sku'])->first();
+            $sql = <<<sql
+INSERT INTO ACT_TRANSACTION_LOG VALUES(?,'IN',?,?,?,?,'ASN',?,?,?,?,?,?,?,?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,
+TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,0,0,0,0,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,?,null,null,null,?,?,?,?,?,?,?,?,
+?,?,?,?,'1','Y',null,?,?,?,?,null,null,?,null,null)
+sql;
+            list($trid,$max) = app('StorageService')->getTrNumber();
+            list($tsid,$max) = $this->getTsNum();
+            $db->insert(DB::raw($sql),[
+                $trid,$asnDetail->customerid,$asnDetail->sku,
+                $asnDetail->asnno,$asnDetail->asnlineno,$lotNum,$asnDetail->receivinglocation,'*',$asnDetail->packid,'EA',$info['amount'],$info['amount'],'99',$time,$who,
+                $time,$who,$time,$asnDetail->customerid,$asnDetail->sku,$trackNumber,$asnDetail->receivinglocation,$who,$asnDetail->packid,'EA',$info['amount'],$info['amount'],$lotNum,
+                '*','0','N',$tsid,substr($asnDetail->receivinglocation,-4),$asnHeader->userdefine1,$asnHeader->userdefine2,
+                $asnHeader->userdefine3,'O'
+            ]);
+            app('StorageService')->setTrNumber();
+            $this->setTsNum();
+            $actTransactionLog=[
+                'trid'=>$trid,'docno'=>$asnDetail->asnno,'customerid'=>$asnDetail->customerid,'sku'=>$asnDetail->sku,'doclineno'=>$asnDetail->asnlineno,'lotNum'=>$lotNum,'location'=>$asnDetail->receivinglocation,
+                'packid'=>$asnDetail->packid,'tsid'=>$tsid,'warehouseid'=>substr($asnDetail->receivinglocation,-4),'userdefine1'=>$asnHeader->userdefine1,'userdefine2'=>$asnHeader->userdefine2,
+                'userdefine3'=>$asnHeader->userdefine3,'trackid'=>$trackNumber
+            ];
+            return $actTransactionLog;
+        });
+    }
+    /**
+     * @param array $info
+     * @return mixed
+     * @throws \Throwable
+     * 或去flux 批次号
+     */
+    public function getOrCreateLotNum(array $info,array $invlotatt,$who,$time)
+    {
+        $invlotatt['customerid']=$info['customerid'];
+        $invlotatt['sku']=$info['sku'];
+        //根据批次规则查询或新建批次
+        $lotnum=OracleInvLotAtt::query()->where($invlotatt)->value('lotnum');
+        if ($lotnum) return $lotnum;
+
+        $db = DB::connection("oracle");
+        list($num,$max)=$this->getLtNum();
+        return $db->transaction(function ()use($db,$info,$invlotatt,$num,$who,$time){
+           $sql = <<<sql
+INSERT INTO INV_LOT_ATT VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,
+TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?,TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),?)
+sql;
+           $db->insert(DB::raw($sql),[
+               $num,$info['customerid'],$info['sku'],$invlotatt['lotatt01'],$invlotatt['lotatt02'],$invlotatt['lotatt03'],$invlotatt['lotatt04'],
+               $invlotatt['lotatt05'],$invlotatt['lotatt06'],$invlotatt['lotatt07'],$invlotatt['lotatt08'],null,null,null,null,$time,$who,$time,$who,$time,null
+           ]);
+           $this->setLtNum();
+           return $num;
+       });
+
+    }
+
+    /**
+     * 获取批次号
+     * @return array
+     */
+    private function getLtNum()
+    {
+        $val = ValueStore::query()->select("value")->where("name","flux_lt_number")->lockForUpdate()->first();
+        if (!$val)$val = ValueStore::query()->create(["name"=>"flux_lt_number","value"=>'0']);
+        $max = $val->value+1;
+        $number = sprintf("%07d", $max);
+        return array ('WLT'.$number,$max);
+    }
+
+    /**
+     * 设置批次号
+     */
+    private function setLtNum()
+    {
+        ValueStore::query()
+            ->select("value")
+            ->where("name","flux_lt_number")
+            ->update(["value"=>DB::raw("value+1")]);
+    }
+    /**
+     * 获取批次号
+     * @return array
+     */
+    private function getTsNum()
+    {
+        $val = ValueStore::query()->select("value")->where("name","flux_ts_number")->lockForUpdate()->first();
+        if (!$val)$val = ValueStore::query()->create(["name"=>"flux_ts_number","value"=>'0']);
+        $max = $val->value+1;
+        $number = sprintf("%07d", $max);
+        return array ('WTS'.$number,$max);
+    }
+
+    /**
+     * 设置批次号
+     */
+    private function setTsNum()
+    {
+        ValueStore::query()
+            ->select("value")
+            ->where("name","flux_ts_number")
+            ->update(["value"=>DB::raw("value+1")]);
+    }
+}

+ 1 - 5
app/Services/InventoryAccountService.php

@@ -4,14 +4,11 @@
 namespace App\Services;
 
 use App\Commodity;
-use App\Http\Controllers\CommodityController;
 use App\Http\Controllers\Controller;
 use App\InventoryAccount;
 use App\InventoryAccountMission;
-use App\OraccleBasCustomer;
 use App\OracleBasSKU;
 use App\OracleInvLotAtt;
-use App\OracleBasCustomer;
 use App\OracleInvLotLocId;
 use App\Owner;
 use App\Services\common\BatchUpdateService;
@@ -19,7 +16,6 @@ use App\Services\common\QueryService;
 use Carbon\Carbon;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\DB;
-use function GuzzleHttp\Psr7\_parse_message;
 use App\Traits\ServiceAppAop;
 
 
@@ -47,7 +43,7 @@ class InventoryAccountService
         $ownerIds=app('OwnerService')->getSelection();
         $inventories=InventoryAccount::query()->with(['owner','creator'])->orderBy('id','desc')->whereIn('owner_id',$ownerIds);
         $columnQueryRules=[
-            'owner_id' => ['multi' => ','],
+            'owner' => ['alias'=>'owner_id','multi' => ','],
             'type' => ['multi' => ','],
             'date_start' => ['alias' => 'created_at' , 'startDate' => ' 00:00:00'],
             'date_end' => ['alias' => 'created_at' , 'endDate' => ' 23:59:59'],

+ 5 - 1
app/Services/LogisticSFService.php

@@ -54,7 +54,11 @@ class LogisticSFService
      */
     public function getResultFromSF(string $head, string $numbers, string $checkWord, string $url): array
     {
-        $responseBody = get_object_vars(simplexml_load_string($this->sendHttpToSF($head, $numbers, $checkWord, $url))->Body)['RouteResponse'];
+        try {
+            $responseBody = get_object_vars(simplexml_load_string($this->sendHttpToSF($head, $numbers, $checkWord, $url))->Body)['RouteResponse'];
+        } catch (Exception $e) {//index RouteResponse 异常处理
+            return [];
+        }
         $result = [];
         if (is_array($responseBody)) {//SF返回多个单号的查询结果
             $result = $this->transformSFMoreToArr($responseBody, $result);

+ 39 - 0
app/Services/MaterialBoxModelService.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Services;
+
+use App\Owner;
+use App\Traits\ServiceAppAop;
+use App\MaterialBoxModel;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Support\Facades\DB;
+
+class MaterialBoxModelService
+{
+    use ServiceAppAop;
+    protected $modelClass=MaterialBoxModel::class;
+
+    /**
+     * 获取货主的模型序列
+     *
+     * @param int|null $owner
+     *
+     * @return Collection
+     */
+    public function getModelSortedByOwner(?int $owner):Collection
+    {
+        $sequence = [];
+        $sql = "(CASE id ";
+        if (!$owner){
+            $owner = Owner::query()->find($owner);
+            if ($owner){
+                $sequence = explode(",",$owner->model_sequence);
+                foreach ($sequence as $index=>$s)$sql .= " WHEN {$s} THEN {$index}";
+                $sql .= " END)";
+            }
+        }
+        $query = MaterialBoxModel::query();
+        if ($sequence)$query->whereIn("id",$sequence)->orderBy(DB::raw($sql));
+        return $query->get();
+    }
+}

+ 20 - 25
app/Services/MaterialBoxService.php

@@ -5,12 +5,8 @@ namespace App\Services;
 
 
 use App\MaterialBox;
-use App\Station;
+use App\MaterialBoxModel;
 use App\StationTaskMaterialBox;
-use App\Storage;
-use Illuminate\Database\Eloquent\Builder;
-use Illuminate\Support\Collection;
-use Illuminate\Support\Facades\Cache;
 use App\Traits\ServiceAppAop;
 use Illuminate\Support\Facades\DB;
 
@@ -24,12 +20,12 @@ class MaterialBoxService
     /**
      * 获取一个空料箱
      *
+     * @param MaterialBoxModel|\stdClass $model
      * @param array $blacklist
-     * @param integer|null $modelId
      *
      * @return MaterialBox|null
      */
-    public function getAnEmptyBox(array $blacklist = [], $modelId = null)
+    public function getAnEmptyBox(MaterialBoxModel $model,array $blacklist = []):?MaterialBox
     {
         $id = 0;
         while (true){
@@ -39,8 +35,8 @@ class MaterialBoxService
                 ->where("id",">",$id)->where("code","like","IDE%")
                 ->where("status",4)->limit(50)->orderBy("id")
                 ->whereNotIn("id",StationTaskMaterialBox::query()->select("material_box_id")
-                    ->where("status","!=","完成")->groupBy("material_box_id"));
-            if ($modelId)$boxes->where("material_box_model_id",$modelId);
+                    ->whereNotIn("status",["完成","取消"])
+                    ->where("material_box_model_id",$model->id)->groupBy("material_box_id"));
             $boxes = $boxes->get();
             if ($boxes->count()==0)break;
             $id = $boxes[count($boxes)-1]->id;
@@ -56,7 +52,7 @@ class MaterialBoxService
                 ->whereNotIn("status",[0,4])->get();
             $haiBoxes->each(function ($haiBox)use(&$notCodes){$notCodes[$haiBox->bin_code] = true;});
 
-            //检测FLUX
+            //剔除FLUX已有库存并且库位内种类超出的料箱
             $ides = [];
             $str = "(";
             foreach ($boxes as $box){
@@ -67,30 +63,31 @@ class MaterialBoxService
             if (!$ides)continue;
             $str = rtrim($str,",").")";
             $sql = <<<sql
-SELECT LOCATIONID,SUM(QTY+QTYPA) qty FROM INV_LOT_LOC_ID WHERE LOCATIONID IN {$str} GROUP BY LOCATIONID
+SELECT LOCATIONID FROM (SELECT LOCATIONID FROM (SELECT LOCATIONID,SUM(QTY+QTYPA) qty FROM INV_LOT_LOC_ID WHERE LOCATIONID IN {$str} GROUP BY LOCATIONID,LOTNUM,CUSTOMERID,SKU) where qty>0) GROUP BY
+                            LOCATIONID HAVING (COUNT(*)>={$model->maximum_kind})
 sql;
-            foreach (DB::connection("oracle")->select(DB::raw($sql)) as $item){
-                if ((int)$item->qty==0)return $ides[$item->locationid];
-                unset($ides[$item->locationid]);
-            }
+            foreach (DB::connection("oracle")->select(DB::raw($sql)) as $item)unset($ides[$item->locationid]);
             if ($ides)return current($ides);
         }
         return null;
     }
 
     /**
-     * 获取料箱所在库区
+     * 获取所有者排序的空盒子
      *
-     * @param string $ide
+     * @param integer|null $ownerId
+     * @param array $blacklist
      *
-     * @return string|null
+     * @return MaterialBox|null
      */
-    public function getBoxLocation(string $ide):?string
+    public function getAnEmptyBoxSortedByOwner(?int $ownerId=null, array $blacklist=[]):?MaterialBox
     {
-        $storage = Storage::query()->with("station")->whereHas("materialBox",function (Builder $box)use($ide){
-            $box->where("code",$ide);
-        })->whereNotNull("station_id")->first();
-        return $storage->station->code ?? null;
+        $models = app("MaterialBoxModelService")->getModelSortedByOwner($ownerId);
+        foreach ($models as $model){
+            $box = $this->getAnEmptyBox($model,$blacklist);
+            if ($box)return $box;
+        }
+        return null;
     }
 
     /**
@@ -103,8 +100,6 @@ sql;
     public function checkUsableBox(int $boxId):bool
     {
         /** @var MaterialBox|\stdClass $box */
-        //$box = MaterialBox::query()->find($boxId);
-        //if (!$this->getBoxLocation($box->code))return false;
         if (StationTaskMaterialBox::query()->select(DB::raw(1))->whereNotIn("status",['完成','取消'])->where("material_box_id",$boxId)->first())return false;
         return true;
     }

+ 1 - 0
app/Services/OrderCommodityService.php

@@ -31,6 +31,7 @@ class OrderCommodityService
         }
     }
 
+    //暂时无意义,直到下个版本前仍未被引用则删除
     public function correctLocation_fromWMS($orderCommodities){
         $orderCommodities->loadMissing('order.batch');
         $details=OracleActAllocationDetails::query()

+ 2 - 1
app/Services/OrderPackageReceivedSyncService.php

@@ -104,7 +104,8 @@ class OrderPackageReceivedSyncService
                 if ($orderPackage && $orderPackage->logistic_number)LogisticAliJiSuSync::dispatch($orderPackage->logistic_number);
             }
         });
-        $this->syncLogisticRouteJD();
+        //TODO 暂时不同步京东
+//        $this->syncLogisticRouteJD();
     }
     public function syncLogisticRouteJD(){
         ini_set('max_execution_time', 60);

+ 21 - 16
app/Services/OwnerPriceOperationService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Components\ErrorPush;
 use App\Feature;
 use App\Jobs\HandlePastBill;
 use App\Owner;
@@ -20,6 +21,7 @@ use App\Traits\ServiceAppAop;
 class OwnerPriceOperationService
 {
     use ServiceAppAop;
+    use ErrorPush;
     protected $modelClass=OwnerPriceOperation::class;
     /**
      * @param Builder $builder
@@ -271,7 +273,7 @@ class OwnerPriceOperationService
             DB::commit();
         }catch (\Exception $exception){
             DB::rollBack();
-            LogService::log(__CLASS__,"即时账单满减处理失败",$exception->getMessage());
+            $this->push(__METHOD__."->".__LINE__,"即时账单满减处理失败",$exception->getMessage()."  参数".json_encode(array($rule, $owner, $result)));
         }
         //进入历史单处理
         if ($pivot && $sign)dispatch(new HandlePastBill(array($rule,$owner,$discountIndex,$pivot)));
@@ -426,7 +428,7 @@ class OwnerPriceOperationService
      *
      * @return double
      */
-    private function matchItem($obj, $columnMapping, $matchObject, $units, $ownerId, $result)
+    public function matchItem($obj, $columnMapping, $matchObject, $units, $ownerId, $result)
     {
         $matchObject = $this->resetChildNodeMapping($matchObject->toArray(),$columnMapping);
         if (!$matchObject)return -1;
@@ -535,30 +537,33 @@ class OwnerPriceOperationService
      */
     public function handlePastBill($rule, $owner, $discountIndex, $pivot)
     {
+        DB::beginTransaction();
         try{
-            DB::beginTransaction();
             $month = date("Y-m");
             $day = date("t",strtotime($month));
-            $units = app("UnitService")->getUnitMapping(["件","箱"]); //获取单位映射集
-            foreach (OwnerFeeDetail::query()->with(["order.logistic","order.shop","order.packages.commodities.commodity","order.batch"])
-                         ->where("owner_id",$owner)
-                         ->whereBetween("worked_at",[$month."-01",$month."-".$day])->get() as $detail){
-                $order = $detail->order;
-
-                $logistic_fee = 0;
-                if ($logistic_fee!==null && $logistic_fee<0)$logistic_fee = null;
-
-                $money = $this->matchItem($rule,Feature::MAPPING["order"],$order,$units,$owner,[$discountIndex=>true]);
-                if ($money>0)$detail->update(["work_fee"=>$money]);
-                else LogService::log(__CLASS__,"处理历史即时账单时发生匹配错误","账单主键:".$detail->id."; 错误代码".$money);
+            $query = OwnerFeeDetail::query()->where("owner_id",$owner)->whereBetween("worked_at",[$month."-01",$month."-".$day]);
+            $units = app("UnitService")->getUnitMapping(["件","单","箱","m³","T","kg"]); //获取单位映射集
+            $exe = function ($mapping,$object,$detail)use($rule,$units,$owner,$discountIndex){
+                $money = $this->matchItem($rule,$mapping,$object,$units,$owner,[$discountIndex=>true]);
+                if ($money>0)$detail->update(["work_fee"=>$money,"work_tax_fee"=>$money*($rule->taxRate->value/100)]);
+                else $this->push(__METHOD__."->".__LINE__,"处理历史即时账单时发生匹配错误","账单主键:".$detail->id."; 错误代码".$money.";参数列表:".json_encode(array($rule, $owner, $discountIndex)));
             };
+            if ($rule->operation_type=='入库'){
+                foreach ($query->with(["store.storeItems.commodity","store.warehouse"])
+                             ->where("outer_table_name",'stores')->get() as $detail)
+                    $exe(Feature::MAPPING["store"],$detail->store,$detail);
+            }else{
+                foreach ($query->with(["order.logistic","order.shop","order.packages.commodities.commodity","order.batch"])
+                             ->where("outer_table_name",'orders')->get() as $detail)
+                    $exe(Feature::MAPPING["order"],$detail->order,$detail);
+            }
             DB::commit();
         }catch (\Exception $e){
             DB::rollBack();
             //处理失败回退标记
             DB::update(DB::raw("UPDATE owner_price_operation_owner SET discount_date = ?,target_value = ? WHERE  owner_price_operation_id = ? AND owner_id = ?"),
                 [$pivot->discount_date,$pivot->target_value,$rule->id,$owner]);
-            LogService::log(__CLASS__,"处理历史即时账单时发生系统错误","计费模型主键:".$rule->id."; 错误信息".$e->getMessage());
+            $this->push(__METHOD__."->".__LINE__,"处理历史即时账单时发生系统错误","计费模型主键:".$rule->id."; 错误信息".$e->getMessage().";参数列表:".json_encode(array($rule, $owner, $discountIndex,$pivot)));
         }
     }
 }

+ 13 - 0
app/Services/RequirementService.php

@@ -0,0 +1,13 @@
+<?php 
+
+namespace App\Services;
+
+use App\Traits\ServiceAppAop;
+use App\Requirement;
+
+class RequirementService
+{
+    use ServiceAppAop;
+    protected $modelClass=Requirement::class;
+
+}

+ 13 - 0
app/Services/RequirementUserService.php

@@ -0,0 +1,13 @@
+<?php 
+
+namespace App\Services;
+
+use App\Traits\ServiceAppAop;
+use App\RequirementUser;
+
+class RequirementUserService
+{
+    use ServiceAppAop;
+    protected $modelClass=RequirementUser::class;
+
+}

+ 70 - 2
app/Services/StationService.php

@@ -7,6 +7,7 @@ namespace App\Services;
 use App\Events\BroadcastToStation;
 use App\Station;
 use App\StationTask;
+use App\StationTaskMaterialBox;
 use App\StationType;
 use Exception;
 use Illuminate\Database\Eloquent\Model;
@@ -98,7 +99,7 @@ class StationService
      *
      * @return Model|null
      */
-    public function getMirrorMappingLocation($mirrorLocation)
+    public function getMirrorMappingLocation(string $mirrorLocation):?Station
     {
         if (!$mirrorLocation)return null;
         return Station::query()->where("code",substr($mirrorLocation,2))->first();
@@ -113,7 +114,74 @@ class StationService
     public function isHalfBoxLocation(?Station $station):bool
     {
         if (!$station)return false;
-        return $station->parent_id==7;
+        return $station->station_type_id==5 && $station->parent_id;
     }
 
+    /**
+     * 是否为缓存架位置
+     *
+     * @param Station|\stdClass $station
+     *
+     * @return bool
+     */
+    public function isCacheShelfLocation(Station $station):bool
+    {
+        return $station->station_type_id == 5;
+    }
+
+    /**
+     * 获取缓存架
+     *
+     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
+     */
+    public function getCacheShelf()
+    {
+        return Station::query()->where("station_type_id",5)
+            ->whereNotNull("parent_id")->get();
+    }
+
+    /**
+     * 库位占用
+     * 为未执行的上架任务预定库位,禁止二次下发
+     *
+     * @param string $location
+     * @param int|null $boxId
+     *
+     * @return int
+     */
+    public function locationOccupy(string $location, ?int $boxId=null):int
+    {
+        $update = ["status"=>1];
+        if ($boxId)$update["material_box_id"]=$boxId;
+        return Station::query()->where("code",$location)->update($update);
+    }
+
+    /**
+     * 库位释放
+     *
+     * @param string $location
+     * @param int|null $boxId
+     *
+     * @return int
+     */
+    public function locationFreed(string $location, ?int $boxId=null):int
+    {
+        $update = ["status"=>0];
+        if ($boxId)$update["material_box_id"]=$boxId;
+        return Station::query()->where("code",$location)->update($update);
+    }
+
+    /**
+     * 检查库位是否可用
+     *
+     * @param mixed $station
+     *
+     * @return bool
+     */
+    public function isAvailable($station):bool
+    {
+        if (!is_a($station,Model::class)) $station = Station::query()->where("code",$station)->first();
+        $s = StationTaskMaterialBox::query()->selectRaw("1")->where("station_id",$station->id)->whereNotIn("status",["完成","取消"])->first();
+        return $station && $station->status==0 && !$s;
+    }
 }

+ 21 - 43
app/Services/StationTaskBatchService.php

@@ -136,79 +136,55 @@ class StationTaskBatchService
     {
         LogService::log(__METHOD__,'runMany','波次任务分配6.1:'.json_encode($stationTaskBatches));
         $stationTaskBatches_failed = null;
-        ($execute =
-            function (
-                Collection $stationTaskBatches, &$stationTaskBatches_failed) {
-                LogService::log(__METHOD__,'runMany','波次任务分配6.2:'.json_encode($stationTaskBatches));
-                if ($stationTaskBatches->isEmpty()) return;
-                LogService::log(__METHOD__,'runMany','波次任务分配6.3:'.json_encode($stationTaskBatches));
+        ($execute = function(Collection $stationTaskBatches, &$stationTaskBatches_failed){
+                if ($stationTaskBatches->isEmpty()) return; //波次任务不存在 跳出
                 $stationTaskBatches_failed = collect();
-                LogService::log(__METHOD__,'runMany','波次任务分配6.4:'.json_encode($stationTaskBatches));
                 foreach ($stationTaskBatches as $stationTaskBatch) {
-                LogService::log(__METHOD__,'runMany','波次任务分配6.5:'.json_encode($stationTaskBatches));
-                    $failed = !$this->run($stationTaskBatch);
-                LogService::log(__METHOD__,'runMany','波次任务分配6.6:'.json_encode($stationTaskBatches));
-                    if ($failed) $stationTaskBatches_failed->push($stationTaskBatch);
+                    $failed = !$this->run($stationTaskBatch); //运行波次 获取执行结果
+                    if ($failed) $stationTaskBatches_failed->push($stationTaskBatch);//执行失败  记录失败波次
                 }
-            })($stationTaskBatches, $stationTaskBatches_failed);
+        })($stationTaskBatches, $stationTaskBatches_failed);
 
-        ($logAtFailings_andWait =
-            function ($stationTaskBatches_failed) {
-                LogService::log(__METHOD__,'runMany','波次任务分配6.7:'.json_encode($stationTaskBatches_failed));
+        (function ($stationTaskBatches_failed) {
                 if ($stationTaskBatches_failed->isEmpty()) return;
-                LogService::log(__METHOD__,'runMany','波次任务分配6.8:'.json_encode($stationTaskBatches_failed));
                 $retry_after_sec = config('task.batchTask.retry_after_sec');
                 LogService::log(__METHOD__, __FUNCTION__,
                     '任务波次没有执行完的,' . $retry_after_sec . '秒后准备重试:' . $stationTaskBatches_failed->toJson()
                     . '调用堆栈r:' . json_encode(array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), 0, 3))
                 );
-                LogService::log(__METHOD__,'runMany','波次任务分配6.9:'.json_encode($stationTaskBatches_failed));
                 sleep($retry_after_sec);
-                LogService::log(__METHOD__,'runMany','波次任务分配6.91:'.json_encode($stationTaskBatches_failed));
             })($stationTaskBatches_failed);
-                LogService::log(__METHOD__,'runMany','波次任务分配6.92:'.json_encode($stationTaskBatches));
-
-        $execute                    ($stationTaskBatches_failed, $stationTaskBatches_failed); //再次尝试
-                LogService::log(__METHOD__,'runMany','波次任务分配6.93:'.json_encode($stationTaskBatches));
-        $this->markManyExcepted  ($stationTaskBatches_failed);
-                LogService::log(__METHOD__,'runMany','波次任务分配6.94:'.json_encode($stationTaskBatches));
-        return                      $stationTaskBatches_failed;
+        $execute($stationTaskBatches_failed, $stationTaskBatches_failed); //再次尝试
+        $this->markManyExcepted($stationTaskBatches_failed);
+        return  $stationTaskBatches_failed;
     }
 
     function run(StationTaskBatch $stationTaskBatch): bool
     {
-        LogService::log(__METHOD__,'runMany','波次任务分配6.r1:'.json_encode($stationTaskBatch));
         $this->instant($this->foreignHaiRoboticsService,'ForeignHaiRoboticsService');
         $this->instant($this->stationService,'StationService');
         $stationTaskBatch->loadMissing(['station','stationTask.stationTaskMaterialBoxes']);
         LogService::log(__METHOD__,'runMany','波次任务分配6.r2:'.json_encode($stationTaskBatch));
-        $toLocation         = $this->stationService->getULineEntrance($stationTaskBatch['station'])['code'];
-        LogService::log(__METHOD__,'runMany','波次任务分配6.r3:'.json_encode($stationTaskBatch));
-        $groupPrefix        = $stationTaskBatch['id'];
+        $toLocation         = $this->stationService->getULineEntrance($stationTaskBatch['station'])['code'];//获取放线入口
+        $groupPrefix        = $stationTaskBatch['id'];//将波次任务ID当作组前缀
         $taskMaterialBoxes  = $stationTaskBatch['stationTask']['stationTaskMaterialBoxes'] ??
             (function () use ($stationTaskBatch) {
                 LogService::log(__METHOD__,'runMany','波次任务分配6.r4:'.json_encode($stationTaskBatch));
                 throw new Exception('找不到料箱:' . json_encode($stationTaskBatch));
-            })();
+            })();//存在任务返回任务 否则抛出无料箱异常
         try{
-            LogService::log(__METHOD__,'runMany','波次任务分配6.r5:'.json_encode($stationTaskBatch));
-            $isFetchedFromRobotics
-                = $this->foreignHaiRoboticsService->
-            fetchGroup($toLocation, $taskMaterialBoxes, $groupPrefix);
+            $isFetchedFromRobotics = $this->foreignHaiRoboticsService->
+                    fetchGroup($toLocation, $taskMaterialBoxes, $groupPrefix);//执行料箱任务
             LogService::log(__METHOD__,'runMany','波次任务分配6.r6:'.json_encode($stationTaskBatch));
         }catch(Exception $e){
             throw new ErrorException('$stationTaskBatch运行波次机器人任务失败,获取组失败: '.$stationTaskBatch->toJson() . $e->getMessage());
         }
-        LogService::log(__METHOD__,'runMany','波次任务分配6.r7:'.json_encode($stationTaskBatch));
-        ($markNewStatus
-            =function()use($isFetchedFromRobotics,$stationTaskBatch){
+        (function()use($isFetchedFromRobotics,$stationTaskBatch){
             $isFetchedFromRobotics?
-                $this->markProcessing($stationTaskBatch):
-                $this->markExcepted($stationTaskBatch);
-            LogService::log(__METHOD__,'runMany','波次任务分配6.r8:'.json_encode($stationTaskBatch));
+                $this->markProcessing($stationTaskBatch)://执行成功标记已处理
+                $this->markExcepted($stationTaskBatch);//执行失败标记失败
         })();
-        LogService::log(__METHOD__,'runMany','波次任务分配6.r9:'.json_encode($stationTaskBatch));
-        return $isFetchedFromRobotics;
+        return $isFetchedFromRobotics;//返回执行结果
     }
 
     function markProcessing($stationTaskBatch_orCollection)
@@ -216,7 +192,9 @@ class StationTaskBatchService
         if (get_class($stationTaskBatch_orCollection)==StationTaskBatch::class){
             $stationTaskBatch_orCollection = collect([$stationTaskBatch_orCollection]);
         }
-        $this->markProcessing_byIds(data_get($stationTaskBatch_orCollection, '*.id'));
+        $taskIds = data_get($stationTaskBatch_orCollection, '*.id');
+        $this->markProcessing_byIds($taskIds);
+        app("StorageService")->handleStorage($stationTaskBatch_orCollection);
     }
     function markProcessing_byIds($ids)
     {

+ 16 - 23
app/Services/StationTaskCommodityService.php

@@ -5,15 +5,14 @@ namespace App\Services;
 
 
 use App\Batch;
+use App\MaterialBoxCommodity;
 use App\OrderCommodity;
-use App\StationTask;
-use App\StationTaskBatch;
 use App\StationTaskCommodity;
 use App\StationTaskMaterialBox;
-use App\Storage;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;
 use App\Traits\ServiceAppAop;
+use Illuminate\Support\Facades\DB;
 
 
 class StationTaskCommodityService
@@ -195,26 +194,20 @@ class StationTaskCommodityService
         $stationTaskMaterialBoxes=StationTaskMaterialBox::query()
             ->whereIn('id', data_get($stationTaskCommodities, '*.station_task_material_box_id') ?? [])
             ->get('material_box_id');
-        $storages=Storage::query()->whereIn('commodity_id',data_get($stationTaskCommodities,'*.commodity_id')??[])
-            ->whereIn('material_box_id',data_get($stationTaskMaterialBoxes,'*.material_box_id')??[])
-            ->get();
-        foreach($storages as $storage){
-            $amountReducing=$stationTaskCommodities->where('material_box_id',$storage['material_box_id'])->first()['amount']??0;
-            $storage['amount']-=$amountReducing;
-            $storage->update();
+        $boxes = data_get($stationTaskMaterialBoxes,'*.material_box_id')??[];
+        $commodities = data_get($stationTaskCommodities,'*.commodity_id')??[];
+        $map = [];
+        foreach ($stationTaskCommodities as $commodity){
+            $map[$commodity->material_box_id."-".$commodity->commodity_id] = $commodity->amount;
         }
-//        $station_id=$stationTaskCommodities[0]['station_id'];
-//        $stationTaskCommodities_next=StationTaskCommodity::query()
-//            ->where('station_id',$station_id)
-//            ->where('status','处理队列')
-//            ->orderBy('updated_at')
-//            ->get();
-//        if($stationTaskCommodities_next->isNotEmpty()){
-//            $stationTaskCommodities_toUpdate=$stationTaskCommodities_next->where(
-//                'material_box_id', $stationTaskCommodities_next->first()['material_box_id']);
-//            StationTaskCommodity::query()
-//                ->whereIn('id',data_get($stationTaskCommodities_toUpdate,'*.id'))
-//                ->update(['status'=>'处理中']);
-//        }
+        MaterialBoxCommodity::query()->whereIn('commodity_id',$commodities)
+            ->whereIn('material_box_id',$boxes)->lockForUpdate()
+            ->get()->each(function ($boxC)use($map){
+                $key = $boxC->material_box_id."-".$boxC->commodity_id;
+                if (!isset($map[$key]))return false;
+                if ($boxC->amount>$map[$key])$boxC->update(["amount"=>DB::raw("amount-{$map[$key]}")]);
+                if ($boxC->amount==$map[$key])$boxC->delete();
+                return true;
+            });
     }
 }

+ 4 - 4
app/Services/StationTaskMaterialBoxService.php

@@ -109,13 +109,14 @@ class StationTaskMaterialBoxService
         $this->instant($this->orderCommodityService,'OrderCommodityService');
         $stationMaterialBoxes_toCreate=new Collection();
         $order_ids=data_get($batch['orders'],'*.id');
-        $orderCommodities=OrderCommodity::query()->with('orderBin')->whereIn('order_id',$order_ids)->get();
-        $orderCommodities=$this->orderCommodityService->correctLocation_fromWMS($orderCommodities);
+        $orderCommodities=OrderCommodity::query()->orderByRaw("commodity_id,amount desc")//同商品多条 数量最小优先
+            ->with('orderBin')->whereIn('order_id',$order_ids)->get();
+        //$orderCommodities=$this->orderCommodityService->correctLocation_fromWMS($orderCommodities);
         if($orderCommodities->isEmpty())return $stationMaterialBoxes_toCreate;
         $stationType=$this->stationTypeService->getForMaterialBox_onBatchProcess();
         $stationTaskBatch=$this->stationTaskBatchService->get(['batch_id'=>$batch['id']])->first();
         $materialBoxIds_used=[];
-        $orderCommodities=$orderCommodities->sortBy('commodity_id');//按商品排序后,出货可以同商品挨在一起
+        //$orderCommodities=$orderCommodities->sortBy('commodity_id');//按商品排序后,出货可以同商品挨在一起
         foreach ($orderCommodities as $orderCommodity){
             $station=$this->stationService->getStation_byType($stationType['name']);
             $materialBox=$this->materialBoxService->firstOrCreate(['code' => $orderCommodity['location']]);
@@ -172,7 +173,6 @@ class StationTaskMaterialBoxService
                     $stationTaskMaterialBox->materialBox->update();
                     break;
                 case '入立库':
-                    $this->cacheShelfService->putStationTaskMaterialBoxProcess($stationTaskMaterialBox);
                     $stationTaskMaterialBox->materialBox['status']='在立库';
                     $stationTaskMaterialBox->materialBox->update();
                     $stationTaskMaterialBox->loadMissing("station");    //提前加载站,后续都需要站信息来处理

+ 77 - 221
app/Services/StorageService.php

@@ -3,13 +3,14 @@
 namespace App\Services;
 
 use App\CommodityMaterialBoxModel;
+use App\Components\ErrorPush;
+use App\MaterialBoxCommodity;
 use App\Station;
 use App\StationTask;
 use App\StationTaskMaterialBox;
 use App\StoreItem;
 use App\TaskTransaction;
 use App\Traits\ServiceAppAop;
-use App\Storage;
 use App\ValueStore;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Model;
@@ -21,38 +22,7 @@ use Illuminate\Support\Str;
 class StorageService
 {
     use ServiceAppAop;
-    protected $modelClass=Storage::class;
-
-
-    /**
-     * 填充缓存架
-     *
-     * @param \Illuminate\Database\Eloquent\Collection $stations
-     */
-    public function paddingCacheShelf($stations)
-    {
-        $collection = new Collection();
-        $stationCollection = new Collection();
-        $blacklist = [];
-        foreach ($stations as $station){
-            $box = app("MaterialBoxService")->getAnEmptyBox($blacklist);
-            if (!$box)continue;
-            $task = StationTask::query()->create([
-                'status' => "待处理",
-                'station_id' => $station->id,
-            ]);
-            $collection->add(StationTaskMaterialBox::query()->create([
-                'station_id' => $station->id,
-                'material_box_id'=>$box->id,
-                'status'=>"待处理",
-                'type' => '取',
-                'station_task_id' => $task->id,
-            ]));
-            $stationCollection->add($station->code);
-            $blacklist[] = $box->id;
-        }
-        app("ForeignHaiRoboticsService")->fetchGroup_multiLocation($stationCollection,$collection,'','立架出至缓存架');
-    }
+    use ErrorPush;
 
     /**
      * 缓存架放置记录
@@ -63,30 +33,20 @@ class StorageService
     {
         DB::beginTransaction();
         try{
-            $storage = Storage::query()->where("material_box_id",$stationTaskMaterialBox->material_box_id)->lockForUpdate()->first();
-            if ($storage)$storage->update(["station_id"=>$stationTaskMaterialBox->station_id,'status'=>0]);
-            else Storage::query()->create([
-                "station_id" => $stationTaskMaterialBox->station_id,
-                "material_box_id" => $stationTaskMaterialBox->material_box_id,
-            ]);
+            Station::query()->where("id",$stationTaskMaterialBox->station_id)
+                ->update(["material_box_id"=>$stationTaskMaterialBox->material_box_id,"status"=>0]);
             $stationTaskMaterialBox->loadMissing("station");
-            //清理原有任务
-            if ($stationTaskMaterialBox->station){
-                switch ($stationTaskMaterialBox->station->parent_id){
-                    case 6:
-                        $this->clearTask([$stationTaskMaterialBox->station->code]);
-                        break;
-                    case 7:
-                        $task = TaskTransaction::query()->with("materialBox")->where("fm_station_id",$stationTaskMaterialBox->station_id)
-                            ->where("status",0)->first();
-                        if ($task)app("CacheShelfService")->lightUp($stationTaskMaterialBox->station->code,'1','0',[
-                            "title"=>$task->materialBox->code ?? '',
-                            "detail01"=>"{$task->doc_code}",
-                            "detail02"=>"商品条码:{$task->bar_code}",
-                            "detail03"=>"上架数量:{$task->amount}",
-                        ]);
-                        break;
-                }
+            //如果为半箱位置 清理原有任务
+            if ($stationTaskMaterialBox->station && app("StationService")->isHalfBoxLocation($stationTaskMaterialBox->station)){
+                $task = TaskTransaction::query()->selectRaw("1")->with("materialBox")->where("fm_station_id",$stationTaskMaterialBox->station_id)
+                    ->where("status",0)->first();
+                if ($task)app("CacheShelfService")->lightUp($stationTaskMaterialBox->station->code,'1','0',[
+                    "title"=>$task->materialBox->code ?? '',
+                    "detail01"=>"{$task->doc_code}",
+                    "detail02"=>"商品条码:{$task->bar_code}",
+                    "detail03"=>"上架数量:{$task->amount}",
+                ]);
+                else $this->clearTask([$stationTaskMaterialBox->station->code]);
             }
             DB::commit();
         }catch (\Exception $e){
@@ -101,13 +61,8 @@ class StorageService
      */
     public function releaseOccupation($stationTaskMaterialBox)
     {
-        if ($stationTaskMaterialBox->station->station_type_id != 5)return;
-        $storage = Storage::query()->where("material_box_id",$stationTaskMaterialBox->material_box_id)->first();
-        if (!$storage)return;
-        $update = [];
-        if ($storage->status == 1)$update["status"] = 0;
-        if ($storage->station_id)$update["station_id"] = null;
-        if ($update)$storage->update($update);
+        if (!app("StationService")->isCacheShelfLocation($stationTaskMaterialBox->station))return;
+        app("StationService")->locationFreed($stationTaskMaterialBox->station->code);
     }
 
     /**
@@ -157,7 +112,8 @@ class StorageService
                     return false;
                 }
                 $taskMaterialBox = $this->createWarehousingTask($station->id,$task->material_box_id);//建立入库任务
-                if (!$this->enterWarehouse($station->id,$task->material_box_id,$task->commodity_id,$task->amount))throw new \Exception("库存异常"); //处理库存
+                //2021-07-27 取消WAS库存维护
+                //if (!$this->enterWarehouse($task->material_box_id,$task->commodity_id,$task->amount))throw new \Exception("库存异常"); //处理库存
                 $task->update([
                     "task_id" => $taskMaterialBox->id,
                     "status" => 1,
@@ -183,7 +139,7 @@ class StorageService
      *
      * @return StationTaskMaterialBox|\stdClass|Model
      */
-    public function createWarehousingTask($stationId,$boxId)
+    public function createWarehousingTask($stationId,$boxId):StationTaskMaterialBox
     {
         /** @var StationTask|\stdClass $task */
         $task = StationTask::query()->create([
@@ -202,32 +158,28 @@ class StorageService
     /**
      * 库存入库
      *
-     * @param integer $stationId
      * @param integer $boxId
      * @param integer $commodityId
      * @param integer $amount
-     * @param integer $modelId
+     * @param integer|null $modelId
      *
      * @return bool
      */
-    public function enterWarehouse($stationId, $boxId, $commodityId, $amount, $modelId = null)
+    public function enterWarehouse(int $boxId,int $commodityId,int $amount,?int $modelId = null):bool
     {
         DB::beginTransaction();
         try{
-            $storage = Storage::query()->where("material_box_id",$boxId)->lockForUpdate()->first();
-            $obj = [
-                "station_id" => $stationId,
-                "material_box_id" => $boxId,
-                "commodity_id" => $commodityId,
-                "amount" => $amount,
-                "status" => 1,
-            ];
+            $storage = MaterialBoxCommodity::query()->where("material_box_id",$boxId)
+                ->where("commodity_id",$commodityId)->lockForUpdate()->first();
             if ($storage){
                 $amountTemp = (int)$storage->amount + (int)$amount;
-                $obj["amount"] = DB::raw("amount+{$amount}");
-                $storage->update($obj);
+                $storage->update(["amount"=>DB::raw("amount+{$amount}")]);
                 $amount = $amountTemp;
-            } else Storage::query()->create($obj);
+            } else $storage = MaterialBoxCommodity::query()->create([
+                "amount" => $amount,
+                "material_box_id" => $boxId,
+                "commodity_id" => $commodityId,
+            ]);
             if ($commodityId && $modelId){
                 //维护料箱最大上限 用于半箱补货
                 $model = CommodityMaterialBoxModel::query()->select("maximum")->where("commodity_id",$commodityId)
@@ -237,7 +189,7 @@ class StorageService
                     ->where("material_box_model_id",$modelId)->update(["maximum"=>$amount]);
             }
             DB::commit();
-            LogService::log(__CLASS__,"库存增加",$storage->toJson()."  |  ".json_encode([$stationId, $boxId, $commodityId, $amount, $modelId]));
+            LogService::log(__CLASS__,"库存增加",$storage->toJson()."  |  ".json_encode([$boxId, $commodityId, $amount, $modelId]));
             return true;
         }catch(\Exception $e){
             DB::rollBack();
@@ -288,6 +240,7 @@ sql;
      * @param int $amount
      *
      * @return array
+     * @throws
      */
     private function splitTask($tasks,$maxIndex,$amount):array
     {
@@ -356,49 +309,11 @@ sql;
             DB::connection("oracle")->update(DB::raw("UPDATE TSK_TASKLISTS SET FMQTY = ?,FMQTY_EACH = ?,PLANTOQTY=?,PLANTOQTY_EACH=? WHERE TASKID = ? AND TASKID_SEQUENCE = ?"),[
                 $amount,$amount,$amount,$amount,$task->taskid,$task->taskid_sequence
             ]);
-            /*$invs = DB::connection("oracle")->select(DB::raw("SELECT * FROM INV_LOT_LOC_ID WHERE LOTNUM = ? AND LOCATIONID IN (?,?) AND TRACEID = ?"),[
-                $task->fmlotnum,$task->fmlocation,$task->plantolocation,$task->fmid
-            ]);
-            foreach ($invs as $inv){
-                if ($inv->locationid==$task->fmlocation){
-                    $columns = '';
-                    $values = '';
-                    DB::connection("oracle")->update(DB::raw("UPDATE inv_lot_loc_id SET qty = qty-?,qtymvout = qtymvout-? WHERE lotnum = ? AND locationid = ? AND traceid = ?"),[
-                        $amount,$amount,$inv->lotnum,$inv->locationid,$inv->traceid
-                    ]);
-                    foreach ($inv as $key=>$val){
-                        if (Str::upper($key)=='TRACEID') $val = "WAS".$task->fmid;
-                        if (Str::upper($key)=='QTY' || Str::upper($key)=='QTYMVOUT') $val = $amount;
-                        $columns .= $key.",";
-                        $values .= $this->valFormat($val) .",";
-                    }
-                    $columns = mb_substr($columns,0,-1);
-                    $values = mb_substr($values,0,-1);
-                    DB::connection("oracle")->insert(DB::raw("INSERT INTO inv_lot_loc_id({$columns}) VALUES({$values})"));
-                }
-                if ($inv->locationid==$task->plantolocation){
-                    $columns = '';
-                    $values = '';
-                    DB::connection("oracle")->update(DB::raw("UPDATE inv_lot_loc_id SET QTYPA = QTYPA-? WHERE lotnum = ? AND locationid = ? AND traceid = ?"),[
-                        $amount,$inv->lotnum,$inv->locationid,$inv->traceid
-                    ]);
-                    foreach ($inv as $key=>$val){
-                        if (Str::upper($key)=='TRACEID') $val = "WAS".$task->fmid;
-                        if (Str::upper($key)=='QTYPA') $val = $amount;
-                        $columns .= $key.",";
-                        $values .= $this->valFormat($val) .",";
-                    }
-                    $columns = mb_substr($columns,0,-1);
-                    $values = mb_substr($values,0,-1);
-                    DB::connection("oracle")->insert(DB::raw("INSERT INTO inv_lot_loc_id({$columns}) VALUES({$values})"));
-                }
-            }*/
             DB::connection("oracle")->commit();
         }catch(\Exception $e) {
             DB::connection("oracle")->rollBack();
             throw new \Exception("拆分任务失败:".$e->getMessage());
         }
-        //return DB::connection("oracle")->selectOne(DB::raw("SELECT * FROM TSK_TASKLISTS WHERE TASKID = ? AND TASKID_SEQUENCE = ?"),[$task->taskid,$seq]);
         return $task;
     }
 
@@ -443,22 +358,21 @@ sql;
         if (!$task->taskid)return false;//ASN单无此入库信息,禁止上架
         $amount = (int)$task->fmqty;
         $db = DB::connection("oracle");
-        $db->transaction(function ()use($db,$amount,$ide,$task,&$who){
+        $db->beginTransaction();
+        try {
             $sql = <<<sql
-SELECT * FROM inv_lot_loc_id  WHERE lotnum = ? AND traceid = ? AND locationid = ? AND customerid= ?  and sku = ? and qtypa >= {$amount} FOR UPDATE
+SELECT * FROM inv_lot_loc_id  WHERE lotnum = ? AND traceid = ? AND locationid = ? AND customerid= ?  and sku = ? and qty >= {$amount} FOR UPDATE
 sql;
-            $inv = $db->selectOne(DB::raw($sql),[$task->plantolotnum,$task->plantoid,$task->plantolocation,$task->customerid,$task->sku]);
+            $inv = $db->selectOne(DB::raw($sql),[$task->fmlotnum,$task->fmid,$task->fmlocation,$task->customerid,$task->sku]);
             if (!$inv)return false;//余量与入库不符
 
             $inv1 = $db->update(DB::raw("UPDATE inv_lot_loc_id SET qty = qty - ? WHERE LOTNUM = ? AND LOCATIONID = ? AND TRACEID = ? AND traceid != '*'"),[
                 $amount,$task->fmlotnum,$task->fmlocation,$task->fmid
             ]);
-            $sql = "UPDATE inv_lot_loc_id SET qty = qtypa - ?";
-            if ($inv->qtypa==$amount)$sql .= ",LOCATIONID = '{$ide}'";
-            $inv2 = $db->update(DB::raw($sql." WHERE LOTNUM = ? AND LOCATIONID = ? AND TRACEID = ? AND traceid != '*'"),[
+            $db->update(DB::raw("UPDATE inv_lot_loc_id SET qtypa = qtypa - ? WHERE LOTNUM = ? AND LOCATIONID = ? AND TRACEID = ? AND traceid != '*'"),[
                 $amount,$task->plantolotnum,$task->plantolocation,$task->plantoid
             ]);
-            if ($inv1!=1 || $inv2!=1){
+            if ($inv1!=1){
                 $db->rollBack();
                 return false;//库存余量错误
             }
@@ -486,7 +400,7 @@ sql;
                 '*','0','N','*',$task->taskid_sequence,$task->warehouseid,$task->userdefine1,$task->userdefine2,
                 $task->userdefine3,'O'
             ]);
-            $this->setTrNumber($max);
+            $this->setTrNumber();
             $sql = <<<sql
 update TSK_TASKLISTS set TASKPROCESS = '99',REASONCODE = 'OK',PLANTOLOCATION = ?,PLANLOGICALTOSEQUENCE = ?,
 COMPLETED_TRANSACTIONID = ?,OPENWHO = ?,OPENTIME = TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),
@@ -498,12 +412,16 @@ sql;
             ]);
             $task->who = $who;
             $this->checkAsn($task);
+            $db->commit();
             return true;
-        });
-        return true;
+        }catch (\Exception $e){
+            $db->rollBack();
+            return false;
+        }
     }
 
-    private function checkAsn($task)
+    private function
+    checkAsn($task)
     {
         $sql = <<<SQL
 SELECT 1 FROM DOC_ASN_DETAILS WHERE ASNNO = ? AND LINESTATUS != '40'
@@ -555,9 +473,9 @@ SQL;
      *
      * @return array
      */
-    private function getTrNumber()
+    public function getTrNumber()
     {
-        $val = ValueStore::query()->select("value")->where("name","flux_tr_number")->first();
+        $val = ValueStore::query()->select("value")->where("name","flux_tr_number")->lockForUpdate()->first();
         if (!$val)$val = ValueStore::query()->create(["name"=>"flux_tr_number","value"=>'0']);
         $max = $val->value+1;
         $number = sprintf("%09d", $max);
@@ -567,80 +485,10 @@ SQL;
     /**
      * 设置事务现号
      *
-     * @param integer $max
-     */
-    private function setTrNumber($max)
-    {
-        ValueStore::query()->select("value")->where("name","flux_tr_number")->update(["value"=>(string)((int)$max+1)]);
-    }
-
-    /**
-     * 入库
-     *
-     * @param integer $boxId
-     * @param integer $amount
-     * @param integer $commodityId
-     *
-     * @return bool
-     */
-    public function warehousing($boxId, $amount, $commodityId = null):bool
-    {
-        DB::beginTransaction();
-        try{
-            $storage = Storage::query()->where("material_box_id",$boxId)->lockForUpdate()->first();
-            if (!$storage && !$commodityId)return false;
-            if (!$storage){
-                Storage::query()->create([
-                    "station_id" => null,
-                    "material_box_id" => $boxId,
-                    "commodity_id" => $commodityId,
-                    "amount" => $amount,
-                ]);
-                return true;
-            }
-            if ($commodityId && $storage->commodity_id && $storage->commodity_id!=$commodityId)return false;
-            $obj = [
-                "station_id" => null,
-                "amount" => DB::raw("amount + {$amount}"),
-            ];
-            if (!$storage->commodity_id && $commodityId)$obj["commodity_id"] = $commodityId;
-            $storage->update($obj);
-            DB::commit();
-            return true;
-        }catch (\Exception $e){
-            DB::rollBack();
-            return false;
-        }
-    }
-
-    /**
-     * 出库
-     *
-     * @param integer $boxId
-     * @param integer $amount
-     * @param integer $commodityId
-     *
-     * @return bool
      */
-    public function outWarehousing($boxId, $amount, $commodityId = null):bool
+    public function setTrNumber()
     {
-        DB::beginTransaction();
-        try{
-            $storage = Storage::query()->where("material_box_id",$boxId)->lockForUpdate()->first();
-            if (!$storage)return false;
-            if ($commodityId && $storage->commodity_id && $storage->commodity_id!=$commodityId)return false;
-            $obj = [
-                "station_id" => null,
-                "amount" => DB::raw("amount - {$amount}"),
-            ];
-            if (!$storage->commodity_id && $commodityId)$obj["commodity_id"] = $commodityId;
-            $storage->update($obj);
-            DB::commit();
-            return true;
-        }catch (\Exception $e){
-            DB::rollBack();
-            return false;
-        }
+        ValueStore::query()->select("value")->where("name","flux_tr_number")->update(["value"=>DB::raw("value+1")]);
     }
 
     /**
@@ -657,15 +505,6 @@ SQL;
                 "ks_bin_space_code" => null,"ks_bin_space_id"=>null,"orig_ks_bin_space_code"=>null,"orig_ks_bin_space_id"=>null,
                 "status"=>4,
             ]);
-        //WAS任务清除
-        $station = Station::query()->select("id")->whereIn("code",$stationCodes);
-        $task = StationTask::query()->select("id")->where("status","!=",'完成')->whereIn("station_id",$station);
-        StationTaskMaterialBox::query()->where("status","!=",'完成')->whereIn("station_task_id",$task)->update([
-            "status" => "完成"
-        ]);
-        StationTask::query()->where("status","!=",'完成')->whereIn("station_id",$station)->update([
-            "status" => "完成"
-        ]);
     }
 
     /**
@@ -675,21 +514,18 @@ SQL;
      * @param StoreItem|\stdClass $item
      * @param string|null $asn
      *
-     * @return ?Storage
+     * @return ?MaterialBoxCommodity
      */
-    public function getHalfBoxLocation(CommodityMaterialBoxModel $model,StoreItem $item,?string $asn = null,array $blacklist = []):?Storage
+    public function getHalfBoxLocation(CommodityMaterialBoxModel $model,StoreItem $item,?string $asn = null,array $blacklist = []):?MaterialBoxCommodity
     {
         if (!$asn){$item->loadMissing("store");$asn = $item->store->asn_code;}
         $boxCodes = '';//拼接料箱编码
         $map = [];//库位与库存映射
         //查询填充
-        $query = Storage::query()->with("materialBox")->whereHas("materialBox",function (Builder $query)use($model){
+        $query = MaterialBoxCommodity::query()->with("materialBox")->whereHas("materialBox",function (Builder $query)use($model){
             $query->where("material_box_model_id",$model->material_box_model_id);
-        })->where("commodity_id",$model->commodity_id)->where("amount","<",$model->maximum)
-            ->where("status",0)->where(DB::raw("{$model->maximum}-amount"),">",0);
-        if ($blacklist)$query->whereHas("materialBox",function (Builder $query)use($blacklist){
-           $query->whereNotIn("id",$blacklist);
-        });
+        })->where("commodity_id",$model->commodity_id)->where("amount","<",$model->maximum);
+        if ($blacklist)$query->whereNotIn("material_box_id",$blacklist);
         $query->get()->each(function ($storage)use(&$boxCodes,&$map){
             $boxCodes .= "'".$storage->materialBox->code."',";
             $map[$storage->materialBox->code] = $storage;
@@ -721,7 +557,7 @@ sql;
                 $sql .= " AND LOTATT0{$i} = $val";
             }
         }
-        $sql .= ") AND LOCATIONID IN ({$boxCodes}) AND TRACEID = '*' AND {$model->maximum}-QTY > 0 ORDER BY {$model->maximum}-QTY";
+        $sql .= ") AND LOCATIONID IN ({$boxCodes}) AND TRACEID = '*' AND {$model->maximum}-QTY > 0 ORDER BY (CASE QTY WHEN 0 THEN 1 ELSE 0 END),{$model->maximum}-QTY";
         $res = DB::connection("oracle")->selectOne(DB::raw($sql),[
             $detail["customerid"],$detail["sku"]
         ]);
@@ -751,4 +587,24 @@ SQL;
         if (!$trk)return $tsk->qty;
         return $tsk->qty - $trk->amount;
     }
+
+    /**
+     * @param Collection $tasks
+     */
+    public function handleStorage(Collection $tasks)
+    {
+        $tasks = \Illuminate\Database\Eloquent\Collection::make($tasks);
+        $tasks->load("stationTaskCommodities");
+        if (!$tasks->count())return;
+        foreach ($tasks as $task){
+            if (!$task->stationTaskCommodities)continue;
+            foreach ($task->stationTaskCommodities as $commodity){
+                $update[] = [$task->material_box_id];
+                $result = MaterialBoxCommodity::query()->where("material_box_id",$task->material_box_id)
+                    ->where("commodity_id",$commodity->commodity_id)
+                    ->update(["amount"=>DB::raw("amount-{$commodity->amount}")]);
+                if ($result!==1)$this->push(__METHOD__."->".__LINE__,"库存处理异常","修改了:".$result."行; 表参数:".$commodity->toJson());
+            }
+        }
+    }
 }

+ 0 - 1
app/Services/common/BatchUpdateService.php

@@ -12,7 +12,6 @@ use App\Traits\ServiceAppAop;
 class BatchUpdateService
 {
     use ServiceAppAop;
-    protected $modelClass=BatchUpdate::class;
     public function batchUpdate($tableName = '', $multipleData = array(), $connection = 'mysql')
     {
         if (count($multipleData) == 1) {

+ 11 - 2
app/Station.php

@@ -3,8 +3,8 @@
 namespace App;
 
 use App\Traits\ModelTimeFormat;
-use Carbon\Carbon;
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
 use Illuminate\Database\Eloquent\Relations\HasOne;
 use App\Traits\ModelLogChanging;
 
@@ -13,8 +13,17 @@ class Station extends Model
     use ModelLogChanging;
     use ModelTimeFormat;
 
-    protected $fillable=['name', 'code', 'station_type_id','sequence','parent_id'];
+    protected $fillable=['name', 'code', 'station_type_id','sequence','parent_id',"material_box_id","status"];
 
+    const STATUS=[
+        0 => "正常",
+        1 => "占用",
+    ];
+
+    public function materialBox():BelongsTo
+    {
+        return $this->belongsTo(MaterialBox::class);
+    }
     public function stationType(){
         return $this->belongsTo(StationType::class);
     }

+ 3 - 4
app/Waybill.php

@@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
 use Illuminate\Database\Eloquent\SoftDeletes;
 
 use App\Traits\ModelLogChanging;
+use Illuminate\Support\Facades\DB;
 
 class Waybill extends Model
 {
@@ -62,7 +63,8 @@ class Waybill extends Model
         'cargo_name',
         'total_number',
         'total_weight',
-        'deliveryType_id'
+        'deliveryType_id',
+        "merge_owner",//合并货主ID集
     ];
 
     public function district()
@@ -125,9 +127,6 @@ class Waybill extends Model
     {   //订单
         return $this->hasOne(DeliveryType::class,'id','deliveryType_id');
     }
-
-
-
     static public function setWeightByOrderCode($orderCode,$weight){
         if(empty($orderCode))return;
         $waybill=Waybill::query()->where('wms_bill_number',$orderCode)->where('status','!=','已完结')

+ 4 - 0
ci/executeCommand.sh

@@ -24,3 +24,7 @@ for file in `ls $update_path`
     done
 
 sshpass -p $password ssh -p 10022 $username@$Ip "cd $dsc; sudo php artisan view:clear"
+# shellcheck disable=SC2164
+cd "$update_path"
+# shellcheck disable=SC2035
+sudo rm -rf *

+ 1 - 1
ci/judgePush.sh

@@ -7,7 +7,7 @@ path=$1
 # shellcheck disable=SC2164
 cd "$update_path"
 # shellcheck disable=SC2035
-rm -rf *
+#rm -rf *
 
 #将项目文件中3分钟之前改动的文件存到update文件
 # shellcheck disable=SC2038

+ 1 - 1
ci/scpUpdate.sh

@@ -19,6 +19,6 @@ expect {
 expect eof"
 done
 
-sudo chmod 775 $update_path/* -R
+sudo chmod 775 $dsc/* -R
 
 

+ 10 - 8
config/api_logistic.php

@@ -174,10 +174,11 @@ return [
             'customer_Code' => 'F2015082279473065',
             'sign' => 'IYKO',
             'needTraceInfo' => 0, //是否需要订阅轨迹 1:是 2:否
-            'orderType' => 2, //下单模式 1:散客模式 2:大客户模式 3:同步筛单下单
-            'transportType' => 'JJDJ', //运输方式/产品类型 快递运输方式 : RCP:大件快递360; NZBRH:重包入户; ZBTH:重包特惠; WXJTH:微小件特惠; JJDJ:经济大件; PACKAGE:标准快递; DEAP:特准快件;HKDJC:航空大件次日达; HKDJG:航空大件隔日达; TZKJC:特快专递; 零担运输方式: JZKY:精准空运(仅散客模式支持该运输方式); JZQY_LONG:精准汽运; JZKH:精准卡航; 整车运输方式 1.整车配送 ZCPS 2.精准专车 JZZHC
-            'payType' => 2, //支付方式  0、发货人付款(现付)(大客户模式不支持寄付) 1、收货人付款(到付) 2、发货人付款(月结)
-            'backSignBill' => 2, //运输方式/产品类型 1:散客模式 2:大客户模式 3:同步筛单下单
+            'orderType' => [1 => '散客模式',2 => '大客户模式',3 => '同步筛单下单'], //下单模式 1:散客模式 2:大客户模式 3:同步筛单下单
+            'transportType' => ['JZQY_LONG' => '精准汽运', 'JZKH' => '精准卡航'], //运输方式/产品类型 快递运输方式 : RCP:大件快递360; NZBRH:重包入户; ZBTH:重包特惠; WXJTH:微小件特惠; JJDJ:经济大件; PACKAGE:标准快递; DEAP:特准快件;HKDJC:航空大件次日达; HKDJG:航空大件隔日达; TZKJC:特快专递; 零担运输方式: JZKY:精准空运(仅散客模式支持该运输方式); JZQY_LONG:精准汽运; JZKH:精准卡航; 整车运输方式 1.整车配送 ZCPS 2.精准专车 JZZHC
+            'payType' => [0 => '发货人付款(现付)(大客户模式不支持寄付)',1 => '收货人付款(到付)',2 => '发货人付款(月结)'], //支付方式  0、发货人付款(现付)(大客户模式不支持寄付) 1、收货人付款(到付) 2、发货人付款(月结)
+            'backSignBill' => [0 =>'无需返单',1 => '签收单原件返回',2 => '电子签收单'], //签收回单  0:无需返单 1:签收单原件返回 2:电子签收单(电子签名图片需要另外对接查询接口)
+            'packageService' => ['纸','纤','木箱','木架','托膜','托木'],  //包装(直接用中文) : 纸、纤、木箱、木架、托膜、托木(大客户模式下运输方式为零担时必填)
             'smsNotify' => 'N', //短信通知  Y:需要 N: 不需要
             'passwordSigning' => 'N', //是否口令签收 仅适用于快递,Y:需要 N: 不需要;若为Y,必须收货人提供验证码给快递员才能签收,该服务是有偿的,具体费用请让我司收货营业部联系张宁(491407),请慎重使用!
             'uri' => [
@@ -190,10 +191,11 @@ return [
             'customer_Code' => 'F2015082279473065',
             'sign' => 'IYKO',
             'needTraceInfo' => 0, //是否需要订阅轨迹 1:是 2:否
-            'orderType' => 2, //下单模式 1:散客模式 2:大客户模式 3:同步筛单下单
-            'transportType' => 'JJDJ', //运输方式/产品类型 快递运输方式 : RCP:大件快递360; NZBRH:重包入户; ZBTH:重包特惠; WXJTH:微小件特惠; JJDJ:经济大件; PACKAGE:标准快递; DEAP:特准快件;HKDJC:航空大件次日达; HKDJG:航空大件隔日达; TZKJC:特快专递; 零担运输方式: JZKY:精准空运(仅散客模式支持该运输方式); JZQY_LONG:精准汽运; JZKH:精准卡航; 整车运输方式 1.整车配送 ZCPS 2.精准专车 JZZHC
-            'payType' => 2, //支付方式  0、发货人付款(现付)(大客户模式不支持寄付) 1、收货人付款(到付) 2、发货人付款(月结)
-            'backSignBill' => 2, //运输方式/产品类型 1:散客模式 2:大客户模式 3:同步筛单下单
+            'orderType' => [1 => '散客模式',2 => '大客户模式',3 => '同步筛单下单'], //下单模式 1:散客模式 2:大客户模式 3:同步筛单下单
+            'transportType' => ['JZQY_LONG' => '精准汽运', 'JZKH' => '精准卡航'], //运输方式/产品类型 快递运输方式 : RCP:大件快递360; NZBRH:重包入户; ZBTH:重包特惠; WXJTH:微小件特惠; JJDJ:经济大件; PACKAGE:标准快递; DEAP:特准快件;HKDJC:航空大件次日达; HKDJG:航空大件隔日达; TZKJC:特快专递; 零担运输方式: JZKY:精准空运(仅散客模式支持该运输方式); JZQY_LONG:精准汽运; JZKH:精准卡航; 整车运输方式 1.整车配送 ZCPS 2.精准专车 JZZHC
+            'payType' => [0 => '发货人付款(现付)(大客户模式不支持寄付)',1 => '收货人付款(到付)',2 => '发货人付款(月结)'], //支付方式  0、发货人付款(现付)(大客户模式不支持寄付) 1、收货人付款(到付) 2、发货人付款(月结)
+            'backSignBill' => [0 =>'无需返单',1 => '签收单原件返回',2 => '电子签收单'], //签收回单  0:无需返单 1:签收单原件返回 2:电子签收单(电子签名图片需要另外对接查询接口)
+            'packageService' => ['纸','纤','木箱','木架','托膜','托木'],  //包装(直接用中文) : 纸、纤、木箱、木架、托膜、托木(大客户模式下运输方式为零担时必填)
             'smsNotify' => 'N', //短信通知  Y:需要 N: 不需要
             'passwordSigning' => 'N', //是否口令签收 仅适用于快递,Y:需要 N: 不需要;若为Y,必须收货人提供验证码给快递员才能签收,该服务是有偿的,具体费用请让我司收货营业部联系张宁(491407),请慎重使用!
             'uri' => [

+ 1 - 1
config/users.php

@@ -1,7 +1,7 @@
 <?php
 
 return [
-    'superAdmin' => ['ldaaww','baoshi56','周亚萍','shiyao','zhouzhendong','胡浩','zengjun','阿珺','huhao','yang',env('SUPER_ADMIN',"")],
+    'superAdmin' => ['ldaaww','baoshi56','周亚萍','shiyao','zhouzhendong','zengjun',"yang",'huhao','zhangwanli',env('SUPER_ADMIN',"")],
     'token_expire_minutes'=>7200,
     'token_check_in_expire_minutes'=>432000, //打卡过期时间,单位为秒
     'cookie_expire_minutes'=>7200,//cookie过期时间,单位分钟

+ 12 - 0
database/factories/RequirementFactory.php

@@ -0,0 +1,12 @@
+<?php
+
+/** @var \Illuminate\Database\Eloquent\Factory $factory */
+
+use App\Requirement;
+use Faker\Generator as Faker;
+
+$factory->define(Requirement::class, function (Faker $faker) {
+    return [
+        //
+    ];
+});

+ 12 - 0
database/factories/RequirementUserFactory.php

@@ -0,0 +1,12 @@
+<?php
+
+/** @var \Illuminate\Database\Eloquent\Factory $factory */
+
+use App\RequirementUser;
+use Faker\Generator as Faker;
+
+$factory->define(RequirementUser::class, function (Faker $faker) {
+    return [
+        //
+    ];
+});

+ 34 - 0
database/migrations/2021_07_13_163057_change_material_box_models_table.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeMaterialBoxModelsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('material_box_models', function (Blueprint $table) {
+            $table->string("description")->nullable()->comment("描述");
+            $table->integer("maximum_kind")->default(1)->comment("最大放置商品种类");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('material_box_models', function (Blueprint $table) {
+            $table->dropColumn("description");
+            $table->dropColumn("maximum_kind");
+        });
+    }
+}

+ 32 - 0
database/migrations/2021_07_14_102919_change_waybills_add_column_merge_owner_id.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeWaybillsAddColumnMergeOwnerId extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            $table->string("merge_owner")->nullable()->comment("合并货主");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            $table->dropColumn("merge_owner");
+        });
+    }
+}

+ 34 - 0
database/migrations/2021_07_14_151459_create_error_temps_table.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateErrorTempsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('error_temps', function (Blueprint $table) {
+            $table->id();
+            $table->string("position");
+            $table->string("title");
+            $table->text("content");
+            $table->timestamp("created_at");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('error_temps');
+    }
+}

+ 39 - 0
database/migrations/2021_07_15_173811_alert_order_type_column_in_waybills_table.php

@@ -0,0 +1,39 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AlertOrderTypeColumnInWaybillsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            $table->unsignedTinyInteger('order_type')->default('2')->nullable()->comment('下单模式 1:散客模式 2:大客户模式 3:同步筛单下单');
+            $table->string('transport_type')->default('JZQY_LONG')->nullable()->comment('运输方式/产品类型 JZQY_LONG:精准汽运  JZKH: 精准卡航 ');
+            $table->unsignedTinyInteger('pay_type')->default('2')->nullable()->comment('支付方式  0、发货人付款(现付)(大客户模式不支持寄付) 1、收货人付款(到付) 2、发货人付款(月结)');
+            $table->unsignedTinyInteger('back_sign_bill')->default('2')->nullable()->comment('签收回单  0:无需返单 1:签收单原件返回 2:电子签收单(电子签名图片需要另外对接查询接口)');
+            $table->string('package_service',10)->default('木箱')->nullable()->comment('包装(直接用中文) : 纸、纤、木箱、木架、托膜、托木(大客户模式下运输方式为零担时必填)');
+            $table->integer('total_number')->default(1)->change();
+            $table->unsignedInteger('deliveryType_id')->default(3)->change();
+        });
+        \Illuminate\Support\Facades\DB::statement("ALTER TABLE waybills MODIFY COLUMN type ENUM('直发车','专线','德邦物流') not null");
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            //
+        });
+    }
+}

+ 32 - 0
database/migrations/2021_07_16_093026_change_owners_add_model_sequence_column.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeOwnersAddModelSequenceColumn extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('owners', function (Blueprint $table) {
+            $table->string("model_sequence")->nullable()->comment("模型序列");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('owners', function (Blueprint $table) {
+            $table->dropColumn("model_sequence");
+        });
+    }
+}

+ 34 - 0
database/migrations/2021_07_19_113938_create_material_box_commodities_table.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateMaterialBoxCommoditiesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('material_box_commodities', function (Blueprint $table) {
+            $table->id();
+            $table->bigInteger("material_box_id")->index()->comment("料箱ID");
+            $table->bigInteger("commodity_id")->index()->comment("商品ID");
+            $table->integer("amount")->default(0)->comment("数量");
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('material_box_commodities');
+    }
+}

+ 34 - 0
database/migrations/2021_07_19_115331_change_stations_add_material_box_id.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeStationsAddMaterialBoxId extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('stations', function (Blueprint $table) {
+            $table->bigInteger("material_box_id")->index()->comment("料箱ID");
+            $table->tinyInteger("status")->default(0)->comment("状态");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('stations', function (Blueprint $table) {
+            $table->dropColumn("material_box_id");
+            $table->dropColumn("status");
+        });
+    }
+}

+ 32 - 0
database/migrations/2021_07_19_165143_change_logistics_table_add_tag_column.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeLogisticsTableAddTagColumn extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('logistics', function (Blueprint $table) {
+            $table->string("tag")->nullable()->comment("标签");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('logistics', function (Blueprint $table) {
+            $table->dropColumn("tag");
+        });
+    }
+}

+ 41 - 0
database/migrations/2021_07_28_115218_create_requirements_table.php

@@ -0,0 +1,41 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateRequirementsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('requirements', function (Blueprint $table) {
+            $table->id();
+            $table->integer('user_id')->comment('创建者');
+            $table->decimal('score')->comment('');
+            $table->timestamp('began_at')->nullable()->comment('任务开始时间');
+            $table->timestamp('finished_at')->nullable()->comment('完结时间');
+            $table->text('title')->nullable()->comment('标题');
+            $table->text('content')->nullable()->comment('内容');
+            $table->tinyInteger('status')->comment('状态');
+            $table->softDeletes();
+            $table->timestamps();
+
+            $table->index(['title']);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('requirements');
+    }
+}

+ 33 - 0
database/migrations/2021_07_28_115724_create_requirement_user_table.php

@@ -0,0 +1,33 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateRequirementUserTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('requirement_user', function (Blueprint $table) {
+            $table->id();
+            $table->integer('user_id')->comment('用户ID');
+            $table->integer('requirement_id')->comment('需求ID');
+            $table->decimal('score')->comment('分数');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('requirement_user');
+    }
+}

+ 16 - 0
database/seeds/RequirementSeeder.php

@@ -0,0 +1,16 @@
+<?php
+
+use Illuminate\Database\Seeder;
+
+class RequirementSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        //
+    }
+}

+ 16 - 0
database/seeds/RequirementUserSeeder.php

@@ -0,0 +1,16 @@
+<?php
+
+use Illuminate\Database\Seeder;
+
+class RequirementUserSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        //
+    }
+}

+ 0 - 0
nginx.htaccess


+ 5 - 0
package-lock.json

@@ -5811,6 +5811,11 @@
         "object-visit": "^1.0.0"
       }
     },
+    "marked": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz",
+      "integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA=="
+    },
     "md5": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",

+ 2 - 1
package.json

@@ -29,12 +29,13 @@
     "davidshimjs-qrcodejs": "0.0.2",
     "echarts": "^4.9.0",
     "element-ui": "^2.14.1",
-    "http-vue-loader": "^1.4.2",
     "html2canvas": "^1.0.0-rc.7",
+    "http-vue-loader": "^1.4.2",
     "jquery.cookie": "^1.4.1",
     "js-cookie": "^2.2.1",
     "jsbarcode": "^3.11.3",
     "laravel-echo": "^1.10.0",
+    "marked": "^2.1.3",
     "md5": "^2.3.0",
     "moment": "^2.28.0",
     "pusher-js": "^5.1.1",

+ 18 - 7
public/.htaccess

@@ -1,9 +1,20 @@
-Options +FollowSymLinks -Indexes
-RewriteEngine On
+<IfModule mod_rewrite.c>
+    <IfModule mod_negotiation.c>
+        Options +FollowSymLinks
+    </IfModule>
 
-RewriteCond %{HTTP:Authorization} .
-RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
+    RewriteEngine On
 
-RewriteCond %{REQUEST_FILENAME} !-d
-RewriteCond %{REQUEST_FILENAME} !-f
-RewriteRule ^ index.php [L]
+    # Redirect Trailing Slashes If Not A Folder...
+    RewriteCond %{REQUEST_FILENAME} !-d
+    RewriteRule ^(.*)/$ /$1 [L,R=301]
+
+    # Handle Front Controller...
+    RewriteCond %{REQUEST_FILENAME} !-d
+    RewriteCond %{REQUEST_FILENAME} !-f
+    RewriteRule ^ index.php [L]
+
+    # Handle Authorization Header
+    RewriteCond %{HTTP:Authorization} .
+    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
+</IfModule>

+ 0 - 1
public/index.php

@@ -1,5 +1,4 @@
 <?php
-
 /**
  * Laravel - A PHP Framework For Web Artisans
  *

+ 3 - 0
resources/js/marked.js

@@ -0,0 +1,3 @@
+
+window.marked = require("marked");
+window.$ = window.jQuery = require('jquery');

+ 269 - 0
resources/views/help.blade.php

@@ -0,0 +1,269 @@
+<!DOCTYPE html>
+<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="icon" href="{{asset('icon/faviconc.ico')}}" type="image/x-icon"/>
+
+    <title>系统🎯手册</title>
+    <style>
+        .sidebar {
+            background: #ffffff;
+            line-height: 180%;
+            position: fixed;
+            left: 0;
+            top: 0;
+            border: 1px solid #aaaaaa;
+            width: 20%;
+            height:100%;
+        }
+        .sidebar p {
+            font-size: 18px;
+            color: #15a230;
+            margin: 0 0 0.3rem 0;
+            text-align: right;
+        }
+        .sidebar li{
+            text-indent: 0.5rem;
+            font-size: 14px;
+            list-style: none;
+            border-bottom:1px solid #ced4da;
+        }
+        .sidebar li .nav_item{
+            padding: 3px;
+        }
+        .sidebar li .item_h1{
+            margin-left: 0;
+        }
+        .sidebar li .item_h2{
+            margin-left: 2rem;
+            font-size: 0.8rem;
+        }
+        .sidebar li .item_h3{
+            margin-left: 4rem;
+            font-size: 0.8rem;
+        }
+        .sidebar li .item_h4{
+            margin-left: 5rem;
+            font-size: 0.8rem;
+        }
+        .sidebar li .item_h5{
+            margin-left: 6rem;
+            font-size: 0.8rem;
+        }
+        .sidebar li .item_h6{
+            margin-left: 7rem;
+            font-size: 0.8rem;
+        }
+        .sidebar li .nav_item.current{
+            color: white;
+            background-color: #5cc26f;
+        }
+        .sidebar a:hover {
+            color: #5cc26f;
+        }
+        .sidebar a {
+            text-decoration: none;
+        }
+        .nowrap{white-space:nowrap;}
+        code {
+            border-radius: 6px;
+            background: rgba(0,0,0,.1);
+            color: red;
+            padding: 8px;
+        }
+        kbd {
+            border-radius: 6px;
+            background: rgba(5,1,5,.2);
+            color: #000000;
+            font-weight: bold;
+            padding: 8px;
+        }
+    </style>
+</head>
+<body>
+<div class="sidebar">
+    <div class="AnchorContent nowrap" id="AnchorContent"></div>
+</div>
+<div id="content" style="margin-left: 100px"></div>
+<script src="{{mix("js/marked.js")}}"></script>
+<script>
+    document.getElementById('content').innerHTML = marked("{!! $read !!}");
+</script>
+<script type="text/javascript">
+    let currentIndex = 0;
+    let currentScrollHigh = 0;
+    let currentContentScrollHigh = 0;
+    $(window).on("load",function(){
+        let body = $("body");
+        let content = $("#AnchorContent");
+        let headCounts = [body.find("h1").length, body.find("h2").length, body.find("h3").length, body.find("h4").length,
+            body.find("h5").length, body.find("h6").length];
+        let vH1Tag = null;  // 显示的最高层级
+        let vH2Tag = null;   // 显示的最低层级
+        for(let i = 0; i < headCounts.length; i++){
+            if(headCounts[i] > 0){
+                if(vH1Tag == null)vH1Tag = 'h' + (i + 1);
+                else vH2Tag = 'h' + (i + 1);
+            }
+        }
+        if(vH1Tag == null)return;
+        let vIndexH1 = 0;
+        let vIndexH2 = 0;
+        let vIndexH3 = 0;
+        let vIndexH4 = 0;
+        let vIndexH5 = 0;
+        let vIndexH6 = 0;
+        let headerALL = [];
+        let headerIDALL = [];
+        let headerHeightALL = [];
+        body.find("h1,h2,h3,h4,h5,h6").each(function(i,item){
+            let id = '';
+            let name = '';
+            let tag = $(item).get(0).tagName.toLowerCase();
+            let className = '';
+            switch (tag){
+                case "h1":
+                    id = name = ++vIndexH1;
+                    vIndexH2 = 0;
+                    vIndexH3 = 0;
+                    vIndexH4 = 0;
+                    vIndexH5 = 0;
+                    vIndexH6 = 0;
+                    className = 'item_h1';
+                    break;
+                case "h2":
+                    id = vIndexH1 + '_' + ++vIndexH2;
+                    name = vIndexH1 + '.' + vIndexH2;
+                    className = 'item_h2';
+                    vIndexH3 = 0;
+                    vIndexH4 = 0;
+                    vIndexH5 = 0;
+                    vIndexH6 = 0;
+                    break;
+                case "h3":
+                    id = vIndexH1 + '_' + vIndexH2+ '_' + ++vIndexH3;
+                    name = vIndexH1 + '.' + vIndexH2+ '.' + +vIndexH3;
+                    className = 'item_h3';
+                    vIndexH4 = 0;
+                    vIndexH5 = 0;
+                    vIndexH6 = 0;
+                    break;
+                case "h4":
+                    id = vIndexH1 + '_' + vIndexH2+ '_'  +vIndexH3 +'_'+ ++vIndexH4 ;
+                    name =  vIndexH1 + '.' + vIndexH2+ '.'  +vIndexH3 +'.'+  vIndexH4 ;
+                    className = 'item_h4';
+                    vIndexH5 = 0;
+                    vIndexH6 = 0;
+                    break;
+                case "h5":
+                    id = vIndexH1 + '_' + vIndexH2+ '_'  +vIndexH3 +'_' +vIndexH4+'_'+ ++vIndexH5;
+                    name = vIndexH1 + '.' + vIndexH2+ '.'  +vIndexH3 +'.' +vIndexH4+'.'+ vIndexH5;
+                    className = 'item_h5';
+                    vIndexH6 = 0;
+                    break;
+                case "h6":
+                    id = vIndexH1 + '_' + vIndexH2+ '_'  +vIndexH3 +'_' +vIndexH4+'_' +vIndexH5+'_'+ ++vIndexH6;
+                    name = vIndexH1 + '.' + vIndexH2+ '.'  +vIndexH3 +'.' +vIndexH4+'.' +vIndexH5+'.'+ vIndexH6;
+                    className = 'item_h6';
+                    break;
+            }
+            if(name.length > 2){
+                let mFirstName = name.substring(0,2);
+                while(mFirstName === "0."){
+                    name = name.substring(2,name.length);
+                    mFirstName = name.substring(0,2);
+                }
+            }
+            $(item).attr("id","wow"+id+"_index_"+i);
+            $(item).addClass("wow_head");
+            content.css('max-height', ($(document).height()) + 'px');
+            content.css('height', ($(window).height()) + 'px');
+            content.css('overflow','auto');
+            content.append('<li><a class="nav_item '+className+' anchor-link"  href="#wow'+id+'_index_'+i+'" link="#wow'+id+'" index="'+i+'">'+name+" "+$(this).text()+" "+'</a></li>');
+            let str = "#wow"+id+"_index_"+i;
+            headerALL.push($(item));
+            headerIDALL.push(str);
+        });
+        $(".anchor-link").click(function(){
+            let index  = $(this).attr("index");
+            $(".sidebar li .nav_item.current").removeClass('current');
+            $(headerNavs[index]).addClass('current');
+            currentScrollHigh = $(window).scrollTop();
+            currentContentScrollHigh = headerHeightALL[index];
+            currentIndex = headerTops[index];
+        });
+        let headerNavs = $(".sidebar li .nav_item");
+        let headerTops = [];
+        $(".wow_head").each(function(i, n){
+            headerTops.push($(n).offset().top);
+        });
+        headerTops.push($(document).height());
+        window.onresize = function(){
+            headerTops = [];
+            $.each(headerNavs, function(i, n){
+                    $(n).trigger("click");
+                    document.querySelector(headerIDALL[i]).scrollIntoView(true);
+                    let scrollTop = $(window).scrollTop();
+                    headerTops.push(scrollTop);
+                }
+            );
+            headerTops.push($(document).height());
+            content.css('height', ($(window).height()) + 'px');
+            let xcontentWidth =  content.width();
+            let xWidth = $(window).width();
+            let xlength = xWidth - xcontentWidth;
+            body.css("marginLeft",xcontentWidth+'px');
+            body.css("max-width",xlength);
+            $(headerNavs[currentIndex]).trigger("click");
+        }
+        $(window).scroll(function(){
+            let scrollTop = $(window).scrollTop(); // 获得将要到达的点离顶距离
+            $.each(headerTops, function(i, n){
+                    if( (scrollTop >= (headerTops[i])  && scrollTop < (headerTops[i+1] -1))  ){
+                        $(".sidebar li .nav_item.current").removeClass('current');
+                        $(headerNavs[i]).addClass('current');
+                        currentScrollHigh = scrollTop;
+                        currentContentScrollHigh = headerHeightALL[i];
+                        currentIndex = i;
+                        let mscrollTop1 = content.scrollTop();  // 当前标签的高度
+                        if((currentContentScrollHigh - mscrollTop1)>  ($(window).height()/2)){
+                            content.animate({scrollTop: (currentContentScrollHigh)}, 10);
+                        } else if( ( mscrollTop1 - currentContentScrollHigh )>  0 ){
+                            content.animate({scrollTop: currentContentScrollHigh-(content.height()/3)}, 10);
+                        }
+                        return false;
+                    }
+                }
+            );
+            if(scrollTop === 0){
+                content.animate({scrollTop: 0}, 10);
+            }
+            if(scrollTop === $(document).height()){
+                content.animate({scrollTop: headerHeightALL[headerHeightALL.length-1]}, 10);
+            }
+        });
+        $.each(headerNavs, function(i, n){
+                headerHeightALL.push($(n).offset().top);
+            }
+        );
+        headerTops = [];
+        $.each(headerNavs, function(i, n){
+                $(n).trigger("click");
+                document.querySelector(headerIDALL[i]).scrollIntoView(true);
+                let scrollTop = $(window).scrollTop();
+                headerTops.push(scrollTop);
+            }
+        );
+        headerTops.push($(document).height());
+        $(headerNavs[0]).trigger("click");
+        document.querySelector(headerIDALL[0]).scrollIntoView(true);
+        let xcontentWidth =  content.width();
+        let xWidth = $(window).width();
+        let xlength = xWidth - xcontentWidth;
+        body.css("marginLeft",xcontentWidth+'px');
+        body.css("max-width",xlength);
+    });
+</script>
+</body>
+</html>

+ 27 - 3
resources/views/inventory/stockInventory/inventoryMission.blade.php

@@ -45,8 +45,7 @@
                 <button class="btn btn-sm btn-info" @click="新增盘点记录()" :class="listMode?'btn-dark':'btn-outline-dark'" v-if="!listMode&&!addInventoryMission">新增盘点记录</button>
                  <button class="btn btn-sm" @click="收起新增()" :class="addInventoryMission?'btn-dark':'btn-outline-dark'" v-if="addInventoryMission">收起新增</button>
             </span>
-
-
+            <button class="btn btn-sm btn-success" @click="outToULine()" v-if="!listMode&&materialBoxCodes">出库</button>
             <span class="form-group  mb-5">
             <label class="text-muted">货主:</label><span class="font-weight-bold">@{{ inventory.owner.name }}</span>
         </span>
@@ -715,7 +714,8 @@
                     scanEndInputted:false,binDisable:false,barcodeDisable:true,amountDisable:false,
                 },
                 goodses:[],
-                selectTr:''
+                selectTr:'',
+                materialBoxCodes:'',
             },
             beforeMount: function () {
                 this.重排序并标记全列表类型();
@@ -770,8 +770,32 @@
                     _this.listMode = false;
                 })();
                 _this.建立记录索引();
+                _this.inventoryMissions.forEach(function (inventoryMission){
+                    if (inventoryMission.location.indexOf('IDE')>-1){
+                        _this.materialBoxCodes += inventoryMission.location + ','
+                    }
+                });
+                if (_this.materialBoxCodes.length > 0) {
+                    _this.materialBoxCodes = _this.materialBoxCodes.substr(0,_this.materialBoxCodes.length - 1);
+                }
             },
             methods:{
+                outToULine(){
+                    if(!confirm('确定要将当前盘点任务涉及的IDE料箱号出至输送线吗?')){return;}
+                    let _this=this;
+                    let text = _this.materialBoxCodes;
+                    if(!text){
+                        alert('当前盘点任务未查询到IDE料箱号!')
+                        return
+                    }
+                    console.log(text)
+                    axios.post('{{url('/api/thirdPart/haiq/storage/takeOutToULine')}}',{codes:text})
+                        .then(function(response){
+                            tempTip.okWindow(response.data.result,'确定')
+                        }).catch(function(err){
+                        tempTip.okWindow(err,'确定')
+                    })
+                },
                 checkAll(e) {
                     if (e.target.checked) {
                         this.inventoryMissions.forEach((el,i)=>{

+ 21 - 1
resources/views/maintenance/logistic/create.blade.php

@@ -2,7 +2,7 @@
 @section('title')录入-承运商@endsection
 
 @section('content')
-    <div class="container-fluid">
+    <div class="container-fluid" id="container">
         <div class="card col-md-8 offset-md-2">
             <div class="card-body">
                 @if(Session::has('successTip'))
@@ -93,6 +93,15 @@
                                    name="belong_company" autocomplete="off" value="{{ old('belong_company') }}" >
                         </div>
                     </div>
+                    <div class="form-group row">
+                        <label for="tag" class="col-2 col-form-label text-right">标签</label>
+                        <div class="col-8">
+                            <select id="tag" class="selectpicker" multiple title="标签(多选)" v-model="tag">
+                                @foreach(\App\Logistic::TAGS as $key=>$tag)<option value="{{$key}}">{{$tag}}</option>@endforeach
+                            </select>
+                            <input hidden name="tag" :value="tag"></input>
+                        </div>
+                    </div>
                     <div class="form-group row">
                         <label for="remark" class="col-2 col-form-label text-right">备注</label>
                         <div class="col-8">
@@ -110,3 +119,14 @@
         </div>
     </div>
 @endsection
+
+@section("lastScript")
+    <script>
+        new Vue({
+            el:"#container",
+            data:{
+                tag:[]
+            },
+        });
+    </script>
+@endsection

+ 30 - 11
resources/views/maintenance/logistic/edit.blade.php

@@ -2,19 +2,19 @@
 @section('title')编辑-承运商@endsection
 
 @section('content')
-    <div class="container-fluid">
+    <div class="container-fluid" id="container">
         <div class="card">
             <div class="card-body">
                 @if(Session::has('successTip'))
                     <div class="alert alert-success h1">{{Session::get('successTip')}}!</div>
                 @endif
-                <form method="POST" action='{{url("maintenance/logistic/{$logistic->id}")}}'>
+                <form method="POST" action='{{url("maintenance/logistic/{$logistic["id"]}")}}'>
                     @csrf
                     @method('PUT')
                     <div class="form-group row">
                         <label for="type" class="col-2 col-form-label text-right">承运商类型 <b class="text-danger">*</b></label>
                         <div class="col-5">
-                            <select id="type" name="type" class="form-control @error('type') is-invalid @enderror" value="@if(old('type')){{old('type')}}@else{{$logistic->type}}@endif" required>
+                            <select id="type" name="type" class="form-control @error('type') is-invalid @enderror" value="@if(old('type')){{old('type')}}@else{{$logistic["type"]}}@endif" required>
                                 <option value="快递">快递</option>
                                 <option value="物流">物流</option>
                                 <option value="全部">全部</option>
@@ -30,7 +30,7 @@
                         <label for="name" class="col-2 col-form-label text-right">承运商名称 <b class="text-danger">*</b></label>
                         <div class="col-8">
                             <input type="text" class="form-control @error('name') is-invalid @enderror"
-                                   name="name" autocomplete="off" value="@if(old('name')){{old('name')}}@else{{$logistic->name}}@endif" required>
+                                   name="name" autocomplete="off" value="@if(old('name')){{old('name')}}@else{{$logistic["name"]}}@endif" required>
                             @error('name')
                             <span class="invalid-feedback" role="alert">
                                 <strong>{{ $message }}</strong>
@@ -42,14 +42,14 @@
                         <label for="english_name" class="col-2 col-form-label text-right">承运商英文名称</label>
                         <div class="col-8">
                             <input id="english_name" type="text" class="form-control"
-                                   name="english_name" autocomplete="off" value="@if(old('name')){{old('name')}}@else{{$logistic->name}}@endif" >
+                                   name="english_name" autocomplete="off" value="@if(old('name')){{old('name')}}@else{{$logistic["name"]}}@endif" >
                         </div>
                     </div>
                     <div class="form-group row">
                         <label for="code" class="col-2 col-form-label text-right">承运商代码 <b class="text-danger">*</b></label>
                         <div class="col-8">
                             <input type="text" class="form-control @error('code') is-invalid @enderror"
-                                   name="code" autocomplete="off" value="@if(old('code')){{old('code')}}@else{{$logistic->code}}@endif" required>
+                                   name="code" autocomplete="off" value="@if(old('code')){{old('code')}}@else{{$logistic["code"]}}@endif" required>
                             @error('code')
                             <span class="invalid-feedback" role="alert">
                                 <strong>{{ $message }}</strong>
@@ -60,14 +60,14 @@
                     <div class="form-group row">
                         <label for="is_bunched" class="col-2 col-form-label text-right">是否子母单</label>
                         <div class="col-8">
-                            <input id="is_bunched" type="checkbox" name="is_bunched" class="switch" @if(old('is_bunched') ?? $logistic->is_bunched=='Y') checked @endif>
+                            <input id="is_bunched" type="checkbox" name="is_bunched" class="switch" @if(old('is_bunched') ?? $logistic["is_bunched"]=='Y') checked @endif>
                         </div>
                     </div>
                     <div class="form-group row">
                         <label for="mobile" class="col-2 col-form-label text-right">承运商电话</label>
                         <div class="col-8">
                             <input id="mobile" type="text" class="form-control @error('mobile') is-invalid @enderror"
-                                   name="mobile" autocomplete="off" value="@if(old('mobile')){{old('mobile')}}@else{{$logistic->mobile}}@endif" >
+                                   name="mobile" autocomplete="off" value="@if(old('mobile')){{old('mobile')}}@else{{$logistic["mobile"]}}@endif" >
                             @error('mobile')
                             <span class="invalid-feedback" role="alert">
                                 <strong>{{ $errors->first('mobile') }}</strong>
@@ -79,7 +79,7 @@
                         <label for="delivery_fee" class="col-2 col-form-label text-right">送货费</label>
                         <div class="col-8">
                             <input id="delivery_fee" type="text" class="form-control @error('delivery_fee') is-invalid @enderror"
-                                   name="delivery_fee" autocomplete="off" value="@if(old('delivery_fee')){{old('delivery_fee')}}@else{{$logistic->delivery_fee}}@endif" >
+                                   name="delivery_fee" autocomplete="off" value="@if(old('delivery_fee')){{old('delivery_fee')}}@else{{$logistic["delivery_fee"]}}@endif" >
                             @error('delivery_fee')
                             <span class="invalid-feedback" role="alert">
                                 <strong>{{ $errors->first('delivery_fee') }}</strong>
@@ -91,14 +91,23 @@
                         <label for="belong_company" class="col-2 col-form-label text-right">隶属公司</label>
                         <div class="col-8">
                             <input id="belong_company" type="text" class="form-control "
-                                   name="belong_company" autocomplete="off" value="@if(old('belong_company')){{old('belong_company')}}@else{{$logistic->belong_company}}@endif" >
+                                   name="belong_company" autocomplete="off" value="@if(old('belong_company')){{old('belong_company')}}@else{{$logistic["belong_company"]}}@endif" >
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="tag" class="col-2 col-form-label text-right">标签</label>
+                        <div class="col-8">
+                            <select id="tag" class="selectpicker" multiple title="标签(多选)" v-model="tag">
+                                @foreach(\App\Logistic::TAGS as $key=>$tag)<option value="{{$key}}">{{$tag}}</option>@endforeach
+                            </select>
+                            <input hidden name="tag" :value="tag"></input>
                         </div>
                     </div>
                     <div class="form-group row">
                         <label for="remark" class="col-2 col-form-label text-right">备注</label>
                         <div class="col-8">
                             <textarea id="remark" type="text" class="form-control "
-                                      name="remark" autocomplete="off" >@if(old('remark')){{old('remark')}}@else{{$logistic->remark}}@endif</textarea>
+                                      name="remark" autocomplete="off" >@if(old('remark')){{old('remark')}}@else{{$logistic["remark"]}}@endif</textarea>
                         </div>
                     </div>
                     <div class="form-group row">
@@ -111,3 +120,13 @@
         </div>
     </div>
 @endsection
+@section("lastScript")
+    <script>
+        new Vue({
+            el:"#container",
+            data:{
+                tag:"{{$logistic["tag"]}}".split(","),
+            },
+        });
+    </script>
+@endsection

+ 3 - 0
resources/views/maintenance/logistic/index.blade.php

@@ -18,6 +18,7 @@
                         <th>承运商类型</th>
                         <th>承运商送货费</th>
                         <th>隶属公司</th>
+                        <th>标签</th>
                         <th>备注</th>
                         <th>创建时间</th>
                         <th>操作</th>
@@ -31,6 +32,7 @@
                         <td>@{{logistic.type}}</td>
                         <td>@{{logistic.delivery_fee}}</td>
                         <td>@{{logistic.belong_company}}</td>
+                        <td>@{{logistic.tag}}</td>
                         <td>@{{logistic.remark}}</td>
                         <td class="text-muted">@{{logistic.created_at}}</td>
                         <td>
@@ -56,6 +58,7 @@
                     @foreach( $logistics as $logistic )
                     {id:'{{$logistic->id}}',name:'{{$logistic->name}}',code:'{{$logistic->code}}',
                         mobile:"{{$logistic->mobile}}",type:"{{$logistic->type}}",delivery_fee:"{{$logistic->delivery_fee}}",
+                        tag:"{{$logistic->tag}}",
                         remark:"{{$logistic->remark}}",belong_company:"{{$logistic->belong_company}}",created_at:'{{$logistic->created_at}}',is_bunched:"{{$logistic->is_bunched}}"},
                     @endforeach
                 ],

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio