ソースを参照

Merge branch 'master' into zengjun

# Conflicts:
#	app/Providers/AppServiceProvider.php
ajun 4 年 前
コミット
bb4d6cfb6b
47 ファイル変更2361 行追加325 行削除
  1. 14 0
      app/Console/Commands/stubs/model.stub
  2. 15 0
      app/Console/Commands/stubs/test.controller.stub
  3. 37 0
      app/Console/Commands/stubs/test.service.stub
  4. 27 0
      app/DepartmentObligationOwner.php
  5. 17 2
      app/Http/Controllers/CustomerController.php
  6. 18 0
      app/Http/Controllers/KpiController.php
  7. 6 19
      app/Http/Controllers/OrderController.php
  8. 126 0
      app/Http/Controllers/ReplenishmentController.php
  9. 3 1
      app/Http/Controllers/StoreBlindReceiveController.php
  10. 145 0
      app/Http/Controllers/StoreCountGoodsAndReceiveController.php
  11. 72 181
      app/Http/Controllers/TestController.php
  12. 34 22
      app/Http/Controllers/WaveController.php
  13. 22 22
      app/Http/Controllers/api/thirdPart/haochuang/SortingController.php
  14. 19 0
      app/Http/Requests/OrderDelivering.php
  15. 45 0
      app/Jobs/BroadcastBatchToZhengCangJob.php
  16. 2 0
      app/Jobs/LaborApplyRecordJob.php
  17. 21 0
      app/Obligation.php
  18. 1 1
      app/OracleBasSKU.php
  19. 7 0
      app/OracleDOCASNDetail.php
  20. 7 0
      app/Owner.php
  21. 4 0
      app/Providers/AppServiceProvider.php
  22. 1 5
      app/Services/ForeignZhenCangService.php
  23. 1 1
      app/Services/HandInStorageService.php
  24. 5 2
      app/Services/LaborApplyService.php
  25. 114 0
      app/Services/ObligationService.php
  26. 60 4
      app/Services/OwnerService.php
  27. 184 0
      app/Services/ReplenishmentService.php
  28. 12 5
      app/Services/StoreItemService.php
  29. 3 2
      composer.json
  30. 63 3
      composer.lock
  31. 65 6
      resources/views/customer/project/create.blade.php
  32. 25 5
      resources/views/customer/project/index.blade.php
  33. 49 7
      resources/views/customer/project/part/_two.blade.php
  34. 141 0
      resources/views/inventory/stockOut/index.blade.php
  35. 174 0
      resources/views/kpi/day/index.blade.php
  36. 186 0
      resources/views/kpi/month/index.blade.php
  37. 2 2
      resources/views/order/wave/_printBody.blade.php
  38. 5 0
      resources/views/order/wave/_split.blade.php
  39. 41 19
      resources/views/order/wave/picking.blade.php
  40. 10 6
      resources/views/order/wave/search.blade.php
  41. 1 1
      resources/views/personnel/laborApply/create.blade.php
  42. 1 1
      resources/views/personnel/laborApply/dispatch/index.blade.php
  43. 1 1
      resources/views/personnel/laborApply/index.blade.php
  44. 12 7
      resources/views/personnel/laborReport/index.blade.php
  45. 31 0
      resources/views/store/countGoodsAndReceive/excel.blade.php
  46. 516 0
      resources/views/store/countGoodsAndReceive/index.blade.php
  47. 16 0
      routes/web.php

+ 14 - 0
app/Console/Commands/stubs/model.stub

@@ -0,0 +1,14 @@
+<?php
+
+namespace {{ namespace }};
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class {{ class }} extends Model
+{
+    use ModelLogChanging;
+
+    //
+}

+ 15 - 0
app/Console/Commands/stubs/test.controller.stub

@@ -0,0 +1,15 @@
+<?php
+
+namespace {{ namespace }};
+
+use Tests\TestCase;
+
+class {{ class }} extends TestCase
+{
+
+    public function testExample()
+    {
+    {{ class }};
+        $this->assertTrue(true);
+    }
+}

+ 37 - 0
app/Console/Commands/stubs/test.service.stub

@@ -0,0 +1,37 @@
+<?php
+
+namespace {{ namespace }};
+use App\Services\{{ serviceName }};
+use Tests\TestCase;
+use App\{{ modelNameUc }};
+use App\Traits\TestMockSubServices;
+
+class {{ class }} extends TestCase
+{
+    use TestMockSubServices;
+    /** @var {{ serviceName }} $service */
+    public $service;
+    private $data;
+    private $amount=2;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('{{ serviceName }}');
+        $this->data['{{ modelNamePlural }}']
+            = factory({{ modelNameUc }}::class, $this->amount)
+            ->create();
+    }
+
+    public function testReturned()
+    {
+        $this->assertTrue(true);
+    }
+
+    function tearDown(): void
+    {
+        {{ modelNameUc }}::query()
+            ->whereIn('id',data_get($this->data['{{ modelNamePlural }}'],'*.id')??[])
+            ->delete();
+        parent::tearDown();
+    }
+}

+ 27 - 0
app/DepartmentObligationOwner.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class DepartmentObligationOwner extends Model
+{
+    use ModelLogChanging;
+
+    use ModelTimeFormat;
+    public $timestamps=false;
+
+    protected $table='department_obligation_owner';
+
+    protected $fillable=[
+        'department_id','obligation_id', 'owner_id', 'valid_time','create_time', 'update_time','delete_flag','failure_time'
+    ];
+
+    public function department()
+    {   //面积报表
+        return $this->hasOne(UserWorkgroup::class,"id","department_id");
+    }
+}

+ 17 - 2
app/Http/Controllers/CustomerController.php

@@ -20,6 +20,7 @@ use App\OwnerFeeStorage;
 use App\OwnerPriceSystem;
 use App\OwnerReport;
 use App\Services\LogService;
+use App\Services\ObligationService;
 use App\Services\OwnerAreaReportService;
 use App\Services\OwnerBillReportService;
 use App\Services\OwnerReportService;
@@ -100,8 +101,9 @@ class CustomerController extends Controller
         if(!Gate::allows('项目管理-项目-查询')){ return redirect('denied');  }
         /** @var OwnerService $service */
         $service = app('OwnerService');
-        $owners = $service->paginate(request()->input(),['customer',"userOwnerGroup","userWorkGroup",
+        $owners = $service->paginate(request()->input(),['customer',"userOwnerGroup","userWorkGroup",'departmentObligationOwner.department',
             "ownerStoragePriceModels","storageAudit","operationAudit","expressAudit","logisticAudit","directLogisticAudit","systemAudit"]);
+        $owners=app('OwnerService')->combineOwners($owners);
         $models = app('OwnerService')->getIntersectPermitting();
         $customers = app('CustomerService')->getSelection();
         $ownerGroups = app('UserOwnerGroupService')->getSelection();
@@ -186,6 +188,9 @@ class CustomerController extends Controller
             "subjection"            => request("subjection"),
             "is_tax_exist"          => request("is_tax_exist") ? 'Y' : 'N',
         ]);
+        /** @var ObligationService $service*/
+        $service= app('ObligationService');
+        $owner=$service->createOrUpdate(request()->input());
         $this->success($owner);
     }
 
@@ -205,7 +210,17 @@ class CustomerController extends Controller
     {
         if(!Gate::allows('项目管理-项目-编辑')){ return redirect('denied');  }
         /** @var Owner $owner */
-        $owner = app('OwnerService')->find($id);
+        $owner = app('OwnerService')->find($id,['departmentObligationOwner']);
+        $departmentObligationOwner=$owner->departmentObligationOwner??[];
+        if (count($departmentObligationOwner)>0){
+            foreach ($departmentObligationOwner as $item){
+                if ($item->obligation_code=='kc')$owner->kc=$item->department_id;
+                if ($item->obligation_code=='jg')$owner->jg=$item->department_id;
+                if ($item->obligation_code=='th')$owner->th=$item->department_id;
+                if ($item->obligation_code=='sh')$owner->sh=$item->department_id;
+                if ($item->obligation_code=='fh')$owner->fh=$item->department_id;
+            }
+        }
         $owner->loadCount(["ownerStoragePriceModels","ownerPriceOperations","ownerPriceExpresses","ownerPriceLogistics","ownerPriceDirectLogistics","ownerPriceSystem"]);
         $isExist = false;
         /** @var \stdClass $owner */

+ 18 - 0
app/Http/Controllers/KpiController.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+
+class KpiController extends Controller
+{
+    public function monthIndex(Request $request)
+    {
+        return view('kpi.month.index');
+    }
+
+    public function dayIndex(Request $request)
+    {
+        return view('kpi.day.index');
+    }
+}

+ 6 - 19
app/Http/Controllers/OrderController.php

@@ -4,20 +4,17 @@ namespace App\Http\Controllers;
 
 use App\Components\Database;
 use App\Http\Requests\OrderDelivering;
-use App\OracleActAllocationDetails;
 use App\OracleDOCOrderHeader;
 use App\OracleDOCWaveDetails;
 use App\OrderIssueType;
-use App\OrderPackage;
 use App\Services\LogisticService;
 use App\Services\LogService;
 use App\Services\OrderPackageService;
 use App\Services\OrderService;
 use App\Services\RejectedBillItemService;
 use App\Services\RejectedBillService;
-use Illuminate\Database\Eloquent\Builder;
+use GuzzleHttp\Exception\GuzzleException;
 use Illuminate\Http\Request;
-use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Gate;
@@ -33,21 +30,6 @@ class OrderController extends Controller
         /** @var OrderService $orderService */
         $orderService = app('OrderService');
         $request = $request->input();
-        if (!app("UserService")->checkAdminIdentity(Auth::id())){
-            $owners = app('OwnerService')->getIntersectPermitting(['id', 'code']);
-            $codes = array_column($owners->toArray(), 'code');
-            if ($request['customerid'] ?? false) {
-                $arr = explode(',', $request['customerid']);
-                $request['customerid'] = [];
-                foreach ($arr as $value) {
-                    if (in_array($value, $codes)) $request['customerid'][] = $value;
-                }
-                if (count($request['customerid']) < 1) $request['customerid'] = [''];
-            } else $request['customerid'] = $codes;
-        }else if (isset($request['customerid'])){
-            $request['customerid'] = explode(',', $request['customerid']);
-            if ($request['customerid']<0)unset($request['customerid']);
-        }
         $service = app(LogisticService::class);
         $logistics = $service->getSelection(['id', 'name']);
         $result = $orderService->paginate($request);
@@ -64,6 +46,10 @@ class OrderController extends Controller
     }
 
     //导出
+
+    /**
+     * @throws \Exception|GuzzleException
+     */
     public function export(Request $request)
     {
         $is_merge = $request->is_merge ?? false;
@@ -74,6 +60,7 @@ class OrderController extends Controller
         if ($request->data) {
             $req["sql"] = $orderService->getSql(['data' => $request->data]);
         } else {
+            new OrderDelivering();
             $req["sql"] = $orderService->getSql($request->input());
         }
         $e = new Export();

+ 126 - 0
app/Http/Controllers/ReplenishmentController.php

@@ -0,0 +1,126 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\AsyncResponse;
+use App\Owner;
+use App\Services\ReplenishmentService;
+use Illuminate\Http\Request;
+use Oursdreams\Export\Export;
+
+class ReplenishmentController extends Controller
+{
+    use AsyncResponse;
+
+    public function getReplenishmentInfoByCustomer(Request $request)
+    {
+        $this->gate("库存管理-补货列表");
+        $customer = $request->input('customer');
+        if (!$customer) $this->error('请选择指定货主!');
+        $orders = $this->getOrders($customer);
+        $orders = array_filter($orders,function($item){
+            return $item['amount'] > 0;
+        });
+        if (count($orders) > 0) $this->success($orders);
+        else $this->error('未查询到相应信息!');
+
+
+    }
+
+
+    public function index(Request $request)
+    {
+        $this->gate("库存管理-补货列表");
+        /** @var UserService $userService */
+        $userService = app('UserService');
+        $owners = Owner::query()->whereIn('id', $userService->getPermittingOwnerIds(auth()->user()))->get();
+        return view('inventory.stockOut.index', compact('owners'));
+    }
+
+    public function export(Request $request)
+    {
+        $this->gate("库存管理-补货列表");
+
+        $customer = $request->input('customer');
+        $orders = array_filter($this->getOrders($customer),function($item){
+            return $item['amount'] > 0;
+        });
+        $row = [
+            '货主',
+            '商品名称',
+            '商品条码',
+            '拣货库位',
+            '缺货数',
+            '存储库位',
+            '数量',
+            '批次号'
+        ];
+        $json = [];
+
+        foreach ($orders as $order) {
+            $eaLocation = '';
+            $rsLocation = '';
+            $qty = '';
+            $lot = '';
+
+            foreach ($order['eaLocation'] as $v) {
+                $eaLocation .= $v . "\r\n";
+            }
+
+            foreach ($order['rsLocation'] as $v) {
+                $rsLocation .= $v['location'] ."\r\n";
+            }
+            foreach ($order['rsLocation'] as $v) {
+                $qty .= $v['qty'] ."\r\n";
+            }
+            foreach ($order['rsLocation'] as $v) {
+                $lot .= $v['lot'] ."\r\n";
+            }
+
+            $data = [
+                $order['customerid'],
+                $order['sku'],
+                $order['alternate_sku1'],
+                $eaLocation,
+                $order['amount'],
+                $rsLocation,
+                $qty,
+                $lot,
+            ];
+            $json[] = $data;
+        }
+        return Export::make($row, $json, "库存管理-补货列表");
+    }
+
+    /**
+     * @param $customer
+     * @return array
+     */
+    private function getOrders($customer): array
+    {
+        /** @var ReplenishmentService $service */
+        $service = app('ReplenishmentService');
+        $orders = $service->getOrderInfoRecentMonthByCustomer($customer);
+        $skuArr = array_diff(array_unique(data_get($orders, '*.sku')), ['', '*', null]);
+        $info = $service->getEaInventoryByCustomerAndSku($customer, $skuArr);
+        $rsInfo = $service->getRsInventoryByCustomerAndSku($customer, $skuArr);
+
+        //将整合后拣货位信息 结合订单汇总
+        foreach ($orders as &$order) {
+            if (isset($info[$order['sku']])) {
+                $item = $info[$order['sku']];
+                $order['amount'] = ($order['amount'] - $item['qty']);
+                $order['eaLocation'] = $item['locationid'];
+            } else {
+                $order['eaLocation'] = [];
+            }
+            if (isset($rsInfo[$order['sku']])) {
+                $rsItem = $rsInfo[$order['sku']];
+                $order['rsLocation'] = $rsItem['locationid'];
+            } else {
+                $order['rsLocation'] = [];
+            }
+        }
+        return $orders;
+    }
+}

+ 3 - 1
app/Http/Controllers/StoreBlindReceiveController.php

@@ -12,7 +12,9 @@ class StoreBlindReceiveController extends Controller
 {
     public function index()
     {
-        $excels=InventoryBlindReceiveExcel::orderBy('id','desc')->get();
+        $excels=InventoryBlindReceiveExcel::query()
+            ->where('name','not like','清点%')
+            ->orderByDesc('id')->get();
         return view('store.blindReceive.excel.index',['excels'=>$excels]);
     }
     public function create()

+ 145 - 0
app/Http/Controllers/StoreCountGoodsAndReceiveController.php

@@ -0,0 +1,145 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\AsyncResponse;
+use App\Exports\InventoryBlindReceiveExcelExport;
+use App\InventoryBlindReceiveExcel;
+use App\OracleDOCASNDetail;
+use App\Services\HandInStorageService;
+use Carbon\Carbon;
+use Doctrine\DBAL\Exception;
+use Doctrine\DBAL\Exception\DatabaseObjectExistsException;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
+use Maatwebsite\Excel\Facades\Excel;
+
+class StoreCountGoodsAndReceiveController extends Controller
+{
+    use AsyncResponse;
+
+    public function index()
+    {
+        /** @var HandInStorageService $handInStorageService  */
+        $handInStorageService=app('HandInStorageService');
+        $qualityStatus=$handInStorageService->getQualityStatus();
+        $attributeLocations=$handInStorageService->getAttributeLocation();
+        return view('store.countGoodsAndReceive.index',
+            compact('qualityStatus','attributeLocations'));
+    }
+    public function excel()
+    {
+        $excels=InventoryBlindReceiveExcel::query()
+            ->where('name','like','清点%')
+            ->orderByDesc('id')->get();
+        return view('store.countGoodsAndReceive.excel',['excels'=>$excels]);
+    }
+
+    public function createExcel(Request $request): array
+    {
+        $goodses=$request->input('goodses')??'';
+        $excelFileName=$request->input('filename')??'';
+        if(!$goodses||!is_array($goodses)||count($goodses)==0){
+            return ['result'=>'failure','fail_info'=>'没有数据提交!'];
+        }
+        $goodsExcelArray=[['条码','数量','箱号']];
+        foreach ($goodses as $goods){
+            array_push($goodsExcelArray,[$goods['barcode'],$goods['amount'],$goods['cast_number']]);
+        }
+        $fileName=Carbon::now()->toDateTimeLocalString().'.xlsx';
+        $fileName = str_replace( ':', '_',$fileName);
+        $goodsNeateningExcel = new InventoryBlindReceiveExcel(['file' => $fileName, 'goods_amount' => count($goodses), 'name'=>'清点_'.$excelFileName]);
+        $goodsNeateningExcel->save();
+        Excel::store(new InventoryBlindReceiveExcelExport($goodsExcelArray),$fileName,'public');
+        $this->removeExpiredExcel();
+        return ['result'=>'success'];
+    }
+    private function removeExpiredExcel(){
+        $excels=InventoryBlindReceiveExcel::query()->where('created_at','<',Carbon::now()->subDays(100)->toDateTimeString())->get();
+        $excels->each(
+            /** @throws \Exception */
+            function(InventoryBlindReceiveExcel $excel){
+            $excel->delete();
+        });
+    }
+
+    public function getReceiveTaskByAsnNoAndBarcodes(Request $request)
+    {
+        $asnno=$request->input('asnno');
+        $goods=$request->input('goods');
+        $asnDetails=OracleDOCASNDetail::query()
+            ->select('asnno','asnlineno','customerid','sku','expectedqty','receivedqty_each',
+                'lotatt01','lotatt02','lotatt03','lotatt04','lotatt05','lotatt08')
+            ->with('basSku.lotId')
+            ->where('asnno',$asnno)
+            ->whereIn('linestatus', ['00', '30'])
+            ->get();
+        $status=false;
+       foreach ($goods as &$good){
+           foreach ($asnDetails as $asnDetail){
+               if (!$asnDetail['basSku']??false)continue;
+               if ($good['sku']==$asnDetail['basSku']['alternate_sku1']
+               ||$good['sku']==$asnDetail['basSku']['alternate_sku2']
+               ||$good['sku']==$asnDetail['basSku']['alternate_sku3']){
+                   $good['basSku']=$asnDetail['basSku'];
+                   $good['customerid']=$asnDetail['customerid'];
+                   $good['asn_amount']=($asnDetail['expectedqty']-$asnDetail['receivedqty_each']);
+                   $good['diff_val']=($good['asn_amount']-$good['amount']);
+                   $good['receiveStatus']=true;
+                   $status=true;
+                   $good['asnlineno']=$asnDetail['asnlineno'];
+                   $good['lotatt01']=$asnDetail['lotatt01'];
+                   $good['lotatt02']=$asnDetail['lotatt02'];
+                   $good['lotatt03']=$asnDetail['lotatt03'];
+                   $good['lotatt04']=$asnDetail['lotatt04'];
+                   $good['lotatt05']=$asnDetail['lotatt05'];
+                   $good['lotatt08']=$asnDetail['lotatt08'];
+               }
+           }
+       }
+       if ($status)$this->success($goods);
+        else $this->error('当前ASN单号未查询到下述商品信息!');
+    }
+
+    public function fluxReceive(Request $request)
+    {
+        $info=$request->input('good');
+        $isSku=$info['sku']??false;
+        if ($info['lotatt02']&&Carbon::now()->gt($info['lotatt02']))$this->error('失效日期超过入库效期');
+        if (!$info['customerid']||$isSku===false||!$info['asnno']) $this->error('参数错误');
+        /** @var HandInStorageService $handInStorageService  */
+        $handInStorageService=app('HandInStorageService');
+        if ($info['customerid']=='ONKYO'||$info['customerid']=='ANMEILAI'||$info['customerid']=='FEIHE'){
+            $res=$handInStorageService->checkWidthHeight($info);
+            if ($res===1)$this->error('需要维护产品档案');
+            if ($res===2)$this->error('需要维护该产品档案中的长宽高');
+        }
+        if ($info['customerid']=='TANGENBEI'||$info['customerid']=='ANMEILAI'){
+            $result=$handInStorageService->checkCubicWeight($info);
+            if ($result===1)$this->error('需要维护产品档案');
+            if ($result===2)$this->error('需要维护该产品档案中的重量体积');
+        }
+        if ($info['customerid']=='JIANSHANG'&&$handInStorageService->checkForwardingLoc($info)===1)$this->error('请维护拣货位');
+        $key = $info['asnno'] . '_' . $info['sku'] . '_' . Auth::id();
+        $ttl = 10;
+        try {
+            //缓存校验操作
+            if (Cache::has($key)){
+                $this->error('当前已操作');
+            }else{
+                Cache::put($key,true, $ttl);
+            }
+            //收货操作
+            $resultIn = $handInStorageService->fluxHandIn($info);
+            if ($resultIn===1)$this->error("超收");
+            if ($resultIn){
+                $this->success('收货成功');
+            } else $this->error("收货失败");
+        } catch (\Exception $e) {
+            app('LogService')->log(__METHOD__,'error_'.__FUNCTION__,json_encode($info).'|catch:'.$e->getMessage());
+        } finally {
+            Cache::forget($key);
+        }
+    }
+}

+ 72 - 181
app/Http/Controllers/TestController.php

@@ -24,6 +24,7 @@ use App\Http\Controllers\api\thirdPart\syrius\units\StorageTypeAttribute;
 use App\Http\Requests\AndroidGateRequest;
 use App\Http\Requests\OrderDelivering;
 use App\Jobs\BatchTaskJob;
+use App\Jobs\BroadcastBatchToZhengCangJob;
 use App\Jobs\CacheShelfTaskJob;
 use App\Jobs\OrderCreateInstantBill;
 use App\Jobs\OrderCreateWaybill;
@@ -38,6 +39,7 @@ use App\Logistic;
 use App\MaterialBox;
 use App\MaterialBoxModel;
 use App\Notifications\RoutineNotification;
+use App\OracleDOCASNDetail;
 use App\OracleDOCASNHeader;
 use App\OracleDOCOrderHeader;
 use App\OracleDocOrderPackingSummary;
@@ -73,6 +75,7 @@ use App\Services\ForeignHaiRoboticsService;
 use App\Services\ForeignZhenCangService;
 use App\Services\LogisticService;
 use App\Services\LogService;
+use App\Services\MenuService;
 use App\Services\NotificationService;
 use App\Services\OracleDOCOrderHeaderService;
 use App\Services\OrderPackageCommoditiesService;
@@ -85,6 +88,7 @@ use App\Services\OwnerPriceOperationService;
 use App\Services\OwnerService;
 use App\Services\OwnerStoreFeeReportService;
 use App\Services\OwnerStoreOutFeeReportService;
+use App\Services\ReplenishmentService;
 use App\Services\ReviewService;
 use App\Services\StationService;
 use App\Services\StorageService;
@@ -107,6 +111,7 @@ use App\WorkOrder;
 use Carbon\Carbon;
 use Carbon\CarbonPeriod;
 use Decimal\Decimal;
+use Doctrine\DBAL\Driver\AbstractDB2Driver;
 use Doctrine\DBAL\Exception;
 use Firebase\JWT\ExpiredException;
 use Firebase\JWT\JWT;
@@ -131,6 +136,7 @@ use Laravel\Horizon\Events\JobFailed;
 use Monolog\Handler\IFTTTHandler;
 use phpDocumentor\Reflection\Types\Resource_;
 use PhpOffice\PhpSpreadsheet\Calculation\Web\Service;
+use PhpParser\Node\Stmt\DeclareDeclare;
 use Ramsey\Uuid\Uuid;
 use Symfony\Component\ErrorHandler\Error\FatalError;
 
@@ -153,166 +159,19 @@ class TestController extends Controller
             dd("方法不存在");
         }
     }
-    /**
-     * @param $wave
-     * @return string
-     */
-    private function wms_status($wave): string
-    {
-        switch ($wave->wavestatus) {
-            case 00:
-                $wms_status = '创建';
-                break;
-            case 40:
-                $wms_status = '部分收货';
-                break;
-            case 90:
-                $wms_status = '取消';
-                break;
-            case 99:
-                $wms_status = '完成';
-                break;
-            case 62:
-                $wms_status = '部分装箱';
-                break;
-            default:
-                $wms_status = (string)$wave->wavestatus;
-        }
-        return $wms_status;
-    }
-    public function assignBatch()
-    {
-        $code = \request("code");
-        $batches = Batch::query()->where("code",$code)->get();
-        if (!$batches->count()){
-            $wave = DB::connection("oracle")->selectOne(DB::raw("select * from DOC_WAVE_HEADER where WAVENO = ?"),[$code]);
-            if (!$wave){
-                dd("FLUX无波次");
-            }
-            $owner = app("OwnerService")->codeGetOwner($wave->customerid);
-            $obj = [
-                "wms_status" => $this->wms_status($wave),
-                "wms_type"=>$wave->descr,
-                "created_at"=>date("Y-m-d H:i:s"),
-                "wms_created_at"=>$wave->addtime,
-                "updated_at"=>$wave->edittime,
-                "owner_id"=>$owner->id,
-            ];
-            $wave = Batch::query()->where("code",$code)->first();
-            if (!$wave){
-                $obj["code"] = $code;
-                $wave = Batch::query()->create($obj);
-            }else{
-                Batch::query()->where("code",$code)->update($obj);
-            }
-            $ordernos = array_column(DB::connection("oracle")->select(DB::raw("select orderno from DOC_WAVE_DETAILS where WAVENO = ?"),[$code]),"orderno");
-            Order::query()->whereIn("code",$ordernos)->update([
-                "batch_id"=>$wave->id
-            ]);
-            Order::query()->with(["batch","bin"])->whereIn("code",$ordernos)->get()->each(function ($order){
-                if (!$order->bin){
-                    $bin = DB::connection("oracle")->selectOne(DB::raw("select seqno from DOC_WAVE_DETAILS where waveno = ? and orderno = ?"),[$order->batch->code,$order->code]);
-                    if ($bin){
-                        OrderBin::query()->create([
-                            'order_id' => $order->id,
-                            'number' => $bin->seqno,
-                        ]);
-                    }
-                }
-            });
-            $batches = Batch::query()->where("code",$code)->get();
-        }
-        app("BatchService")->assignTasks($batches);
-    }
-    private function i3()
-    {
-        $taskItem = new TaskItem();
-        $taskItem->name = "测试衣服商品名3";
-        $taskItem->barcode = "TEST-014";
-        $taskItem->quantity = (int)1;
-        $taskItem->binLocations = [
-            "G04-039-1",
-        ];
-        $taskItem->attributes = [
-            "orderLineNo" => "1",
-            "skuLineNo"   => "1",
-            "sku"         => "TEST3",
-            "lotNum"      => "LOT1792011",
-            "logisticNumber"=> "极兔",
-        ];
-        return (array)$taskItem->get();
-    }
-    private function i2()
-    {
-        $taskItem = new TaskItem();
-        $taskItem->name = "测试衣服商品名2";
-        $taskItem->barcode = "TEST-013";
-        $taskItem->quantity = (int)1;
-        $taskItem->binLocations = [
-            "G04-056-1",
-        ];
-        $taskItem->attributes = [
-            "orderLineNo" => "1",
-            "skuLineNo"   => "1",
-            "sku"         => "TEST1",
-            "lotNum"      => "LOT179201",
-            "logisticNumber"=> "圆通",
-        ];
-        return (array)$taskItem->get();
-    }
-    private function i1()
-    {
-        $taskItem = new TaskItem();
-        $taskItem->name = "测试衣服  商品名";
-        $taskItem->barcode = "TEST-012";
-        $taskItem->quantity = (int)1;
-        $taskItem->binLocations = [
-            "G04-046-0",
-        ];
-        $taskItem->attributes = [
-            "orderLineNo" => "1",
-            "skuLineNo"   => "1",
-            "sku"         => "TEST",
-            "lotNum"      => "LOT17920",
-            "logisticNumber"=> "顺丰",
-        ];
-        return (array)$taskItem->get();
-    }
-    private function t1()
-    {
-        $task = new Task();
-        $task->id = "TEST0010";
-        $task->batchId = "WTEST0002";
-        $task->warehouseId = "101";
-        $task->attributes = [
-            "customer" => "幼岚",
-        ];
-        $task->type = Task::TOTAL_PICKING;
-        $task->storages = [["type"=>"1A_container"]];
-        $task->items = [
-            $this->i1(),
-            $this->i2(),
-            $this->i3(),
-        ];
-        return $task->get();
-    }
-    use Signature;
-    private static $delayedHour = 48;
-    function process(Request $request): array
-    {
-        $station_id = $request->input('station_id');
-        $batch_id = $request->input('batch_id');
+    function process(Request $request){
+        $token = trim($request->input('token'));
+        $station_id = 'test';
+        $batch_id = 'W211111001514-6';
+
         $childIndex = null;
         $arr = explode('-',$batch_id);
         if (count($arr)==2){
             $batch_id = $arr[0];
             $childIndex = (int)$arr[1];
+            $request->offsetSet("batch_id",$batch_id);
         }
 
-        $s = new SortingController();
-        // 同步orderCommodity
-        $s->syncOrder($batch_id);
-
         /** @var Batch|\stdClass $batch */
         $batch=Batch::query()->where('code',$batch_id)->orderBy('id','desc')->first();
         $data=[
@@ -330,39 +189,40 @@ FROM (SELECT T.ORDERNO, ROWNUM AS NO
 FROM (SELECT ORDERNO FROM DOC_WAVE_DETAILS WHERE WAVENO = '{$batch_id}' ORDER BY SEQNO) T)
 WHERE NO BETWEEN {$start} AND {$end}
 SQL;
+            dd($sql);
             $waves = DB::connection("oracle")->select(DB::raw($sql));
             $codes = array_column($waves,'orderno');
-            $orders = Order::query()->whereIn("code",$codes)->get();
-        }else $orders = $batch->orders()->get();
+            $orders = Order::query()->with(["bin","owner","orderCommodities.commodity.barcodes"])->whereIn("code",$codes)->get();
+        }else $orders = $batch->orders()->with(["bin","owner","orderCommodities.commodity.barcodes"])->get();
 
         $ordersSorted=$orders->sortBy(function(Order $order){
-            return $order->bin()->first()['number'];
+            return $order->bin->number;
         });
-        $ordersSorted->each(function(Order $order)use(&$data,$request){
+        $ordersSorted->each(function(Order $order)use(&$data,$request,$childIndex,$batch){
             if($order['status']=='取消')return;
             $orderData=[
                 'order_id'=>$order['code'],
-                'owner'=>$order->owner()->first()['code'],
+                'owner'=>$order->owner->code,
                 'status'=>$order['status']=='未处理'?'available':$order['status'],
                 'created_at'=>$order['created_at']->toDateTimeString(),
-                'bin'=>(function()use($order){
-                    $bin=$order->bin()->first()['number']??'';
+                'bin'=>(function()use($order,$childIndex,$batch){
+                    $bin=$order->bin->number??'';
                     if(!$bin){
                         $bin=OracleDOCWaveDetails::query()->where('orderno', 'SO201230003574')->get('seqno')->first()['seqno']??'';
-                        dump('BIN 缺失');
-                        return $bin;
+                        LogService::log(__METHOD__,__FUNCTION__,'bin缺失补查:'.$bin.'. order:'.$order->toJson());
+                        return $childIndex!==null ? $bin-(($childIndex-1)*$batch->split_size) : $bin;
                     }
-                    return $bin;
+                    return $childIndex!==null ? $bin-(($childIndex-1)*$batch->split_size) : $bin;
                 })(),
                 'barcodes'=>[]
             ];
-            $order->orderCommodities()->each(function(OrderCommodity $orderCommodity)use(&$orderData,$request){
-                $commodity=$orderCommodity->commodity()->first();
+            $order->orderCommodities->each(function(OrderCommodity $orderCommodity)use(&$orderData,$request){
+                $commodity=$orderCommodity->commodity;
                 if(!$commodity){
-                    dump("没订单");
+                    app('LogService')->log(__METHOD__, 'error' . __FUNCTION__, '播种位数据准备出错,找不到订单对应的Commodity id的对象'.$orderCommodity['commodity_id'].',是否表数据在波次生成后丢失?'.json_encode($request->all()));
                     return;
                 }
-                $barcodeStr=$commodity->barcodes()->get()->map(function(CommodityBarcode $barcode){
+                $barcodeStr=$commodity->barcodes->map(function(CommodityBarcode $barcode){
                     return $barcode['code'];
                 })->filter(function($code){
                     return $code&&(!preg_match('/[\x{4e00}-\x{9fa5}]/u',$code));
@@ -380,19 +240,42 @@ SQL;
         });
         return $data;
     }
+
     public function test(Request $request)
     {
-        $request->offsetSet("station_id",'123456789');
+        $s = new MenuService();
+        dd($s->getVisibleFunctionList());
+        dd(1);
+
         dd($this->process($request));
-        echo 'Now memory_get_usage: ' . memory_get_usage() . '<br />';
-        $t1 = microtime(true);
-// ... 执行代码 ...
-        $t2 = microtime(true);
-        echo '耗时'.round($t2-$t1,3).'秒<br>';
-        echo 'Now memory_get_usage: ' . memory_get_usage() . '<br />';
-        return;
-        $a = new \App\Http\Controllers\api\thirdPart\syrius\producer\OrderController();
-        dd($a->createOrder($this->t1())->body());
+        $batch = Batch::query()->where("code","W211111001514")->first();
+        dd($batch->orders()->with("bin")->first());
+        $path = '';
+        $id = 109;
+
+        $file = fopen($path, "r");
+        $user=array();
+        $i=0;
+        //输出文本中所有的行,直到文件结束为止。
+        while(! feof($file)){
+            $user[$i]= trim(fgets($file));//fgets()函数从文件指针中读取一行
+            $i++;
+        }
+        fclose($file);
+        foreach ($user as $item){
+            $arr = explode(",",$item);
+            if (count($arr)!=2){
+                dump($item);
+                continue;
+            }
+            DB::table("details")->insert([
+                "name" => $arr[0],
+                "size" => $arr[1],
+                "created_at" => date("Y-m-d H:i:s"),
+                "updated_at" => date("Y-m-d H:i:s"),
+                "header_id" => $id
+            ]);
+        }
     }
     public function test1()
     {
@@ -857,10 +740,18 @@ sql;
 
     public function testZhenCang()
     {
-        $batches=Batch::query()->with(['orders.orderCommodities.commodity.barcodes'])->find(161071);
-        /** @var ForeignZhenCangService  $foreignZhenCangService */
-       $foreignZhenCangService=app('ForeignZhenCangService');;
-       $foreignZhenCangService->broadcastBatch($batches);
+//        $batches=Batch::query()->where('id',161071)->get();
+//        BroadcastBatchToZhengCangJob::dispatch($batches);
+//        $sql = <<<sql
+//select department_id,obligation_id,owner_id,max(valid_time) from department_obligation_owner group by obligation_id,owner_id,department_id
+//sql;
+//        $info = DB::select(DB::raw($sql));
+//        dd($info);
+//        $owner=Owner::query()->with(['departmentObligationOwner'])->find(403);
+//        dd($owner);
+//        $a=app('ObligationService')->recombineCodeIdArr();
+        $now=Carbon::now()->subMonths(-1)->startOfMonth()->startOfDay()->toDateTimeString();
+        dd($now);
     }
 
     public function syncOrderIssue()

+ 34 - 22
app/Http/Controllers/WaveController.php

@@ -162,14 +162,29 @@ class WaveController extends Controller
     public function split()
     {
         $codes = \request("codes",[]);
-        $splitSize = \request("splitSize");
-        if (!$codes || !$splitSize)$this->error("无记录");
-        if (!is_numeric($splitSize) || !is_int((int)$splitSize))$this->error("非法输入");
-        $size = Batch::query()->whereIn("code",$codes)->whereNull("split_size")->count();
-        if ($size!=count($codes))$this->error("波次不全或不允许二次分割");
-        Batch::query()->whereIn("code",$codes)->whereNull("split_size")->update([
-            "split_size" => $splitSize
-        ]);
+        $splitSize = \request("split");
+        $splitNumber = \request("number");
+        if (!$codes || (!$splitSize && !$splitNumber))$this->error("无记录");
+        if ((!is_numeric($splitSize) || !is_int((int)$splitSize)) && !is_numeric($splitNumber) || !is_int((int)$splitNumber))$this->error("非法输入");
+        if ($splitSize){
+            $size = Batch::query()->whereIn("code",$codes)->whereNull("split_size")->count();
+            if ($size!=count($codes))$this->error("波次不全或不允许二次分割");
+            Batch::query()->whereIn("code",$codes)->whereNull("split_size")->update([
+                "split_size" => $splitSize
+            ]);
+        }else{
+            $no = "";
+            foreach ($codes as $code){
+                $no .= "'".$code."',";
+            }
+            $no = rtrim($no,',');
+            $sql = <<<SQL
+SELECT WAVENO,MAX(SEQNO) count from DOC_WAVE_DETAILS WHERE WAVENO IN ({$no}) GROUP BY WAVENO
+SQL;
+            foreach (DB::connection("oracle")->select(DB::raw($sql)) as $wave){
+                Batch::query()->where("code",$wave->waveno)->update(["split_size" => (int)ceil($wave->count/$splitNumber)]);
+            };
+        }
         $this->success();
     }
 
@@ -178,10 +193,12 @@ class WaveController extends Controller
         $codes = \request("codes",[]);
         if (!$codes)$this->error("无记录");
         $batches = [];
-        foreach (Batch::query()->select("code","split_size")->withCount("orders")
+        foreach (Batch::query()->select("code","split_size","id")
                      ->whereIn("code",$codes)->whereNotNull("split_size")->get() as $batch){
             if ($batch->orders_count==0)continue;
-            $batches[$batch->code] = (int)ceil($batch->orders_count/$batch->split_size);
+            $bin = OrderBin::query()->selectRaw("MAX(number) max")->whereIn("order_id",Order::query()
+                ->select("id")->where("batch_id",$batch->id))->first();
+            $batches[$batch->code] = (int)ceil($bin->max/$batch->split_size);
         }
         $this->success($batches);
     }
@@ -195,30 +212,25 @@ class WaveController extends Controller
     {
         $code = \request("code");
         $batch = null;
-        if (!$code || !$batch = Batch::query()->select("id")->where("code",$code)->first())$this->error("无记录");
+        if (!$code || !$batch = Batch::query()->select("id","split_size")->where("code",$code)->first())$this->error("无记录");
         $sql = <<<SQL
-SELECT a.ORDERNO,a.QTY,s.ALTERNATE_SKU1 FROM ACT_ALLOCATION_DETAILS a
+SELECT a.ORDERNO,a.QTY,s.ALTERNATE_SKU1,a.LOCATION,w.SEQNO FROM ACT_ALLOCATION_DETAILS a
     LEFT JOIN DOC_ORDER_HEADER o ON a.ORDERNO = o.ORDERNO
     LEFT JOIN DOC_WAVE_DETAILS w ON o.ORDERNO = w.ORDERNO
     LEFT JOIN BAS_SKU s ON a.SKU = s.SKU
-WHERE w.WAVENO = '{$code}' ORDER BY w.SEQNO;
+WHERE w.WAVENO = '{$code}' ORDER BY w.SEQNO
 SQL;
         $orders = DB::connection("oracle")->select(DB::raw($sql));
         $result = [];
         $currentList = [];
-        $slowPointer = 0;
         $nodeSign = "";
         foreach ($orders as $order){
-            if ($order->orderno!=$nodeSign){
-                if ($slowPointer==$batch->split_size){
-                    $result[] = $currentList;
-                    $currentList = [];
-                    $slowPointer = 0;
-                }
-                $slowPointer++;
+            if ($order->seqno%$batch->split_size==0 && $nodeSign!=$order->orderno){
+                $result[] = $currentList;
+                $currentList = [];
                 $nodeSign = $order->orderno;
             }
-            $currentList[] = ["barcode"=>$order->alternate_sku1,"qty"=>$order->qty];
+            $currentList[] = ["barcode"=>$order->alternate_sku1,"qty"=>$order->qty,"location"=>$order->location];
         }
         if ($currentList)$result[] = $currentList;
         $this->success($result);

+ 22 - 22
app/Http/Controllers/api/thirdPart/haochuang/SortingController.php

@@ -62,6 +62,15 @@ class SortingController extends Controller
         $token = trim($request->input('token'));
         $station_id = $request->input('station_id');
         $batch_id = $request->input('batch_id');
+
+        $childIndex = null;
+        $arr = explode('-',$batch_id);
+        if (count($arr)==2){
+            $batch_id = $arr[0];
+            $childIndex = (int)$arr[1];
+            $request->offsetSet("batch_id",$batch_id);
+        }
+
         $errors=$this->processValidator($request->all())->errors();
         if(count($errors)>0){
             app('LogService')->log(__METHOD__, 'error' . __FUNCTION__, json_encode($request->all()).'|'.json_encode($errors));
@@ -70,12 +79,6 @@ class SortingController extends Controller
 //        if(!UserToken::getUser($token)){
 //            return ['result'=>'unauthority','fail_info'=>'无效令牌或令牌过期'];
 //        }
-        $childIndex = null;
-        $arr = explode('-',$batch_id);
-        if (count($arr)==2){
-            $batch_id = $arr[0];
-            $childIndex = (int)$arr[1];
-        }
 
         // 同步orderCommodity
         $this->syncOrder($batch_id);
@@ -92,44 +95,41 @@ class SortingController extends Controller
             $start = (($childIndex-1)*$batch->split_size)+1;
             $end = $childIndex*$batch->split_size;
             $sql = <<<SQL
-SELECT ORDERNO
-FROM (SELECT T.ORDERNO, ROWNUM AS NO
-FROM (SELECT ORDERNO FROM DOC_WAVE_DETAILS WHERE WAVENO = '{$batch_id}' ORDER BY SEQNO) T)
-WHERE NO BETWEEN {$start} AND {$end}
+SELECT ORDERNO FROM DOC_WAVE_DETAILS WHERE WAVENO = '{$batch_id}' AND SEQNO BETWEEN {$start} AND {$end};
 SQL;
             $waves = DB::connection("oracle")->select(DB::raw($sql));
             $codes = array_column($waves,'orderno');
-            $orders = Order::query()->whereIn("code",$codes)->get();
-        }else $orders = $batch->orders()->get();
+            $orders = Order::query()->with(["bin","owner","orderCommodities.commodity.barcodes"])->whereIn("code",$codes)->get();
+        }else $orders = $batch->orders()->with(["bin","owner","orderCommodities.commodity.barcodes"])->get();
 
         $ordersSorted=$orders->sortBy(function(Order $order){
-            return $order->bin()->first()['number'];
+            return $order->bin->number;
         });
-        $ordersSorted->each(function(Order $order)use(&$data,$request){
+        $ordersSorted->each(function(Order $order)use(&$data,$request,$childIndex,$batch){
             if($order['status']=='取消')return;
             $orderData=[
                 'order_id'=>$order['code'],
-                'owner'=>$order->owner()->first()['code'],
+                'owner'=>$order->owner->code,
                 'status'=>$order['status']=='未处理'?'available':$order['status'],
                 'created_at'=>$order['created_at']->toDateTimeString(),
-                'bin'=>(function()use($order){
-                    $bin=$order->bin()->first()['number']??'';
+                'bin'=>(function()use($order,$childIndex,$batch){
+                    $bin=$order->bin->number??'';
                     if(!$bin){
                         $bin=OracleDOCWaveDetails::query()->where('orderno', 'SO201230003574')->get('seqno')->first()['seqno']??'';
                         LogService::log(__METHOD__,__FUNCTION__,'bin缺失补查:'.$bin.'. order:'.$order->toJson());
-                        return $bin;
+                        return $childIndex!==null ? $bin-(($childIndex-1)*$batch->split_size) : $bin;
                     }
-                    return $bin;
+                    return $childIndex!==null ? $bin-(($childIndex-1)*$batch->split_size) : $bin;
                 })(),
                 'barcodes'=>[]
             ];
-            $order->orderCommodities()->each(function(OrderCommodity $orderCommodity)use(&$orderData,$request){
-                $commodity=$orderCommodity->commodity()->first();
+            $order->orderCommodities->each(function(OrderCommodity $orderCommodity)use(&$orderData,$request){
+                $commodity=$orderCommodity->commodity;
                 if(!$commodity){
                     app('LogService')->log(__METHOD__, 'error' . __FUNCTION__, '播种位数据准备出错,找不到订单对应的Commodity id的对象'.$orderCommodity['commodity_id'].',是否表数据在波次生成后丢失?'.json_encode($request->all()));
                     return;
                 }
-                $barcodeStr=$commodity->barcodes()->get()->map(function(CommodityBarcode $barcode){
+                $barcodeStr=$commodity->barcodes->map(function(CommodityBarcode $barcode){
                     return $barcode['code'];
                 })->filter(function($code){
                     return $code&&(!preg_match('/[\x{4e00}-\x{9fa5}]/u',$code));

+ 19 - 0
app/Http/Requests/OrderDelivering.php

@@ -2,6 +2,8 @@
 
 namespace App\Http\Requests;
 
+use Illuminate\Support\Facades\Auth;
+
 class OrderDelivering extends GateRequest
 {
     public function __construct()
@@ -31,5 +33,22 @@ class OrderDelivering extends GateRequest
             $date = date('Y-m-d',strtotime("-{$increment} day"));
             request()->offsetSet("orderdate_start",$date." 00:00");
         }
+
+        if (!app("UserService")->checkAdminIdentity(Auth::id())){
+            $owners = app('OwnerService')->getIntersectPermitting(['id', 'code']);
+            $codes = array_column($owners->toArray(), 'code');
+            if (request("customerid")) {
+                $arr = explode(',', request("customerid"));
+                $customer = [];
+                foreach ($arr as $value) {
+                    if (in_array($value, $codes)) $customer[] = $value;
+                }
+                if (count($customer) < 1) $customer = [''];
+                request()->offsetSet("customerid",$customer);
+            } else request()->offsetSet("customerid",$codes);
+        }else if (request("customerid")){
+            $codes = explode(',', request("customerid"));
+            if ($codes<0)request()->offsetUnset("customerid");
+        }
     }
 }

+ 45 - 0
app/Jobs/BroadcastBatchToZhengCangJob.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Batch;
+use App\Services\ForeignZhenCangService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+
+class BroadcastBatchToZhengCangJob implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    private $batches;
+
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     */
+    public function __construct($batches)
+    {
+        $this->batches=$batches;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        /** @var ForeignZhenCangService  $foreignZhenCangService */
+        $foreignZhenCangService=app('ForeignZhenCangService');
+        foreach ($this->batches as &$batch){
+            $batch->loadMissing([
+                'orders.orderCommodities.commodity.barcodes'
+            ]);
+            $foreignZhenCangService->broadcastBatch($batch);
+        }
+    }
+}

+ 2 - 0
app/Jobs/LaborApplyRecordJob.php

@@ -9,6 +9,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Foundation\Bus\Dispatchable;
 use Illuminate\Queue\InteractsWithQueue;
 use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Facades\Log;
 
 class LaborApplyRecordJob implements ShouldQueue
 {
@@ -37,6 +38,7 @@ class LaborApplyRecordJob implements ShouldQueue
      */
     public function handle()
     {
+        Log::debug("LaborApplyRecordJob isAppend = " . ($this->isAppend + 1) . "");
         $response = $this->service->allocationLaborToLaborCompany($this->isAppend);
         if (!$response['success']) throw new WarningException($response['error_message']);
     }

+ 21 - 0
app/Obligation.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class Obligation extends Model
+{
+    use ModelLogChanging;
+
+    use ModelTimeFormat;
+    protected $table='obligation';
+    public $timestamps=false;
+
+    protected $fillable=[
+        'name','code', 'create_time', 'update_time','delete_flag'
+    ];
+}

+ 1 - 1
app/OracleBasSKU.php

@@ -10,9 +10,9 @@ use Illuminate\Database\Eloquent\Model;
  */
 use App\Traits\ModelTimeFormat;
 use App\Traits\ModelLogChanging;
-
 class OracleBasSKU extends Model
 {
+    use \Awobaz\Compoships\Compoships;
     use ModelLogChanging;
 
     use ModelTimeFormat;

+ 7 - 0
app/OracleDOCASNDetail.php

@@ -9,6 +9,7 @@ use App\Traits\ModelLogChanging;
 
 class OracleDOCASNDetail extends Model
 {
+    use \Awobaz\Compoships\Compoships;
     use ModelLogChanging;
 
     use ModelTimeFormat;
@@ -29,4 +30,10 @@ class OracleDOCASNDetail extends Model
         return $this->hasOne(OracleBasCode::class,'code','lotatt08')
             ->where('codeid','QLT_STS');
     }
+    public function basSku()
+    {
+        return $this->hasOne(OracleBasSKU::class,['customerid','sku'],['customerid','sku'])
+            ->select('customerid','sku','lotid','alternate_sku1','alternate_sku2','alternate_sku3');
+
+    }
 }

+ 7 - 0
app/Owner.php

@@ -118,6 +118,13 @@ class Owner extends Model
     {   //面积报表
         return $this->hasOne(OwnerAreaReport::class,"owner_id","id");
     }
+    public function departmentObligationOwner()
+    {   //部门职能关联
+        return $this->hasMany(DepartmentObligationOwner::class,"owner_id","id")
+            ->selectRaw('obligation_code,obligation_id,owner_id,department_id,max(valid_time)')
+            ->groupBy('obligation_id','owner_id','department_id')
+            ->whereNull('failure_time');
+    }
     public function ownerStoragePriceModels()
     {   //仓储计费
         $query = OwnerStoragePriceModel::query()->select("target_id")

+ 4 - 0
app/Providers/AppServiceProvider.php

@@ -192,6 +192,8 @@ use App\Services\LaborApplyService;
 use App\Services\SyriusTaskService;
 use App\Services\WorkOrderLogService;
 use App\Services\OrderIssueTypeService;
+use App\Services\ReplenishmentService;
+use App\Services\ObligationService;
 
 class AppServiceProvider extends ServiceProvider
 {
@@ -276,6 +278,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('MenuService',MenuService::class);
         app()->singleton('NewOrderCountingRecordService',NewOrderCountingRecordService::class);
         app()->singleton('NotificationService',NotificationService::class);
+        app()->singleton('ObligationService',ObligationService::class);
         app()->singleton('OracleActAllocationDetailService', OracleActAllocationDetailService::class);
         app()->singleton('OracleBasCustomerService', OracleBasCustomerService::class);
         app()->singleton('OracleBasSkuService', OracleBasSkuService::class);
@@ -348,6 +351,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('RejectedBillItemService', RejectedBillItemService::class);
         app()->singleton('RejectedBillService', RejectedBillService::class);
         app()->singleton('RejectedService', RejectedService::class);
+        app()->singleton('ReplenishmentService',ReplenishmentService::class);
         app()->singleton('RequirementService',RequirementService::class);
         app()->singleton('RequirementUserService',RequirementUserService::class);
         app()->singleton('ReviewService',ReviewService::class);

+ 1 - 5
app/Services/ForeignZhenCangService.php

@@ -33,13 +33,9 @@ class ForeignZhenCangService
             }
             $body['orders'][] = $orderArr;
         }
+        dd($body);
         $response = Http::withHeaders([
             'Host' => 'zc-it.com',
         ])->post('http://1.116.164.201:8080/api/createBatch',$body);
     }
-
-    public function broadcastBatchByFlux()
-    {
-
-    }
 }

+ 1 - 1
app/Services/HandInStorageService.php

@@ -453,7 +453,7 @@ sql;
      * @throws \Throwable
      * flux手持端 上架
      */
-    public function fluxHandPa(array $info, array $taskParam): bool
+    public function fluxHandPa(array $info, array $taskParam)
     {
         $tasks = $this->selectFluxTask($taskParam, $info['amount']);
         if (!$tasks) return false; //获取任务失败

+ 5 - 2
app/Services/LaborApplyService.php

@@ -92,11 +92,12 @@ class LaborApplyService
         $warehouses = Warehouse::all();
         //给每个仓库计算分配数据 更改申请状态为指派成功
         foreach ($warehouses as $warehouse) {
-            //查询当日的的申请,将申请的男女工分别加和
+            //根据时间,仓库,状态 查询当日的的申请,将申请的男女工分别加和
             $builder = DB::table('labor_applies')
                 ->selectRaw("sum(man_num) as man_num ,sum(woman_num) as woman_num")
                 ->whereBetween('created_at', [now()->startOfDay(), now()->endOfDay()])
-                ->where('warehouse_id', $warehouse->id);
+                ->where('warehouse_id', $warehouse->id)
+                ->where('status', 1);
             //如果是追加模式
             if ($isAppend) {
                 //只查询最后一次分配后的申请
@@ -154,6 +155,8 @@ class LaborApplyService
                 'exceed_max_labor_num_status' => LaborCompanyDispatch::NOT_EXCEED_MAX_LABOR_NUM,//没有超限额
                 'status' => 1,//创建
                 'warehouse_id' => $warehouse_id,
+                'created_at' => now(),
+                'updated_at' => now(),
             ];
         }
         //分配男工

+ 114 - 0
app/Services/ObligationService.php

@@ -0,0 +1,114 @@
+<?php
+
+namespace App\Services;
+
+use App\DepartmentObligationOwner;
+use App\Owner;
+use App\Traits\ServiceAppAop;
+use App\Obligation;
+use Carbon\Carbon;
+
+class ObligationService
+{
+    use ServiceAppAop;
+    protected $modelClass=Obligation::class;
+
+    public function getSelection($column = ['id','code'])
+    {
+        return Obligation::query()->select($column)->get();
+    }
+    public function recombineCodeIdArr(){
+        $obligations=$this->getSelection()->toArray();
+        return array_combine(array_column($obligations, 'code'), array_column($obligations, 'id'));
+    }
+    public function createOrUpdate(array $param){
+        $obligation=$this->recombineCodeIdArr();
+        $owner=Owner::query()->with('departmentObligationOwner')->find($param['id']);
+        $departmentObligationOwner=$owner->departmentObligationOwner->toArray()??[];
+        $time=Carbon::now()->subMonths(-1)->startOfMonth()->startOfDay()->toDateTimeString();
+        if (empty($departmentObligationOwner)){//第一次新增 部门和职能及货主关联
+           $insert_param=[];
+            $insert_param[]=['department_id'=>$param['kc'],'obligation_id'=>$obligation['kc'],'obligation_code'=>'kc','owner_id'=>$param['id'],'valid_time'=>$time];
+            $insert_param[]=['department_id'=>$param['jg'],'obligation_id'=>$obligation['jg'],'obligation_code'=>'jg','owner_id'=>$param['id'],'valid_time'=>$time];
+            $insert_param[]=['department_id'=>$param['th'],'obligation_id'=>$obligation['th'],'obligation_code'=>'th','owner_id'=>$param['id'],'valid_time'=>$time];
+            $insert_param[]=['department_id'=>$param['sh'],'obligation_id'=>$obligation['sh'],'obligation_code'=>'sh','owner_id'=>$param['id'],'valid_time'=>$time];
+            $insert_param[]=['department_id'=>$param['fh'],'obligation_id'=>$obligation['fh'],'obligation_code'=>'fh','owner_id'=>$param['id'],'valid_time'=>$time];
+            DepartmentObligationOwner::query()->insert($insert_param);
+        }else{//修改货主中的 仓库组, 加工组, 发货组, 收货组, 退货组信息
+            $kc=DepartmentObligationOwner::query()
+                ->where('obligation_id',$obligation['kc'])
+                ->where('owner_id',$param['id'])
+                ->where('valid_time',$time)->first();
+            if ($kc){
+                $kc->update(['department_id'=>$param['kc']]);
+            }else{
+                DepartmentObligationOwner::query()
+                    ->orderByDesc('id')
+                    ->where('obligation_id',$obligation['kc'])
+                    ->where('owner_id',$param['id'])
+                    ->update(['failure_time'=>$time]);
+                DepartmentObligationOwner::query()->insert(['department_id'=>$param['kc'],'obligation_id'=>$obligation['kc'],'obligation_code'=>'kc','owner_id'=>$param['id'],'valid_time'=>$time]);
+            }
+            $jg=DepartmentObligationOwner::query()
+                ->where('obligation_id',$obligation['jg'])
+                ->where('owner_id',$param['id'])
+                ->where('valid_time',$time)->first();
+            if ($jg){
+                $jg->update(['department_id'=>$param['jg']]);
+            }else{
+                DepartmentObligationOwner::query()
+                    ->orderByDesc('id')
+                    ->where('obligation_id',$obligation['jg'])
+                    ->where('owner_id',$param['id'])
+                    ->update(['failure_time'=>$time]);
+                DepartmentObligationOwner::query()->insert(['department_id'=>$param['jg'],'obligation_id'=>$obligation['jg'],'obligation_code'=>'jg','owner_id'=>$param['id'],'valid_time'=>$time]);
+            }
+
+            $th=DepartmentObligationOwner::query()
+                ->where('obligation_id',$obligation['th'])
+                ->where('owner_id',$param['id'])
+                ->where('valid_time',$time)->first();
+            if ($th){
+                $th->update(['department_id'=>$param['th']]);
+            }else{
+                DepartmentObligationOwner::query()
+                    ->orderByDesc('id')
+                    ->where('obligation_id',$obligation['th'])
+                    ->where('owner_id',$param['id'])
+                    ->update(['failure_time'=>$time]);
+                DepartmentObligationOwner::query()->insert(['department_id'=>$param['th'],'obligation_id'=>$obligation['th'],'obligation_code'=>'th','owner_id'=>$param['id'],'valid_time'=>$time]);
+            }
+
+            $sh=DepartmentObligationOwner::query()
+                ->where('obligation_id',$obligation['sh'])
+                ->where('owner_id',$param['id'])
+                ->where('valid_time',$time)->first();
+            if ($sh){
+                $sh->update(['department_id'=>$param['sh']]);
+            }else{
+                DepartmentObligationOwner::query()
+                    ->orderByDesc('id')
+                    ->where('obligation_id',$obligation['sh'])
+                    ->where('owner_id',$param['id'])
+                    ->update(['failure_time'=>$time]);
+                DepartmentObligationOwner::query()->insert(['department_id'=>$param['sh'],'obligation_id'=>$obligation['sh'],'obligation_code'=>'sh','owner_id'=>$param['id'],'valid_time'=>$time]);
+            }
+
+            $fh=DepartmentObligationOwner::query()
+                ->where('obligation_id',$obligation['fh'])
+                ->where('owner_id',$param['id'])
+                ->where('valid_time',$time)->first();
+            if ($fh){
+                $fh->update(['department_id'=>$param['fh']]);
+            }else{
+                DepartmentObligationOwner::query()
+                    ->orderByDesc('id')
+                    ->where('obligation_id',$obligation['fh'])
+                    ->where('owner_id',$param['id'])
+                    ->update(['failure_time'=>$time]);
+                DepartmentObligationOwner::query()->insert(['department_id'=>$param['fh'],'obligation_id'=>$obligation['fh'],'obligation_code'=>'fh','owner_id'=>$param['id'],'valid_time'=>$time]);
+            }
+        }
+        return Owner::query()->with('departmentObligationOwner')->find($param['id']);
+    }
+}

+ 60 - 4
app/Services/OwnerService.php

@@ -124,8 +124,8 @@ class OwnerService implements UserFilter
     }
 
     public function firstOrCreate(array $params, array $values = null){
-        if (!$values) return Owner::query()->firstOrCreate($params);
-        return Owner::query()->firstOrCreate($params,$values);
+        if (!$values) return Owner::query()->whereNull("deleted_at")->firstOrCreate($params);
+        return Owner::query()->whereNull("deleted_at")->firstOrCreate($params,$values);
     }
 
 
@@ -270,8 +270,38 @@ class OwnerService implements UserFilter
                 else $builder->where('owner_id',$param);
                 continue;
             }
-            if ($column == 'user_work_group'){
-                $builder->where("user_workgroup_id",$param);
+//            if ($column == 'user_work_group'){
+//                $builder->where("user_workgroup_id",$param);
+//                continue;
+//            }
+            if ($column == 'kcGroup'){
+                $builder->whereHas("departmentObligationOwner",function($query)use($param){
+                    $query->where('obligation_code','kc')->where('department_id',$param);
+                });
+                continue;
+            }
+            if ($column == 'jgGroup'){
+                $builder->whereHas("departmentObligationOwner",function($query)use($param){
+                    $query->where('obligation_code','jg')->where('department_id',$param);
+                });
+                continue;
+            }
+            if ($column == 'fhGroup'){
+                $builder->whereHas("departmentObligationOwner",function($query)use($param){
+                    $query->where('obligation_code','fh')->where('department_id',$param);
+                });
+                continue;
+            }
+            if ($column == 'thGroup'){
+                $builder->whereHas("departmentObligationOwner",function($query)use($param){
+                    $query->where('obligation_code','th')->where('department_id',$param);
+                });
+                continue;
+            }
+            if ($column == 'shGroup'){
+                $builder->whereHas("departmentObligationOwner",function($query)use($param){
+                    $query->where('obligation_code','sh')->where('department_id',$param);
+                });
                 continue;
             }
             if (is_array($param))$builder->whereIn($column,$param);
@@ -561,4 +591,30 @@ sql;
         }
         return $query->whereNull("deleted_at");
     }
+
+    public function combineOwners($owners)
+    {
+        foreach ($owners as $owner){
+            $departmentObligationOwner=$owner->departmentObligationOwner??false;
+            if (!$departmentObligationOwner)continue;
+            foreach ($departmentObligationOwner as $item){
+                if ($item->obligation_code=='kc'){
+                    $owner->kc=$item->department_id;$owner->kcGroup=$item->department?$item->department->name:'';
+                }
+                if ($item->obligation_code=='jg'){
+                    $owner->jg=$item->department_id;$owner->jgGroup=$item->department?$item->department->name:'';
+                }
+                if ($item->obligation_code=='th'){
+                    $owner->th=$item->department_id;$owner->thGroup=$item->department?$item->department->name:'';
+                }
+                if ($item->obligation_code=='sh'){
+                    $owner->sh=$item->department_id;$owner->shGroup=$item->department?$item->department->name:'';
+                }
+                if ($item->obligation_code=='fh'){
+                    $owner->fh=$item->department_id;$owner->fhGroup=$item->department?$item->department->name:'';
+                }
+            }
+        }
+        return $owners;
+    }
 }

+ 184 - 0
app/Services/ReplenishmentService.php

@@ -0,0 +1,184 @@
+<?php
+
+namespace App\Services;
+
+use App\Traits\ServiceAppAop;
+use Carbon\Carbon;
+use Illuminate\Support\Facades\DB;
+
+
+class ReplenishmentService
+{
+    use ServiceAppAop;
+
+    /**
+     * @param $customer
+     * @return array
+     * 根据货主,订单状态为拣货完成之前的
+     * 订单信息
+     */
+    public function getOrderInfoRecentMonthByCustomer($customer): array
+    {
+        $db = DB::connection("oracle");
+        $sql = <<<sql
+select orders.customerid, orders.sku,orders.amount,BAS_SKU.ALTERNATE_SKU1,BAS_SKU.ALTERNATE_SKU2,BAS_SKU.ALTERNATE_SKU3
+from (
+         select customerid, sku, sum(QTYORDERED_EACH) amount
+         from DOC_ORDER_DETAILS
+         where ORDERNO in (select ORDERNO
+                           from DOC_ORDER_HEADER
+                           where SOSTATUS IN ('00', '10', '20', '30', '40', '50')
+                             AND customerid = ?
+                             AND ADDTIME >= TO_DATE(?, 'yyyy-mm-dd hh24:mi:ss')
+                             AND ADDTIME <= TO_DATE(?, 'yyyy-mm-dd hh24:mi:ss'))
+         group by customerid, sku
+     ) orders
+left join BAS_SKU on orders.customerid=BAS_SKU.customerid and orders.sku = BAS_SKU.SKU
+order by orders.amount desc
+sql;
+        $res= $db->select(DB::raw($sql),[$customer,Carbon::now()->subDays(30)->toDateTimeString(),Carbon::now()->toDateTimeString()]);
+        $orders=array();
+        foreach ($res as $item){
+            $orders[]=json_decode( json_encode( $item),true);
+        }
+        return $orders;
+
+    }
+
+    /**
+     * @param $customer
+     * @param array $skuArr
+     * @return array
+     * 根据货主和发货sku 获取库存拣货位及拣货位商品数量
+     * 并整合为sku 为key的数组
+     */
+    public function getEaInventoryByCustomerAndSku($customer,array $skuArr): array
+    {
+        $db = DB::connection("oracle");
+        $info=array();
+        foreach (array_chunk($skuArr,1000) as $item){
+            $sql = <<<sql
+select INV_LOT_LOC_ID.CUSTOMERID,INV_LOT_LOC_ID.SKU,INV_LOT_LOC_ID.LOCATIONID,sum(INV_LOT_LOC_ID.QTY) qty
+from INV_LOT_LOC_ID
+         left join BAS_LOCATION on BAS_LOCATION.LOCATIONID = INV_LOT_LOC_ID.LOCATIONID
+where BAS_LOCATION.LOCATIONUSAGE = 'EA'
+  AND customerid = ?
+
+sql;
+        if (count($item) > 0) {
+            $sql .= " and sku in (";
+            foreach ($item as $index => $str) {
+                if ($index == 0) {
+                    $sql .= "'" . $str . "'";
+                    continue;
+                }
+                $sql .= ",'" . $str . "'";
+            }
+            $sql .= ")";
+        }
+            $sql.= ' group by INV_LOT_LOC_ID.CUSTOMERID,INV_LOT_LOC_ID.SKU,INV_LOT_LOC_ID.LOCATIONID';
+            $info[]= $db->select(DB::raw($sql),[$customer]);
+        }
+        $info = array_merge(...$info);
+        //整合同sku下的拣货库位
+        $tmpArray = array();
+        foreach ($info as $row) {
+            $key = $row->sku;
+            if (array_key_exists($key, $tmpArray)) {
+                if (is_array($tmpArray[$key]['locationid'])) {
+                    $tmpArray[$key]['locationid'][] = $row->locationid;
+                } else {
+                    $tmpArray[$key]['locationid'] = array($tmpArray[$key]['locationid'], $row->locationid);
+                }
+                if ($tmpArray[$key]['qty']) {
+                    $tmpArray[$key]['qty'] += $row->qty;
+                } else {
+                    $tmpArray[$key]['qty'] =  $row->qty;
+                }
+            } else {
+                $tmpArray[$key] = array('sku'=>$row->sku,'locationid'=>array($row->locationid),'qty'=>$row->qty);
+            }
+        }
+        return $tmpArray;
+    }
+
+    /**
+     * @param $customer
+     * @param array $skuArr
+     * @return array
+     * 根据货主和发货sku 获取库存存储位及存储位商品数量
+     * 并整合为sku 为key的数组
+     */
+    public function getRsInventoryByCustomerAndSku($customer,array $skuArr): array
+    {
+        $db = DB::connection("oracle");
+        $info=array();
+        foreach (array_chunk($skuArr,1000) as $item){
+            $sql = <<<sql
+select INV_LOT_LOC_ID.CUSTOMERID,INV_LOT_LOC_ID.SKU,INV_LOT_LOC_ID.LOCATIONID,INV_LOT_LOC_ID.LOTNUM,sum(INV_LOT_LOC_ID.QTY) qty
+from INV_LOT_LOC_ID
+         left join BAS_LOCATION on BAS_LOCATION.LOCATIONID = INV_LOT_LOC_ID.LOCATIONID
+where BAS_LOCATION.LOCATIONUSAGE = 'RS'
+  AND customerid = ?
+sql;
+            if (count($item) > 0) {
+                $sql .= " and sku in (";
+                foreach ($item as $index => $str) {
+                    if ($index == 0) {
+                        $sql .= "'" . $str . "'";
+                        continue;
+                    }
+                    $sql .= ",'" . $str . "'";
+                }
+                $sql .= ")";
+            }
+            $sql.= ' group by INV_LOT_LOC_ID.CUSTOMERID,INV_LOT_LOC_ID.SKU,INV_LOT_LOC_ID.LOCATIONID,INV_LOT_LOC_ID.LOTNUM order by qty desc';
+            $info[]= $db->select(DB::raw($sql),[$customer]);
+        }
+        $info=array_merge(...$info);
+        //整合同sku下的存储库位
+        $tmpArray = array();
+        foreach ($info as $row) {
+            $key = $row->sku;
+            if (array_key_exists($key, $tmpArray)) {
+                if (is_array($tmpArray[$key]['locationid'])) {
+                    if (count($tmpArray[$key]['locationid'])<5){
+                        $tmpArray[$key]['locationid'][] = ['location'=>$row->locationid,'qty'=>$row->qty,'lot'=>$row->lotnum];
+                    }
+                } else {
+                    $tmpArray[$key]['locationid'] = array($tmpArray[$key]['locationid'], ['location'=>$row->locationid,'qty'=>$row->qty,'lot'=>$row->lotnum]);
+                }
+            } else {
+                $tmpArray[$key] = array('sku'=>$row->sku,'locationid'=>array(['location'=>$row->locationid,'qty'=>$row->qty,'lot'=>$row->lotnum]));
+            }
+        }
+        return $tmpArray;
+    }
+
+    public function combinationSql(array $skuArr,$sql)
+    {
+        foreach (array_chunk($skuArr,1000) as $index=>$item){
+            if ($index==0){
+                $sql .= " and sku in (";
+                foreach ($item as $i => $str) {
+                    if ($i == 0) {
+                        $sql .= "'" . $str . "'";
+                        continue;
+                    }
+                    $sql .= ",'" . $str . "'";
+                }
+            }else{
+                $sql .= " or sku in (";
+                foreach ($item as $a => $str) {
+                    if ($a == 0) {
+                        $sql .= "'" . $str . "'";
+                        continue;
+                    }
+                    $sql .= ",'" . $str . "'";
+                }
+            }
+            $sql .= ")";
+        }
+        return $sql;
+    }
+}

+ 12 - 5
app/Services/StoreItemService.php

@@ -35,11 +35,18 @@ class StoreItemService
 
     public function getAsnDetailsByAsnHerder($asnHerders)
     {
-        return OracleDOCASNDetail::query()
-            ->with(['lineStatus', 'qualityStatus'])
-            ->whereIn('asnno',array_unique(data_get($asnHerders, '*.asnno')))
-            ->select('asnno','asnlineno','customerid','sku','skudescrc','linestatus','lotatt08','lotatt05','receivedqty','expectedqty','addtime','edittime')
-            ->get();
+        $asnnos=array_unique(data_get($asnHerders, '*.asnno'));
+        $collect=collect();
+        foreach (array_chunk($asnnos,1000) as $item){
+            $res= OracleDOCASNDetail::query()
+                ->with(['lineStatus', 'qualityStatus'])
+                ->whereIn('asnno',$item)
+                ->select('asnno','asnlineno','customerid','sku','skudescrc','linestatus','lotatt08','lotatt05','receivedqty','expectedqty','addtime','edittime')
+                ->get();
+            $collect->merge($res);
+        }
+        return $collect;
+
     }
 
     public function createStoreItem($asnDetails)

+ 3 - 2
composer.json

@@ -12,8 +12,10 @@
         "ext-bcmath": "*",
         "ext-json": "*",
         "ext-mbstring": "*",
+        "ext-oci8": "*",
         "ext-openssl": "*",
         "ext-pdo": "*",
+        "awobaz/compoships": "^2.1",
         "doctrine/dbal": "^2.10",
         "endroid/qr-code": "^3.7",
         "facade/ignition": "^2.0",
@@ -33,8 +35,7 @@
         "predis/predis": "^1.1",
         "pusher/pusher-php-server": "^4.1",
         "te7a-houdini/laravel-trix": "^2.0",
-        "yajra/laravel-oci8": "7.0",
-        "ext-oci8": "*"
+        "yajra/laravel-oci8": "7.0"
     },
     "require-dev": {
         "barryvdh/laravel-debugbar": "^3.2",

+ 63 - 3
composer.lock

@@ -4,8 +4,68 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "5dc450e032b783ab6f83fb3d7348eb9e",
+    "content-hash": "a8a45b0f4001cb3c8e61821f0cc50383",
     "packages": [
+        {
+            "name": "awobaz/compoships",
+            "version": "2.1.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/topclaudy/compoships.git",
+                "reference": "df6a9eb558d03c2c8be2ebb07e277568eb3302c0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/topclaudy/compoships/zipball/df6a9eb558d03c2c8be2ebb07e277568eb3302c0",
+                "reference": "df6a9eb558d03c2c8be2ebb07e277568eb3302c0",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/database": ">=5.6 <9.0"
+            },
+            "require-dev": {
+                "ext-sqlite3": "*"
+            },
+            "suggest": {
+                "awobaz/blade-active": "Blade directives for the Laravel 'Active' package",
+                "awobaz/eloquent-auto-append": "Automatically append accessors to model serialization",
+                "awobaz/eloquent-mutators": "Reusable mutators (getters/setters) for Laravel 5's Eloquent",
+                "awobaz/syntactic": "Syntactic sugar for named and indexed parameters call."
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Awobaz\\Compoships\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Claudin J. Daniel",
+                    "email": "cdaniel@awobaz.com"
+                }
+            ],
+            "description": "Laravel relationships with support for composite/multiple keys",
+            "keywords": [
+                "laravel",
+                "laravel composite keys",
+                "laravel relationships"
+            ],
+            "support": {
+                "issues": "https://github.com/topclaudy/compoships/issues",
+                "source": "https://github.com/topclaudy/compoships/tree/2.1.2"
+            },
+            "funding": [
+                {
+                    "url": "https://paypal.me/awobaz",
+                    "type": "custom"
+                }
+            ],
+            "time": "2021-09-04T16:00:10+00:00"
+        },
         {
             "name": "bacon/bacon-qr-code",
             "version": "2.0.4",
@@ -10515,9 +10575,9 @@
         "ext-bcmath": "*",
         "ext-json": "*",
         "ext-mbstring": "*",
+        "ext-oci8": "*",
         "ext-openssl": "*",
-        "ext-pdo": "*",
-        "ext-oci8": "*"
+        "ext-pdo": "*"
     },
     "platform-dev": [],
     "platform-overrides": {

+ 65 - 6
resources/views/customer/project/create.blade.php

@@ -97,6 +97,11 @@
                     waring_line_on : "{{$owner->waring_line_on ?? ''}}",
                     subjection : "{{$owner->subjection ?? ''}}",
                     is_tax_exist : "{{$owner->is_tax_exist ?? ''}}"==='Y',
+                    kc :"{{$owner->kc ?? ''}}",
+                    jg :"{{$owner->jg ?? ''}}",
+                    th :"{{$owner->th ?? ''}}",
+                    sh :"{{$owner->sh ?? ''}}",
+                    fh :"{{$owner->fh ?? ''}}",
                 },
                 ownerTemp : {},
                 customers : [
@@ -482,7 +487,12 @@
                     if (!this.owner.customer_id) error["customer_id"] = ["必须选择客户"];
                     if (!this.owner.owner_group_id) error["owner_group_id"] = ["必须选择项目小组"];
                     if (!this.owner.warehouse_id) error["warehouse_id"] = ["必须选择仓库"];
-                    if (!this.owner.user_workgroup_id) error["user_workgroup_id"] = ["必须选择仓库小组"];
+                    // if (!this.owner.user_workgroup_id) error["user_workgroup_id"] = ["必须选择仓库小组"];
+                    if (!this.owner.kc) error["kc"] = ["必须选择库存组"];
+                    if (!this.owner.jg) error["jg"] = ["必须选择加工组"];
+                    if (!this.owner.th) error["th"] = ["必须选择退货组"];
+                    if (!this.owner.sh) error["sh"] = ["必须选择收货组"];
+                    if (!this.owner.fh) error["fh"] = ["必须选择发货组"];
                     //if (!this.owner.tax_rate_id) error["tax_rate_id"] = ["必须选择税率"];
                     if (JSON.stringify(error) !== "{}"){
                         this.errors = error;
@@ -494,7 +504,11 @@
                     let old = this.ownerTemp;
                     if (params.customer_id !== old.customer_id ||
                     params.owner_group_id !== old.owner_group_id ||
-                    params.user_workgroup_id !== old.user_workgroup_id ||
+                    params.kc !== old.kc ||
+                    params.jg !== old.jg ||
+                    params.th !== old.th ||
+                    params.sh !== old.sh ||
+                    params.fh !== old.fh ||
                     params.warehouse_id !== old.warehouse_id ||
                     params.tax_rate_id !== old.tax_rate_id ||
                     params.waring_line_on !== old.waring_line_on ||
@@ -512,7 +526,12 @@
                             this.errors = [];
                             this.ownerTemp.customer_id = res.customer_id;
                             this.ownerTemp.owner_group_id = res.owner_group_id;
-                            this.ownerTemp.user_workgroup_id = res.user_workgroup_id;
+                            // this.ownerTemp.user_workgroup_id = res.user_workgroup_id;
+                            if (res.department_obligation_owner.obligation_code==='kc')this.ownerTemp.kc = res.department_obligation_owner.obligation_id;
+                            if (res.department_obligation_owner.obligation_code==='jg')this.ownerTemp.jg = res.department_obligation_owner.obligation_id;
+                            if (res.department_obligation_owner.obligation_code==='th')this.ownerTemp.th = res.department_obligation_owner.obligation_id;
+                            if (res.department_obligation_owner.obligation_code==='sh')this.ownerTemp.sh = res.department_obligation_owner.obligation_id;
+                            if (res.department_obligation_owner.obligation_code==='fh')this.ownerTemp.fh = res.department_obligation_owner.obligation_id;
                             this.ownerTemp.warehouse_id = res.warehouse_id;
                             this.ownerTemp.tax_rate_id = res.tax_rate_id;
                             this.ownerTemp.waring_line_on = res.waring_line_on;
@@ -2059,12 +2078,52 @@
                         }
                     });
                 },
-                filterUserGroup(e){
+                filterkc(e){
                     let value = e.target.value;
-                    if (!value)this.owner.user_workgroup_id = "";
+                    if (!value)this.owner.kc = "";
                     this.userGroups.some(userGroup=>{
                         if (userGroup.name.indexOf(value)!==-1){
-                            this.owner.user_workgroup_id = userGroup.id;
+                            this.owner.kc = userGroup.id;
+                            return true;
+                        }
+                    });
+                },
+                filterjg(e){
+                    let value = e.target.value;
+                    if (!value)this.owner.jg = "";
+                    this.userGroups.some(userGroup=>{
+                        if (userGroup.name.indexOf(value)!==-1){
+                            this.owner.jg = userGroup.id;
+                            return true;
+                        }
+                    });
+                },
+                filterth(e){
+                    let value = e.target.value;
+                    if (!value)this.owner.th = "";
+                    this.userGroups.some(userGroup=>{
+                        if (userGroup.name.indexOf(value)!==-1){
+                            this.owner.th = userGroup.id;
+                            return true;
+                        }
+                    });
+                },
+                filtersh(e){
+                    let value = e.target.value;
+                    if (!value)this.owner.sh = "";
+                    this.userGroups.some(userGroup=>{
+                        if (userGroup.name.indexOf(value)!==-1){
+                            this.owner.sh = userGroup.id;
+                            return true;
+                        }
+                    });
+                },
+                filterfh(e){
+                    let value = e.target.value;
+                    if (!value)this.owner.fh = "";
+                    this.userGroups.some(userGroup=>{
+                        if (userGroup.name.indexOf(value)!==-1){
+                            this.owner.fh = userGroup.id;
                             return true;
                         }
                     });

+ 25 - 5
resources/views/customer/project/index.blade.php

@@ -64,7 +64,12 @@
                     <td><span>@{{ owner.name }}</span></td>
                     <td><span>@{{ owner.customer_name }}</span></td>
                     <td><span>@{{ owner.user_owner_group_name }}</span></td>
-                    <td><span>@{{ owner.user_work_group_name }}</span></td>
+{{--                    <td><span>@{{ owner.user_work_group_name }}</span></td>--}}
+                    <td><span>@{{ owner.kcGroup }}</span></td>
+                    <td><span>@{{ owner.jgGroup }}</span></td>
+                    <td><span>@{{ owner.thGroup }}</span></td>
+                    <td><span>@{{ owner.shGroup }}</span></td>
+                    <td><span>@{{ owner.fhGroup }}</span></td>
                     <td><span><b>@{{owner.relevance ? owner.relevance.length : 0}}</b>/6&nbsp;<span class="badge badge-success" v-if="owner.audit_count>0">@{{ owner.audit_count }}项待审</span></span></td>
                     <td><span>@{{ owner.created_at }}</span></td>
                     <td><span>@{{ owner.customer_company_name }}</span></td>
@@ -108,7 +113,13 @@
                         is_activation : "{{$owner->deleted_at ? '否' : '是'}}",
                         ownerStoragePriceModels : {!! $owner->ownerStoragePriceModels !!},
                         audit_count:"{{count($owner->storageAudit)+count($owner->operationAudit)+count($owner->expressAudit)+count($owner->logisticAudit)+count($owner->directLogisticAudit)+($owner->systemAudit ? 1 : 0)}}",
-                        a:"{{$owner}}"
+                        a:"{{$owner}}",
+                        kc:"{{$owner->kc}}", kcGroup:"{{$owner->kcGroup}}",
+                        jg:"{{$owner->jg}}", jgGroup:"{{$owner->jgGroup}}",
+                        th:"{{$owner->th}}", thGroup:"{{$owner->thGroup}}",
+                        sh:"{{$owner->sh}}", shGroup:"{{$owner->shGroup}}",
+                        fh:"{{$owner->fh}}", fhGroup:"{{$owner->fhGroup}}",
+
                     },
                     @endforeach
                 ],
@@ -140,8 +151,10 @@
                 let data=[
                     [
                         {name:'user_owner_group_id',type:'select',tip:'项目小组',placeholder: '项目小组',data:this.ownerGroups},
-                        {name:'user_work_group',type:'select',tip: '仓库小组搜索',placeholder: '仓库小组',data:this.user_work_groups},
-
+                        // {name:'user_work_group',type:'select',tip: '仓库小组搜索',placeholder: '仓库小组',data:this.user_work_groups},
+                        {name:'kcGroup',type:'select',tip: '库存组搜索',placeholder: '库存组',data:this.user_work_groups},
+                        {name:'jgGroup',type:'select',tip: '加工组搜索',placeholder: '加工组',data:this.user_work_groups},
+                        {name:'shGroup',type:'select',tip: '收货组搜索',placeholder: '收货组',data:this.user_work_groups},
                         {name:'created_at_start',type:'time',tip:['选择显示创建日期的起始时间','']},
                         {name:'ids',type:'select_multiple_select',tip:['输入关键词快速定位下拉列表,回车确定','选择要显示的项目'],
                             placeholder:['项目','定位或多选项目'],data:this.models},
@@ -149,6 +162,8 @@
                     ],[
                         {name:'customers',type:'select_multiple_select',tip:['客户','定位或多选项目'],placeholder: ['客户','定位或多选项目'],data:this.customers},
                         {name:'using_type',type:'select',placeholder: '用仓类型',data:[{name:"常温",value:"常温"},{name:"恒温",value:"恒温"}]},
+                        {name:'thGroup',type:'select',tip: '退货组搜索',placeholder: '退货组',data:this.user_work_groups},
+                        {name:'fhGroup',type:'select',tip: '发货组搜索',placeholder: '发货组',data:this.user_work_groups},
                         {name:'created_at_end',type:'time',tip:['选择显示创建日期的结束时间','']},
                     ],
                 ];
@@ -162,7 +177,12 @@
                     {name:'name',value: '项目'},
                     {name:'customer',value: '客户'},
                     {name:'user_owner_group_name',value: '项目小组'},
-                    {name:'user_work_group_name',value: '仓库小组'},
+                    // {name:'user_work_group_name',value: '仓库小组'},
+                    {name:'kc',value: '库存组'},
+                    {name:'jg',value: '加工组'},
+                    {name:'th',value: '退货组'},
+                    {name:'sh',value: '收货组'},
+                    {name:'fh',value: '发货组'},
                     {name:'relevance', neglect: true,value: '计费模型填写情况'},
                     {name:'created_at',value: '创建日期'},
                     {name:'customer_full_name',value: '公司全称'},

+ 49 - 7
resources/views/customer/project/part/_two.blade.php

@@ -9,11 +9,11 @@
     </span>
 </div>
 <div class="row mt-3">
-    <label for="owner_group_id" class="col-2 text-info">项目组</label>
+    <label for="owner_group_id" class="col-2 text-info">项目组</label>
     <select id="owner_group_id" v-model="owner.owner_group_id" @change="selectGroup()" class="form-control form-control-sm col-4 mb-0" :class="errors.owner_group_id ? 'is-invalid' : ''" >
         <option v-for="ownerGroup in ownerGroups" :value="ownerGroup.id">@{{ ownerGroup.name }}</option>
     </select>
-    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字项目组" @input="filterOwnerGroup($event)"></label>
+    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字项目组" @input="filterOwnerGroup($event)"></label>
     <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.owner_group_id">
         <strong>@{{ errors.owner_group_id[0] }}</strong>
     </span>
@@ -27,16 +27,58 @@
         <strong>@{{ errors.warehouse_id[0] }}</strong>
     </span>
 </div>
+
 <div class="row mt-3">
-    <label for="user_workgroup_id" class="col-2 text-info">仓库小组</label>
-    <select id="user_workgroup_id" v-model="owner.user_workgroup_id" @change="selectGroup()" class="form-control form-control-sm col-4 mb-0" :class="errors.user_workgroup_id ? 'is-invalid' : ''" >
+    <label for="kc" class="col-2 text-info">库存组</label>
+    <select id="kc" v-model="owner.kc" @change="selectKcGroup()"   class="form-control form-control-sm col-4 mb-0" :class="errors.kc ? 'is-invalid' : ''" >
         <option v-for="userGroup in userGroups" :value="userGroup.id" v-if="userGroup.warehouse_id == owner.warehouse_id">@{{ userGroup.name }}</option>
     </select>
-    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字项目小组" @change="filterUserGroup($event)"></label>
-    <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.user_workgroup_id">
-        <strong>@{{ errors.user_workgroup_id[0] }}</strong>
+    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字库存组" @change="filterkc($event)"></label>
+    <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.kc">
+        <strong>@{{ errors.kc[0] }}</strong>
     </span>
 </div>
+<div class="row mt-3">
+    <label for="jg" class="col-2 text-info">加工组</label>
+    <select id="jg" v-model="owner.jg"  class="form-control form-control-sm col-4 mb-0" :class="errors.jg ? 'is-invalid' : ''" >
+        <option v-for="userGroup in userGroups" :value="userGroup.id" v-if="userGroup.warehouse_id == owner.warehouse_id">@{{ userGroup.name }}</option>
+    </select>
+    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字加工组" @change="filterjg($event)"></label>
+    <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.jg">
+        <strong>@{{ errors.jg[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label for="th" class="col-2 text-info">退货组</label>
+    <select id="th" v-model="owner.th"  class="form-control form-control-sm col-4 mb-0" :class="errors.th ? 'is-invalid' : ''" >
+        <option v-for="userGroup in userGroups" :value="userGroup.id" v-if="userGroup.warehouse_id == owner.warehouse_id">@{{ userGroup.name }}</option>
+    </select>
+    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字退货组" @change="filterth($event)"></label>
+    <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.th">
+        <strong>@{{ errors.th[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label for="sh" class="col-2 text-info">收货组</label>
+    <select id="sh" v-model="owner.sh"  class="form-control form-control-sm col-4 mb-0" :class="errors.sh ? 'is-invalid' : ''" >
+        <option v-for="userGroup in userGroups" :value="userGroup.id" v-if="userGroup.warehouse_id == owner.warehouse_id">@{{ userGroup.name }}</option>
+    </select>
+    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字收货组" @change="filtersh($event)"></label>
+    <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.sh">
+        <strong>@{{ errors.sh[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label for="fh" class="col-2 text-info">发货组</label>
+    <select id="fh" v-model="owner.fh"  class="form-control form-control-sm col-4 mb-0" :class="errors.fh ? 'is-invalid' : ''" >
+        <option v-for="userGroup in userGroups" :value="userGroup.id" v-if="userGroup.warehouse_id == owner.warehouse_id">@{{ userGroup.name }}</option>
+    </select>
+    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字发货组" @change="filterfh($event)"></label>
+    <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.fh">
+        <strong>@{{ errors.fh[0] }}</strong>
+    </span>
+</div>
+
 <div class="row mt-3">
     <label for="subjection" class="col-2">主体公司</label>
     <select id="subjection" v-model="owner.subjection" class="form-control form-control-sm col-4 mb-0" >

+ 141 - 0
resources/views/inventory/stockOut/index.blade.php

@@ -0,0 +1,141 @@
+@extends('layouts.app')
+@section('title')库存管理-补货列表@endsection
+@section('content')
+    <div id="list" class="d-none item-logistic-index">
+        <div class="container-fluid">
+            <div class="m-2 form-inline" id="btn">
+                <select class="form-control form-control-sm tooltipTarget" name="owner_id" id="owner_id"
+                        style="width: 150px;position: relative" title="选择指定货主" v-model="owner_id">
+                    <option value="">货主</option>
+                    <option v-for="owner in owners" :value="owner.name">@{{ owner.value }}</option>
+                </select>
+                <input placeholder="定位货主" id="ownerName" autocomplete="off" @input="定位货主($event)"
+                       class="form-control form-control-sm tooltipTarget" style="width: 100px" title="输入关键字定位货主">
+                <button class="btn btn-sm btn-outline-info ml-3" @click="search()" >查询</button>
+
+                <button type="button"
+                        @click="orderItemExport(true)"
+                        class="btn btn-outline-dark btn-sm ml-2"
+                        title="导出所有页将会以搜索条件得到的筛选结果,将其全部记录(每一页)导出">导出Excel
+                </button>
+
+            </div>
+            <table class="table table-striped table-bordered table-hover card-body td-min-width-80" id="table">
+                <tr v-if="item.amount > 0 " v-for="(item,i) in details" @click="selectTr===i+1?selectTr=0:selectTr=i+1"
+                    :class="selectTr===i+1?'focusing' : ''">
+                    <td>@{{ item.customerid }}</td>
+                    <td>@{{ item.sku }}</td>
+                    <td>@{{ item.alternate_sku1 }}</td>
+                    <td>
+                        <ul style="list-style: none" v-if="item.eaLocation.length>0">
+                            <li v-for="(v,k) in item.eaLocation" v-if="k<3 || item.moreEaLocation">@{{ v }}</li>
+                            <a v-if="item.eaLocation.length >= 3" href="javascript:;"
+                               @click="item.moreEaLocation = !(item.moreEaLocation)">展示更多</a>
+                        </ul>
+                        <div v-else>拣货库位不存在</div>
+                    </td>
+                    <td>@{{ item.amount }}</td>
+                    <td>
+                        <ul style="list-style: none">
+                            <li v-for="(v,k) in item.rsLocation" v-if="k<3 || item.moreRaLocation">@{{ v.location }}
+                                <span class="font-weight-bold text-dark">&nbsp;&nbsp;&nbsp;:@{{ v.qty }}</span>
+                                <span class="font-weight-bold text-dark">&nbsp;&nbsp;&nbsp;:@{{ v.lot }}</span>
+                            </li>
+                            <a v-if="item.rsLocation.length >= 3" href="#javascript:;"
+                               @click="item.moreRaLocation = !(item.moreRaLocation)">展示更多</a>
+                        </ul>
+                    </td>
+                </tr>
+            </table>
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>{{--新版2--}}
+    <script>
+        let vue = new Vue({
+            el: "#list",
+            data: {
+                selectTr: 0,
+                owner_id: '',
+                owners: [
+                        @foreach($owners as $owner)
+                    {
+                        name: '{{$owner->code}}', value: '{{$owner->name}}'
+                    },
+                    @endforeach
+                ],
+                details: []
+            },
+            created() {
+            },
+            mounted() {
+                $('#list').removeClass('d-none');
+                $(".up").slideUp();
+                let column = [
+                    {name: 'owner_name', value: '货主'},
+                    {name: 'sku', value: '商品名称'},
+                    {name: 'barcode', value: '商品条码'},
+                    {name: 'ea_location', value: '拣货库位'},
+                    {name: 'amount', value: '缺货数'},
+                    {name: 'rs_location', value: '存储库位'},
+                ];
+                new Header({
+                    el: "table",
+                    name: "item",
+                    column: column,
+                    data: this.details,
+                    restorationColumn: 'addtime',
+                    fixedTop: ($('#form_div').height()) + ($('#btn').height()) + 1,
+                }).init();
+                $('#table tr:eq(0) th:eq(0)').remove();
+            },
+            methods: {
+                orderItemExport(sign) {
+                    if (this.owner_id === '') {
+                        tempTip.show('请选择货主!');
+                        return;
+                    }
+                    let url = '{{url('inventory/stockOut/export')}}';
+                    let token = '{{ csrf_token() }}';
+                    if (sign) {
+                        excelExport(true, checkData, url, this.total, token, {customer: this.owner_id});
+                    }
+                },
+
+                定位货主(e) {
+                    this.owners.some(owner => {
+                        if (owner.value.indexOf(e.target.value) !== -1) {
+                            this.owner_id = owner.name;
+                            return true;
+                        }
+                    });
+                    if (e.target.value === '' || e.target.value === null || e.target.value === undefined) {
+                        this.owner_id = '';
+                    }
+                },
+
+                search() {
+                    let url = "{{ url('inventory/stockOut/getReplenishmentInfoByCustomer') }}"
+                    axios.post(url, {
+                        customer: this.owner_id
+                    }).then(res => {
+                        if (res.data.success){
+                            this.details = res.data.data
+                        }else {
+                            window.tempTip.show(res.data.data);
+                            window.tempTip.setDuration(2000);
+                        }
+
+                    }).catch(function (err){
+                        window.tempTip.show('网络异常'+err);
+                        window.tempTip.setDuration(2000);
+                    });
+                }
+            },
+            filters: {},
+        });
+    </script>
+@endsection

+ 174 - 0
resources/views/kpi/day/index.blade.php

@@ -0,0 +1,174 @@
+@extends('layouts.app')
+@section('title')KPI-日报表@endsection
+@section('content')
+    <div class="d-none" id="list">
+        <div class="container-fluid">
+            <div id="form_div"></div>
+            <!--            导出-->
+            <span class="dropdown"></span>
+            <h3>2021</h3>
+            <!--            表格-->
+            <table class="table table-striped table-bordered table-hover text-nowrap waybill-table td-min-width-80"
+                   style="background: #fff;" id="table">
+                <tr v-for="(item,i) in details.data" :key="i">
+                    <td><input class="checkItem" type="checkbox" :value="item.id"></td>
+                    <td class="td-warm text-muted"><span>@{{ item.statTime.slice(0,10) }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.avgOnDutyTime }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.avgOffDutyTime }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.attendanceNum }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ Math.round(item.workTimes) }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.totalDeliveryQty }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.expressCollectQty }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.whDeliveryNum }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.transferDeliveryNum }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.purchaseEntryNum }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.transferEntryNum }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.returnEntryNum }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.inventoryNum }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.inventoryQty }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.occupationArea }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.delay24Qty }}</span></td>
+                    <td class="td-warm text-muted"><span>@{{ item.delay48Qty }}</span></td>
+                </tr>
+            </table>
+            <nav aria-label="...">
+                <ul class="pagination">
+                    <li class="page-item" :class="current===1?'disabled':''">
+                        <button class="page-link" @click="pagination('pre')">上一页</button>
+                    </li>
+                    <li class="page-item" :class="current===details.pages?'disabled':''">
+                        <button class="page-link" @click="pagination('next')">下一页</button>
+                    </li>
+                </ul>
+            </nav>
+        </div>
+    </div>
+
+
+@endsection
+
+@section('lastScript')
+    <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>{{--新版2--}}
+    <script>
+        let vue = new Vue({
+            el: "#list",
+            data: {
+                selectTr: '',
+                details: {
+                    data: [],
+                    total: null,
+                    current: null,
+                    pages: null,
+                    size: null
+                },
+                size: 10,
+                current: 1
+            },
+            created() {
+                let url = this.getBaseUrl();
+                url += `/api/deliver/getDayPage?size=${this.size}&current=${this.current}`;
+                axios.get(url).then(res => {
+                    this.details.data = res.data.data.list;
+                    this.details.total = res.data.data.page.total;
+                    this.details.current = res.data.data.page.pageNum;
+                    this.details.pages = res.data.data.page.pages
+                    this.details.size = res.data.data.page.pageSize;
+                });
+            },
+            mounted: function () {
+                $('#list').removeClass('d-none');
+                let data = [
+                    [
+                        {name: 'date_start', type: 'time', tip: '选择显示指定日期的起始时间'},
+                    ]
+                ];
+                this.form = new query({
+                    el: "#form_div",
+                    condition: data,
+                });
+                this.form.init();
+                this.rendingHeader();
+
+            },
+            methods: {
+                //根据环境获取不同的url
+                getBaseUrl() {
+                    let url = '';
+                    let env = "{{ config('app.env') }}";
+                    if (env === 'local') {
+                        url = ' http://127.0.0.1:8111'
+                    } else if (env === 'production') {
+                        url = ' http://101.133.135.193'
+                    }
+                    return url;
+                },
+                pagination(flag) {
+                    if (flag === 'pre' && this.current > 1) {
+                        this.current--;
+                    } else if (flag === 'next' && this.current < this.details.pages) {
+                        this.current++;
+                    }
+                    let env = "{{ config('env') }}";
+                    console.log(env);
+                    let url = this.getBaseUrl();
+
+                    url += `/api/deliver/getDayPage?size=${this.size}&current=${this.current}`;
+                    axios.get(url).then(res => {
+                        this.details.data = res.data.data.list;
+                        this.details.total = res.data.data.page.total;
+                        this.details.current = res.data.data.page.pageNum;
+                        this.details.pages = res.data.data.page.pages
+                        this.details.size = res.data.data.page.pageSize;
+                    });
+                },
+                rendingHeader() {
+                    let column = [
+                        {name: 'stat_time', value: '统计日期', neglect: true, class: "td-cool"},
+                        {name: 'avg_on_duty_time', value: '平均上班时间', neglect: true, class: "td-cool"},
+                        {name: 'avg_off_duty_time', value: '平均下班时间', class: "td-cool"},
+                        {name: 'attendance_num', value: '出勤人数', neglect: true, class: "td-cool"},
+                        {name: 'work_times', value: '生产工时', class: "td-cool"},
+
+                        {name: 'total_delivery_qty', value: '总发货量', class: "td-warm"},
+                        {name: 'express_collect_qty', value: '快递揽收数量', neglect: true, class: "td-warm"},
+                        {name: 'wh_delivery_num', value: '仓库发货个数', class: "td-warm"},
+                        {name: 'transfer_delivery_num', value: '调拨出库总个数', class: "td-warm"},
+
+                        {name: 'purchase_entry_num', value: '采购入库数', class: "td-cool"},
+                        {name: 'transfer_entry_num', value: '调拨入库数', class: "td-cool"},
+                        {name: 'return_entry_num', value: '退货入库数', class: "td-cool"},
+
+                        {name: 'inventory_num', value: '盘点库位数', class: "td-warm"},
+                        {name: 'inventory_qty', value: '盘点数量', class: "td-warm"},
+                        {name: 'occupation_area', value: '盘点数量', class: "td-warm"},
+
+                        {name: 'delay_24_qty', value: '24小时延迟数', neglect: true, class: "td-cool"},
+                        {name: 'delay_48_qty', value: '24小时延迟数', neglect: true, class: "td-cool"},
+                    ];
+                    new Header({
+                        el: "table",
+                        name: "details",
+                        column: column,
+                        data: this.details.data,
+                        restorationColumn: 'id',
+                        fixedTop: ($('#form_div').height()) + ($('#btn').height()) + 2,
+                        before: [
+                            {colspan: '6', value: '人员工时(含临时工)', class: "table-header-layer-1"},
+                            {
+                                colspan: '4',
+                                value: '出库',
+                                font: "fa fa-file-text-o",
+                                class: "table-header-layer-1"
+                            },
+                            {colspan: '3', value: '入库', font: "fa fa-truck", class: "table-header-layer-1"},
+                            {colspan: '3', value: '库存', font: "fa fa-truck", class: "table-header-layer-1"},
+                            {colspan: '2', value: '异常', font: "fa fa-truck", class: "table-header-layer-1"},
+                        ],
+                    }).init();
+                },
+            },
+        });
+    </script>
+@endsection

+ 186 - 0
resources/views/kpi/month/index.blade.php

@@ -0,0 +1,186 @@
+@extends('layouts.app')
+@section('title')KPI-月报表@endsection
+@section('content')
+    <div class="d-none" id="list">
+        <div class="container-fluid">
+            <div id="form_div"></div>
+            <!--            导出-->
+            <span class="dropdown"></span>
+            <h3>2021</h3>
+            <!--            表格-->
+            <table class="table table-striped table-bordered table-hover text-nowrap waybill-table td-min-width-80"
+                   style="background: #fff;" id="table">
+                <tr v-for="(item,i) in details.data" :key="i">
+                    <td><input class="checkItem" type="checkbox" :value="item.id"></td>
+                    <td class="td-warm text-muted"><span>@{{item.userWorkgroupName}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.statTime.slice(0,10)}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.purchseEntry}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.allocateTransferEntry}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2bEntry}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.inWarehouseEntry}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.otherEntry}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.returnEntry}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.barterEntry}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.adjustEntry}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.virtualEntry}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.overtimeShelve}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2cDeliveryQty}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2cDeliveryNum}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2cDelayNum}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2cErrorNum}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2cComplainNum}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2bDeliveryNum}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2bDeliveryQty}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2bComplainNum}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2bDeliveryBulk}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.b2bDeliveryWeigh}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.inventory}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.inventoryProfit}}</span></td>
+                    <td class="td-warm text-muted"><span>@{{item.inventoryLoss}}</span></td>
+                </tr>
+            </table>
+            <nav aria-label="...">
+                <ul class="pagination">
+                    <li class="page-item" :class="current===1?'disabled':''">
+                        <button class="page-link" @click="pagination('pre')">上一页</button>
+                    </li>
+                    <li class="page-item" :class="current===details.pages?'disabled':''">
+                        <button class="page-link" @click="pagination('next')">下一页</button>
+                    </li>
+                </ul>
+            </nav>
+        </div>
+    </div>
+
+
+@endsection
+
+@section('lastScript')
+    <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>{{--新版2--}}
+    <script>
+        let vue = new Vue({
+            el: "#list",
+            data: {
+                selectTr: '',
+                details: {
+                    data: [],
+                    total: null,
+                    current: null,
+                    pages: null,
+                    size: null
+                },
+                size: 10,
+                current: 1
+            },
+            created() {
+                let url = this.getBaseUrl();
+                url += `/api/deliver/getMonthPage?size=${this.size}&current=${this.current}`;
+                axios.get(url).then(res => {
+                    this.details.data = res.data.data.list;
+                    this.details.total = res.data.data.page.total;
+                    this.details.current = res.data.data.page.pageNum;
+                    this.details.pages = res.data.data.page.pages
+                    this.details.size = res.data.data.page.pageSize;
+                });
+            },
+            mounted: function () {
+                $('#list').removeClass('d-none');
+                let data = [
+                    [
+                        {name: 'date_start', type: 'dateTime', tip: '选择显示指定日期的起始时间'},
+                    ]
+                ];
+                this.form = new query({
+                    el: "#form_div",
+                    condition: data,
+                });
+                this.form.init();
+                this.rendingHeader();
+
+            },
+            methods: {
+                getBaseUrl() {
+                    let url = '';
+                    let env = "{{ config('app.env') }}";
+                    if (env === 'local') {
+                        url = ' http://127.0.0.1:8111'
+                    } else if (env === 'production') {
+                        url = ' http://101.133.135.193'
+                    }
+                    return url;
+                },
+                pagination(flag) {
+                    console.log(flag);
+                    if (flag === 'pre' && this.current > 1) {
+                        this.current--;
+                    } else if (flag === 'next' && this.current < this.details.pages) {
+                        this.current++;
+                    }
+                    console.log(this.current, this.details.pages);
+                    let url = this.getBaseUrl();
+                    url += `/api/deliver/getMonthPage?size=${this.size}&current=${this.current}`;
+                    axios.get(url).then(res => {
+                        this.details.data = res.data.data.list;
+                        this.details.total = res.data.data.page.total;
+                        this.details.current = res.data.data.page.pageNum;
+                        this.details.pages = res.data.data.page.pages
+                        this.details.size = res.data.data.page.pageSize;
+                    });
+                },
+                rendingHeader() {
+                    let column = [
+                        {name: 'workgroupName', value: '组名', neglect: true, class: "td-warm"},
+                        {name: 'month', value: '月份', class: "td-warm"},
+                        {name: 'purchseEntry', value: '入库采购', neglect: true, class: "td-warm"},
+                        {name: 'allocateTransferEntry', value: '调拨入库', class: "td-warm"},
+                        {name: 'b2bEntry', value: 'B2B入库', class: "td-warm"},
+                        {name: 'inWarehouseEntry', value: '进仓入库', neglect: true, class: "td-warm"},
+                        {name: 'otherEntry', value: '其他入库', class: "td-warm"},
+                        {name: 'returnEntry', value: '退货入库', class: "td-warm"},
+                        {name: 'barterEntry', value: '换货入库', class: "td-warm"},
+                        {name: 'adjustEntry', value: '调整入库', class: "td-warm"},
+                        {name: 'virtualEntry', value: '虚拟入库', class: "td-warm"},
+                        {name: 'overtimeShelve', value: '未及时上架', class: "td-warm"},
+
+
+                        {name: 'b2cDeliveryQty', value: 'B2C发货个数', class: "td-cool"},
+                        {name: 'b2cDeliveryNum', value: 'B2C发货单数', class: "td-cool"},
+                        {name: 'b2cDelayNum', value: 'B2C延误单数', neglect: true, class: "td-cool"},
+                        {name: 'b2cErrorNum', value: 'B2C错漏发单数', neglect: true, class: "td-cool"},
+                        {name: 'b2cComplainNum', value: 'B2C客诉单数', class: "td-cool"},
+                        {name: 'b2bDeliveryNum', value: 'B2B发货行数', neglect: true, class: "td-cool"},
+                        {name: 'b2bDeliveryQty', value: 'B2B发货个数', class: "td-cool"},
+                        {name: 'b2bComplainNum', value: 'B2B客诉行数', class: "td-cool"},
+                        {name: 'b2bDeliveryBulk', value: 'B2B发货体积', class: "td-cool"},
+                        {name: 'b2bDeliveryWeigh', value: 'B2B发货重量', class: "td-cool"},
+
+
+                        {name: 'inventory', value: '盘点总数量', class: "td-warm"},
+                        {name: 'inventoryProfit', value: '盘盈数量', class: "td-warm"},
+                        {name: 'inventoryLoss', value: '盘亏数量', class: "td-warm"},
+                    ];
+                    new Header({
+                        el: "table",
+                        name: "details",
+                        column: column,
+                        data: this.details.data,
+                        restorationColumn: 'id',
+                        fixedTop: ($('#form_div').height()) + ($('#btn').height()) + 2,
+                        before: [
+                            {colspan: '13', value: '生产部-入库数据', class: "table-header-layer-1"},
+                            {
+                                colspan: '10',
+                                value: '生产部-发货数据',
+                                font: "fa fa-file-text-o",
+                                class: "table-header-layer-1"
+                            },
+                            {colspan: '4', value: '生产部-库存数据', font: "fa fa-truck", class: "table-header-layer-1"},
+                        ],
+                    }).init();
+                },
+            },
+        });
+    </script>
+@endsection

+ 2 - 2
resources/views/order/wave/_printBody.blade.php

@@ -1,7 +1,7 @@
-<div class="container" style="min-width: 400px;min-height: 600px" id="printContent" v-show="infoShow">
+<div class="container"  id="printContent" v-show="infoShow">
     <div class="card">
         <div class="card-body mt-4 text-center" v-for="(value, key) in splitGroupBySize">
-            <div v-for="index in value"><img class="mt-1" :id="key+'-'+index" alt="#" src="#"></div>
+            <div v-for="index in value" style="width: 100vw;height: 100vh"><img class="mt-1" style="width: 100vw" :id="key+'-'+index" alt="#" src="#"></div>
         </div>
     </div>
 </div>

+ 5 - 0
resources/views/order/wave/_split.blade.php

@@ -7,8 +7,13 @@
             </div>
             <div class="modal-body">
                 <div class="form-group m-5">
+                    <label class="label">按订单大小</label>
                     <input class="form-control" type="number" step="1" v-model="splitSize" placeholder="子波次大小">
                 </div>
+                <div class="form-group m-5">
+                    <label class="label">按波次数量</label>
+                    <input class="form-control" type="number" step="1" v-model="batchNumber" placeholder="子波次大小">
+                </div>
             </div>
             <div class="modal-footer">
                 <button class="col-12 btn btn-primary" @click="splitBatch()">确定</button>

+ 41 - 19
resources/views/order/wave/picking.blade.php

@@ -3,7 +3,7 @@
 @section('content')
     <div id="container" class="d-none container-fluid mt-2">
         <div class="card">
-            <div class="card-header">
+            <div class="card-header m-0">
                 <b>波次信息</b>
                 <button  class="btn text-white btn-sm btn-info pull-right" @click="isShow=!isShow" data-toggle="collapse" data-target="#body">@{{ isShow ? '隐藏' : '显示' }}</button>
             </div>
@@ -19,18 +19,19 @@
                 </div>
             </div>
             <div class="card mt-2">
-                <div class="card-header row m-0">
+                <div class="card-header row m-0 p-0">
                     <b class="col-4">分拣信息</b>
-                    <input id="barcode" v-model="barcode" @keydown.enter="searchBarcode()" class="form-control form-control-sm rounded-pill col-6 offset-2" placeholder="条码"></input>
+                    <input id="barcode" v-model="barcode" @keydown.13="searchBarcode()" class="form-control form-control-sm rounded-pill col-6 offset-2" placeholder="条码"></input>
                 </div>
                 <div class="card-body">
-                    <div class="row border-info" style="height:60vh;overflow-y: auto">
-                        <div class="col-5 m-2 p-0" style="height: 80px;border: 1px solid #aaaaaa;z-index:100;position:relative;" v-for="index in waves.length"
-                             :style="[waveQtyMap['_'+(index-1)] && waveQtyMap['_'+(index-1)]>0 ? {boxShadow: '0 0 5px 5px rgba(19,193,137)'} : '']">
-                            <div class="text-center small font-weight-bold text-secondary">@{{ batch+'-'+index }}</div>
-                            <div style="display:flex;align-items:center;justify-content:center;" class="w-100 h-75 text-primary font-weight-bold">
-                                @{{ waveQtyMap['_'+(index-1)] ? waveQtyMap['_'+(index-1)] : '0' }}
+                    <div class="row border-info p-0" style="height:65vh;overflow-y: auto">
+                        <div class="col-4 m-0 p-1" style="height: 55px;border: 1px solid #aaaaaa;z-index:100;position:relative;" v-for="index in waves.length"
+                             :style="[waveQtyMap['_'+(index-1)] && waveQtyMap['_'+(index-1)].sum>0 ? {boxShadow: colorPool[colorIndex]+' 0 0 5px 5px inset'} : '']">
+                            <div class="text-center small font-weight-bold h-25 text-secondary">@{{ 'W-'+index }}</div>
+                            <div style="display:flex;align-items:center;justify-content:center;" class="w-100 h-50 text-primary font-weight-bold">
+                                @{{ waveQtyMap['_'+(index-1)] ? waveQtyMap['_'+(index-1)].sum : '0' }}
                             </div>
+                            <div class="text-center small font-weight-bold h-25 text-muted mb-1">@{{ waveQtyMap['_'+(index-1)] ? waveQtyMap['_'+(index-1)].lot : '0' }}</div>
                         </div>
                     </div>
                 </div>
@@ -52,9 +53,14 @@
             el:"#container",
             data:{
                 batch:"",
+                barcode:"",
                 isShow:false,
                 waves:[],
                 waveQtyMap:{},
+                colorIndex:0,
+                colorPool:[
+                    "RGB(224,41,43)","rgba(19,193,137)","RGB(97,179,233)"
+                ]
             },
             mounted:function(){
                 this.pageInit();
@@ -90,17 +96,33 @@
                 },
                 searchBarcode(){
                     let waveQtyMap = {};
-                    this.waves.forEach((wave,i)=>{
-                        wave.forEach(order=>{
-                            if (order.barcode === this.barcode){
-                                if (waveQtyMap['_'+i]===undefined)waveQtyMap['_'+i] = 1;
-                                else waveQtyMap['_'+i]++;
-                            }
+                    try {
+                        this.waves.forEach((wave,i)=>{
+                            wave.forEach(order=>{
+                                if (order.barcode === this.barcode){
+                                    if (order.scanSign!==undefined){
+                                        throw new Error("unique");
+                                    }
+                                    order.scanSign = true;
+                                    if (waveQtyMap['_'+i]===undefined){
+                                        waveQtyMap['_'+i] = {"sum":order.qty,"lot":order.location};
+                                    } else waveQtyMap['_'+i].sum += order.qty;
+                                }
+                            })
                         })
-                    })
-                    this.waveQtyMap = waveQtyMap;
-                    this.barcode = "";
-                    $("#barcode").focus();
+                    }catch (e){
+                        window.tempTip.setDuration(2000);
+                        window.tempTip.setIndex(999);
+                        window.tempTip.show("重复扫描");
+                        return;
+                    }finally {
+                        this.waveQtyMap = waveQtyMap;
+                        let el = $("#barcode");
+                        el.focus();
+                        el.select();
+                    }
+                    if (this.colorIndex===this.colorPool.length-1)this.colorIndex = 0;
+                    else this.colorIndex++;
                 },
             }
         });

+ 10 - 6
resources/views/order/wave/search.blade.php

@@ -138,6 +138,7 @@
                 selectTr:'',
                 batchCodes:"",
                 splitSize:"",
+                batchNumber:"",
                 infoShow:false,
                 splitGroupBySize:{},
             },
@@ -286,15 +287,19 @@
                 },
                 splitBatch(){
                     window.tempTip.setDuration(2000);
+                    window.tempTip.setIndex(999);
                     if (this.checkData.length<1){
                         window.tempTip.show("未选中记录行");
                         return;
                     }
-                    if (!this.splitSize){
+                    if (!this.splitSize && !this.batchNumber){
                         window.tempTip.show("未输入分割大小");
                         return;
                     }
-                    window.tempTip.postBasicRequest("{{url('order/wave/split')}}",{codes:this.checkData,split:this.splitSize},res=>{})
+                    window.tempTip.postBasicRequest("{{url('order/wave/split')}}",{codes:this.checkData,split:this.splitSize,number:this.batchNumber},res=>{
+                        $("#splitBatch").modal('hide');
+                        return "分割成功";
+                    },true)
                 },
                 exePrint(){
                     window.tempTip.setDuration(2000);
@@ -304,17 +309,16 @@
                     }
                     window.tempTip.postBasicRequest("{{url('order/wave/printChild')}}",{codes:this.checkData},res=>{
                         this.splitGroupBySize = res;
-                        this.infoShow = true;
                         setTimeout(()=>{
                             for(let key  in this.splitGroupBySize){
                                 for (let i=1;i<=this.splitGroupBySize[key];i++){
-                                    window.setBarcode(key+'-'+i, "#"+key+"-"+i, 3, 70, true)
+                                    window.setBarcode(key+'-'+i, "#"+key+"-"+i, 2, 50, true)
                                 }
                             }
-                        },100);
+                        },10);
                         setTimeout(()=>{
                             exe();
-                        },200);
+                        },50);
                     })
                     let exe = ()=>{
                         let iframe=document.getElementById("print-iframe");

+ 1 - 1
resources/views/personnel/laborApply/create.blade.php

@@ -13,7 +13,7 @@
                    2 禁止开放
                    3 临时开放
                 -->
-                @can('人事管理')
+                @can('人事管理-临时工申请协调-录入-临时开放')
                     <form v-if="can_create_status === 2" action="{{ route('laborApply.temporaryOpen') }}" method="post"
                           accept-charset="UTF-8">
                         {{ csrf_field() }}

+ 1 - 1
resources/views/personnel/laborApply/dispatch/index.blade.php

@@ -42,7 +42,7 @@
                                 </a>
                             </div>
                         @endcan()
-                        @can('人事管理')
+                        @can('临时工申请协调-劳务派遣明细-人事确认')
                             <div class="float-left ml-3" v-if="labor_company_dispatch.status==='创建'">
                                 <form :action="getBaseUrl(labor_company_dispatch) + '/personnelCheck'" method="post"
                                       accept-charset="UTF-8" onsubmit="return confirm('是否确认!')">

+ 1 - 1
resources/views/personnel/laborApply/index.blade.php

@@ -6,7 +6,7 @@
         <div class="container-fluid">
             <div id="form_div"></div>
             <div class="ml-3 form-inline" id="btn">
-                @can('人事管理')
+                @can('临时工申请协调-查看-重新生成劳务派遣数据')
                     <span class="ml-1">
                         <a title="00:00 - 01:00 禁止生成数据" href="{{ route('laborApply.createDispatch') }}" type="button"
                            class="btn btn-sm ml-2 btn-outline-danger">重新生成劳务派遣数据</a>

+ 12 - 7
resources/views/personnel/laborReport/index.blade.php

@@ -105,13 +105,13 @@
                                                 @can('人事管理-门卫审核')
                                                     <span >
                                 <b v-if="laborReport.isAdult==1"   class="text-danger">童工</b>
-                                <b v-else-if="laborReport.userDutyCheckVerifyUserId{{--&&laborReport.amountOfJoined==1--}}"   class="text-success">已审核</b>
+                                <b v-else-if="laborReport.userDutyCheckVerifyUserId&&laborReport.amountOfJoined==1"   class="text-success">已审核</b>
                                 <b v-else-if="laborReport.userDutyCheckVerifyUserId&&laborReport.amountOfJoined&&laborReport.sequence"  class="text-black">&nbsp;&nbsp;&nbsp;@{{laborReport.sequence}}/@{{laborReport.amountOfJoined}}</b>
                                 <button v-else style="transform:scale(1.1)" class="btn btn-lg btn-outline-secondary"  @click="guardClockAudit(laborReport.id,laborReport.user_duty_check_id)">门卫审核</button>
                                 </span>
                                                 @else
                                                     <b v-if="laborReport.isAdult==1"   class="text-danger">童工</b>
-                                                    <b v-else-if="laborReport.userDutyCheckVerifyUserId{{--&&laborReport.amountOfJoined==1--}}"  class="text-success">已审核</b>
+                                                    <b v-else-if="laborReport.userDutyCheckVerifyUserId&&laborReport.amountOfJoined==1"  class="text-success">已审核</b>
                                                     <b v-else-if="laborReport.userDutyCheckVerifyUserId&&laborReport.amountOfJoined&&laborReport.sequence"  class="text-black">&nbsp;&nbsp;&nbsp;@{{ laborReport.sequence }}/@{{ laborReport.amountOfJoined }}</b>
                                                     <span v-else class="text-center"><b class="text-danger">门卫未审核</b></span>
                                                 @endcan
@@ -325,11 +325,12 @@
                     let tokenOfBroadcastEnterAndLeave='{{$tokenOfBroadcastEnterAndLeave}}';
                     if(tokenOfBroadcastEnterAndLeave){
                         Echo.channel('{{$laravelEchoPrefix}}'+tokenOfBroadcastEnterAndLeave).listen('ImportEvent',(e)=>{
-                            // let labor=e.laborReport;
-                            // laborReports.push(labor);
-                            setTimeout(function () {
-                                window.location.reload();
-                            },500);
+                            let labor=e.laborReport;
+                            laborReports.unshift(labor);
+
+                            // setTimeout(function () {
+                            //     window.location.reload();
+                            // },500);
                         });
                     }
                     //退场
@@ -357,6 +358,7 @@
                             if (laborReport.user_duty_check_id==userDutyCheck.id){
                                 laborReport.userDutyCheckVerifyUserId=userDutyCheck.verify_user_id;
                                 laborReport.user_duty_check_id=userDutyCheck.id;
+                                laborReport.amountOfJoined=1;
                                 return false
                             }
                             return true;
@@ -382,6 +384,7 @@
                     _this.permittingWorkgroups.forEach(function(workgroup){
                         Echo.channel('{{$laravelEchoPrefix}}'+workgroup.token).listen('ClockinEvent',(e)=>{
                             // let res=false;
+                            // let labor=e.laborReport;
                             // laborReports.forEach(function (item){
                             //     if(item.id==labor.id){
                             //         res=true;
@@ -405,6 +408,7 @@
                             //     labor.has_group_verify_right=labor.has_group_verify_right;
                             //     laborReports.push(labor);
                             // }
+
                             setTimeout(function () {
                                 window.location.reload();
                             },500);
@@ -604,6 +608,7 @@
                                 _this.laborReports.every(function (laborReport) {
                                     if (laborReport.id==id){
                                         laborReport.userDutyCheckVerifyUserId=response.data.data;
+                                        laborReport.amountOfJoined=1;
                                         tempTip.setDuration(1000);
                                         tempTip.showSuccess('审核通过!');
                                         return false

+ 31 - 0
resources/views/store/countGoodsAndReceive/excel.blade.php

@@ -0,0 +1,31 @@
+@extends('layouts.app')
+@section('title')点收一体-表格@endsection
+
+
+@section('content')
+    <div class="container">
+        <div class="row mt-2">
+            <div class="col-12">
+                <p><span class="h4">Excel文件列表</span><span class="text-muted">(仅保留三个月以内的文件)</span></p>
+                <table class="table table-striped" >
+                    <tr>
+                        <th>序号</th>
+                        <th>名称</th>
+                        <th>时间</th>
+                        <th>条目数</th>
+                        <th>文件下载</th>
+                    </tr>
+                    @foreach($excels as $i=>$excel)
+                        <tr>
+                            <td>{{$i+1}}</td>
+                            <td>{{$excel['name']}}</td>
+                            <td>{{$excel['created_at']}}</td>
+                            <td>{{$excel['goods_amount']}}</td>
+                            <td><a href="{{asset('storage/'.$excel['file'])}}"><span class="fa fa-download"></span><span class="fa fa-download"></span><span class="fa fa-download"></span></a></td>
+                        </tr>
+                    @endforeach
+                </table>
+            </div>
+        </div>
+    </div>
+@endsection

+ 516 - 0
resources/views/store/countGoodsAndReceive/index.blade.php

@@ -0,0 +1,516 @@
+@extends('layouts.app')
+@section('title')点收一体@endsection
+
+@section('content')
+    <div class="d-none" id="container">
+        <audio src="{{asset('sound/warning_otherBarcode.mp3')}}" controls="controls" preload id="soundWarning" hidden>
+        </audio>
+        <audio src="{{asset('sound/ding.mp3')}}" controls="controls" preload id="soundDing" hidden>
+        </audio>
+        <div class="row">
+            <div class="col-4 p-0 m-0" id="countGoods">
+                <div class="col-12 text-center bg-white mt-2">
+                    <h4 class="font-weight-bold text-dark">清点模式</h4>
+                </div>
+                    <div class="card-body">
+                            <div class="row pl-5">
+                                <div class="col-6">
+                                    <label class="text-left font-weight-bold text-muted">条码</label>
+                                    <input type="text" id="barcode" class="form-control" :disabled="status.barcodeDisable" placeholder="扫入条码"
+                                           @focusin="focusOutDocument" @focusout="focusDocument" v-model="inputting.barcode">
+                                </div>
+
+                                <div v-if="inputMode==='sweepModel'" class="col-6">
+                                    <label class="text-left font-weight-bold text-muted">已扫数量</label>
+                                    <input type="number" id="amount" class="form-control mt-0" placeholder="" :disabled="status.amountDisable"
+                                           v-model="inputting.amount" style='height: 40px;font-size: 1.6em;color:blue;font-weight: bolder;padding: 3px;text-align: center'>
+                                </div>
+                            </div>
+                        <p class="card-text text-muted mt-3 mb-n3 text-center">已完成:</p>
+                        <hr>
+                        <table class="table table-sm table-striped table-bordered" v-if="goodses.length>0">
+                            <tr>
+                                <th class="text-center">条码</th>
+                                <th class="text-center">数量</th>
+                                <th class="text-center">箱规</th>
+                                <th class="text-center">操作</th>
+                            </tr>
+                            <tr v-for="(goods,i) in goodses" :id="'tr_'+i">
+                                <td class="text-center">@{{ goods.barcode }}</td>
+                                <td class="text-center">@{{ goods.amount }}</td>
+                                <td class="text-center">
+                                    <span v-if="goods.cast_number">第@{{ goods.cast_number }}箱</span>
+                                </td>
+                                <td class="text-center">
+                                    <span v-if="goods.countGoodStatus">
+                                        <button class="btn btn-outline-info btn-sm" @click="countGoods(i,goods.barcode)">完成清点</button>
+                                    </span>
+                                    <button class="btn btn-outline-danger btn-sm" @click="removeGoods($event,goods.barcode)">删</button>
+                                </td>
+                            </tr>
+                        </table>
+                        <hr>
+                        <span class="btn btn-outline-dark btn form-control" style="cursor: pointer" @click="submitExcelData">结束清点</span>
+                    </div>
+            </div>
+            <div class="col-8 p-0 m-0" id="receive">
+                <div class="col-12 text-center bg-white mt-2">
+                    <h4 class="font-weight-bold text-dark">收货模式</h4>
+                </div>
+                <div class="card-body m-0">
+                        <div class="col-8 offset-2 row">
+                             <label for="asnno" class="font-weight-bold text-muted ">输入ASN</label>
+                            <input type="text" id="asnno" class="form-control" @focusin="focusOutDocument" autocomplete="off"
+                                   @change="getReceiveTaskByAsnNoAndBarcodes()" disabled="true" placeholder="ASN单号" v-model="asnno">
+                        </div>
+                    <table class="table table-sm table-striped" v-if="regroupGoods.length>0">
+                        <hr>
+                        <tr>
+                            <th class="text-center">货主</th>
+                            <th class="text-center">条码</th>
+                            <th class="text-center">清点数量</th>
+                            <th class="text-center">ASN数量</th>
+                            <th class="text-center">差值</th>
+                            <th class="text-center">容器号</th>
+                            <th class="text-center">生产日期</th> <!--lotatt01-->
+                            <th class="text-center">失效日期</th> <!--lotatt02-->
+                            <th class="text-center">批号</th>    <!--lotatt04-->
+                            <th class="text-center">属性仓</th>  <!--lotatt05-->
+                            <th class="text-center">质量状态</th> <!--lotatt08-->
+                            <th class="text-center">入库日期</th> <!--lotatt03-->
+                            <th class="text-center">操作</th>
+                        </tr>
+                        <tr v-for="(goods,i) in regroupGoods">
+                            <td class="text-center">@{{ goods.customerid }}</td>
+                            <td class="text-center">@{{ goods.sku }}</td>
+                            <td class="text-center">@{{ goods.amount }}</td>
+                            <td class="text-center">@{{ goods.asn_amount }}</td>
+                            <td class="text-center">@{{ goods.diff_val }}</td>
+
+                            <td class="text-center">
+                                <span v-if="goods.receiveStatus">
+                                    <input type="text" autocomplete="off" class="form-control form-control-sm" :class="errors.trackNumber ? 'is-invalid' : ''"
+                                           id="trackNumber" v-model="goods.trackNumber">
+                                    <span class="invalid-feedback offset-3" role="alert" v-if="errors.trackNumber">
+                                        <strong>@{{ errors.trackNumber[0] }}</strong>
+                                    </span>
+                                </span>
+                            </td>
+
+                            <td class="text-center">
+                                <span v-if="goods.basSku.lot_id">
+                                    <span v-if="goods.basSku.lot_id.lotkey01==='Y'">
+                                        <input type="date" autocomplete="off" class="form-control form-control-sm input-sm" :class="errors.lotatt01 ? 'is-invalid' : ''"
+                                                 id="lotatt01" v-model="goods.lotatt01">
+                                     <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt01">
+                                        <strong>@{{ errors.lotatt01[0] }}</strong>
+                                    </span>
+                                    </span>
+                                </span>
+                            </td>
+                            <td class="text-center">
+                               <span v-if="goods.basSku.lot_id">
+                                   <span v-if="goods.basSku.lot_id.lotkey02==='Y'">
+                                       <input type="date" autocomplete="off" class="form-control form-control-sm input-sm" :class="errors.lotatt02 ? 'is-invalid' : ''"
+                                              id="lotatt02" v-model="goods.lotatt02">
+                                    <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt02">
+                                        <strong>@{{ errors.lotatt02[0] }}</strong>
+                                    </span>
+                                   </span>
+                                </span>
+                            </td>
+                            <td class="text-center">
+                                <span v-if="goods.basSku.lot_id">
+                                    <span v-if="goods.basSku.lot_id.lotkey04==='Y'">
+                                    <input type="text" autocomplete="off" class="form-control form-control-sm input-sm" :class="errors.lotatt04 ? 'is-invalid' : ''"
+                                             id="lotatt04" v-model="goods.lotatt04">
+                                     <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt04">
+                                        <strong>@{{ errors.lotatt04[0] }}</strong>
+                                    </span>
+                                    </span>
+                                </span>
+                            </td>
+                            <td class="text-center">
+                                <span v-if="goods.basSku.lot_id">
+                                    <span v-if="goods.basSku.lot_id.lotatt05==='Y'">
+                                    <select class="form-control form-control-sm" :disabled="goods.basSku.lot_id.lotkey05==='N'"
+                                            id="lotatt05" v-model="goods.lotatt05" :class="errors.lotatt05 ? 'is-invalid' : ''">
+                                        <option v-for="(attributeLocation,i) in attributeLocations"
+                                            :value="attributeLocation.code">@{{ attributeLocation.codename_c }}</option>
+                                    </select>
+                                     <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt05">
+                                        <strong>@{{ errors.lotatt05[0] }}</strong>
+                                    </span>
+                                    </span>
+                                </span>
+                            </td>
+                            <td class="text-center">
+                                <span v-if="goods.basSku.lot_id">
+                                     <span v-if="goods.basSku.lot_id.lotkey08==='Y'">
+                                     <select class="form-control form-control-sm" :class="errors.lotatt08 ? 'is-invalid' : ''"
+                                              id="lotatt08" v-model="goods.lotatt08">
+                                        <option v-for="(quality,i) in qualityStatus"  :value="quality.code">@{{ quality.codename_c }}</option>
+                                    </select>
+                                     <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt08">
+                                        <strong>@{{ errors.lotatt08[0] }}</strong>
+                                    </span>
+                                     </span>
+                                </span>
+                            </td>
+                            <td class="text-center">
+                                <span v-if="goods.basSku.lot_id">
+                                    <span v-if="goods.basSku.lot_id.lotkey03==='Y'">
+                                    <input type="date" autocomplete="off" class="form-control form-control-sm input-sm" :class="errors.lotatt03 ? 'is-invalid' : ''"
+                                           :disabled="goods.basSku.lot_id.lotkey03==='N'"  id="lotatt03" v-model="goods.lotatt03">
+                                     <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt03">
+                                        <strong>@{{ errors.lotatt03[0] }}</strong>
+                                    </span>
+                                    </span>
+                                </span>
+                            </td>
+                            <td class="text-center">
+                                <span v-if="goods.receiveStatus&&goods.diff_val>=0">
+                                    <button class="btn btn-outline-info btn-sm" @click="receiveGoods(goods)">收</button>
+                                </span>
+                            </td>
+                        </tr>
+                    </table>
+                    <span class="btn btn-outline-dark btn form-control mt-5" v-if="status.finishReceiveButton"
+                          style="cursor: pointer" @click="finishReceive()">结束收货</span>
+                </div>
+            </div>
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        new Vue({
+            el: '#app',
+            data:{
+                qualityStatus:{!! $qualityStatus !!},
+                attributeLocations:{!! $attributeLocations !!},
+                focusing:'document',
+                lastScannedBarcode:'',
+                inputMode:'sweepModel',
+                inputting:{
+                    barcode:'',amount:'',fromIncreasing:true,cast_number:'',countGoodStatus:true
+                },
+                status:{
+                    scanEndInputted:false,barcodeDisable:true,amountDisable:true,finishReceiveButton:false,
+                },
+                asnno:'',
+                basSku:{
+                    lot_id:'',
+                },
+                goodses:[],
+                initGoods:[],
+                regroupGoods:[],
+                errors:{},
+            },
+            mounted() {
+                if (navigator.userAgent.indexOf("Android")!==-1)this.isAndroid = true;
+                this.pageInit();
+                $("#container").removeClass("d-none");
+                this.scanListening();
+            },
+            methods: {
+                //页面初始化
+                pageInit(){
+                    if (!this.isAndroid)return;
+                    let element = document.getElementById("navbarSupportedContent").parentElement;
+                    element.className = "row";
+                    element.children[0].className += " col-5";
+                    element.innerHTML = element.children[0].outerHTML;
+                    let e1 = document.getElementById("menu");
+                    let e2 = document.getElementById("demand-div");
+                    if (e1)e1.remove();
+                    if (e2)e2.remove();
+                },
+                focusDocument: function () {
+                    this.focusing = 'document';
+                },
+                focusOutDocument: function () {
+                    this.focusing = '';
+                },
+                scanListening: function () {
+                    let data = this;
+                    $(document).on('keypress', function (e) {
+                        if(data.focusing!=='document'){return}
+                        if (e.keyCode !== 13) {
+                            if(data.status.scanEndInputted){
+                                data.lastScannedBarcode=data.inputting.barcode;
+                                data.inputting.barcode='';
+                                data.status.scanEndInputted=false;
+                            }
+                            data.inputting.barcode += String.fromCharCode(e.keyCode);
+                        } else {
+                            if(data.inputting.barcode.length<=1){
+                                window.tempTip.setDuration(4500);
+                                window.tempTip.show('未扫入条码,请检查扫码枪设置,尝试调至“直接键盘输出”模式');
+                                return;
+                            }
+                            data.status.scanEndInputted = true;
+                            switch(data.inputMode){
+                                case 'sweepModel': data.commitGoodsOnSweepModel();break;
+                            }
+                        }
+                    });
+                },
+                commitGoodsOnSweepModel(){
+                    let repeatedBarcode=this.repeatedIncreasingBarcodeFromSaved();
+                    if(!repeatedBarcode){
+                        this.focusOutDocument();
+                        this.alertVibrate();
+                        this.inputting.amount=1;
+                        this.goodses.unshift(JSON.parse(JSON.stringify(this.inputting)));
+                        window.tempTip.setDuration(500);
+                        window.tempTip.showSuccess('保存成功');
+                        this.focusDocument();
+                        this.audioDing();
+                    }else{
+                        repeatedBarcode.amount++;
+                        this.inputting.amount=repeatedBarcode.amount;
+                        window.tempTip.setDuration(500);
+                        window.tempTip.showSuccess(repeatedBarcode.amount);
+                        this.focusDocument();
+                        this.audioDing();
+                    }
+                },
+                audioDing: function () {
+                    let audio = document.getElementById('soundDing');
+                    audio.currentTime = 0;//重新播放
+                    audio.play();// 播放
+                    function startVibrate(duration) {
+                        if (navigator.vibrate) {
+                            navigator.vibrate(duration);
+                        } else if (navigator.webkitVibrate) {
+                            navigator.webkitVibrate(duration);
+                        }
+                    }
+                    startVibrate(500);
+                },
+                alertVibrate: function () {
+                    function startVibrate(duration) {
+                        if (navigator.vibrate) {
+                            navigator.vibrate(duration);
+                        } else if (navigator.webkitVibrate) {
+                            navigator.webkitVibrate(duration);
+                        }
+                    }
+                    let vibrateInterval = setInterval(function() {
+                        startVibrate(150);
+                    }, 50);
+                    setTimeout(function() {
+                        clearInterval(vibrateInterval)
+                    }, 2000);
+                },
+                repeatedIncreasingBarcodeFromSaved: function () {
+                    let data = this;
+                    let repeatedGoods=null;
+                    data.goodses.every(function(goods){
+                        if(goods.barcode===data.inputting.barcode && goods.fromIncreasing && goods.countGoodStatus){
+                            repeatedGoods=goods;
+                            return false;
+                        }
+                        return true;
+                    });
+                    return repeatedGoods;
+                },
+                cleanInputs: function () {
+                    this.inputting.barcode='';
+                    this.inputting.amount='';
+                    this.inputting.cast_number='';
+                    this.lastScannedBarcode='';
+                },
+                countGoods: function (i,barcode) {
+                    if(!confirm('确定要结束清点'+barcode+'的记录吗'))return;
+                    let data = this;
+                    let cast_number=0;
+                    data.goodses.forEach(function (goods) {
+                        if (goods.barcode===barcode)cast_number++
+                    });
+
+                    data.goodses.every(function(goods,i){
+                        if(goods.barcode===barcode &&goods.countGoodStatus){
+                            goods.countGoodStatus=false;
+                            goods.cast_number=cast_number;
+                            return false;
+                        }
+                        return true;
+                    })
+
+                    $('#tr_'+i).attr("class",'alert alert-dark');
+                },
+                removeGoods: function ($e,barcode) {
+                    if(!confirm('确定要删除条码为'+barcode+'的记录吗'))return;
+                    let data = this;
+                    data.goodses.every(function(goods,i){
+                        if(goods.barcode===barcode){
+                            data.goodses.splice(i,1)
+                            return false;
+                        }
+                        return true;
+                    })
+                },
+                regroupArr(arr){
+                    let a =JSON.parse(JSON.stringify(arr));
+                    return a.reduce((total, cur, index) => {
+                        let hasValue = total.findIndex(current => {
+                            return current.barcode === cur.barcode
+                        })
+                        hasValue === -1 && total.push(cur)
+                        hasValue !== -1 && (total[hasValue].amount = total[hasValue].amount + cur.amount)
+                        return total
+                    }, []);
+                },
+                assignRegroupGoods(){
+                    let data=this;
+                    data.initGoods=data.regroupArr(data.goodses);
+                    data.initGoods.forEach(function (obj){
+                        delete obj.fromIncreasing;
+                        delete obj.cast_number;
+                        delete obj.countGoodStatus;
+                        obj.asnno='';obj.customerid='';
+                        obj.location='';obj.asn_amount='';
+                        obj.diff_val='';obj.receiveStatus=false;
+                        obj.basSku=data.basSku;obj.asnlineno='';
+                        obj.lotatt01='';obj.lotatt02='';
+                        obj.lotatt03='';obj.lotatt04='';
+                        obj.lotatt05='';obj.lotatt08='';
+                    })
+                    data.initGoods=JSON.parse(JSON.stringify(data.initGoods).replace(/barcode/g,"sku"));
+                    data.regroupGoods=data.initGoods;
+                },
+                receiveGoods(goods){
+                    let data=this;
+                    this.errors={};
+                    this.checkGood(goods);
+                    if (JSON.stringify(this.errors)!=='{}')return;
+                    goods.asnno=data.asnno;
+                    tempTip.setDuration(99999);
+                    tempTip.waitingTip('提交中');
+                    let url='{{url("store/countGoodsAndReceive/fluxReceive")}}';
+                    axios.post(url,{good:goods})
+                        .then(function(res){
+                            if(res.data.success){
+                                data.regroupGoods.forEach(function (good,i){
+                                    if (goods.sku==good.sku){
+                                        data.regroupGoods.splice(i,1)
+                                    }
+                                })
+                                tempTip.setDuration(2000);
+                                tempTip.cancelWaitingTip();
+                                tempTip.showSuccess(res.data.data);
+                            }else{
+                                tempTip.setDuration(3000);
+                                tempTip.cancelWaitingTip();
+                                tempTip.show(res.data.data);
+                                data.alertVibrate()
+                            }
+                        })
+                        .catch(function (err) {
+                            tempTip.setDuration(2000);
+                            tempTip.cancelWaitingTip();
+                            tempTip.show("网络错误:"+err);
+                            data.alertVibrate()
+                        });
+                },
+                checkGood(good){
+                    let error = {};
+                    if (!good.trackNumber)error.trackNumber = ["容器号必填"];
+                    if (good.basSku.lot_id && good.basSku.lot_id.lotkey01==='Y' && !good.lotatt01) error.lotatt01=["生产日期为选"];
+                    if (good.basSku.lot_id && good.basSku.lot_id.lotkey02==='Y' && !good.lotatt02) error.lotatt02=["失效日期为选"];
+                    if (good.basSku.lot_id && good.basSku.lot_id.lotkey03==='Y' && !good.lotatt03) error.lotatt03=["入库日期为选"];
+                    if (good.basSku.lot_id && good.basSku.lot_id.lotkey04==='Y' && !good.lotatt04) error.lotatt04=["批号未填"];
+                    if (good.basSku.lot_id && good.basSku.lot_id.lotkey05==='Y' && !good.lotatt05) error.lotatt05=["属性仓未选"];
+                    if (good.basSku.lot_id && good.basSku.lot_id.lotkey08==='Y' && !good.lotatt08) error.lotatt08=["质量状态未选"];
+                    if (JSON.stringify(error)!=='{}'){this.errors = error;}
+                },
+                getReceiveTaskByAsnNoAndBarcodes(){
+                    let data=this;
+                    data.regroupGoods=data.initGoods;//验证asn下商品时 初始商品数据
+                    if(data.asnno===''||data.asnno===null||data.asnno===undefined) window.tempTip.show('请先输入ASN单号!');
+                    if (data.asnno && data.asnno.indexOf('ASN')===-1)window.tempTip.show('无效ASN号!');
+                    let url='{{url("store/countGoodsAndReceive/getReceiveTaskByAsnNoAndBarcodes")}}';
+                    window.axios.post(url,{asnno:data.asnno,goods:data.initGoods})
+                        .then(res=>{
+                            if (res.data.success){
+                                data.regroupGoods=res.data.data;
+                                this.$forceUpdate()
+                            }else {
+                                tempTip.setDuration(3000);
+                                tempTip.show(res.data.data);
+                            }
+                        }).catch(err=>{
+                        window.tempTip.setDuration(2000);
+                        window.tempTip.show("网络错误:"+err);
+                    })
+                },
+                removeDisable(){
+                    let asnNo=$('#asnno');
+                    asnNo.removeAttr('disabled');
+                    this.status.finishReceiveButton=true;
+                    asnNo.focus();
+                },
+                submitExcelData: function () {
+                    let data = this;
+                    data.focusOutDocument();
+                    if(data.goodses.length===0){
+                        window.tempTip.show('请先录入数据再提交收货');return;
+                    }
+                    window.tempTip.confirm('请检查表格,确定全部完成。',
+                        function () {
+                            window.tempTip.setInputType('input');
+                            window.tempTip.setIndex(999999);
+                            window.tempTip.inputVal('收货前将上传excel文件,请输入文件名:',function(val){
+                                if(val===''){
+                                    window.tempTip.setDuration(2500);
+                                    window.tempTip.show('失败!文件名不能为空,请重新点击生成');
+                                    return;
+                                }
+                                window.tempTip.setDuration(15500);
+                                window.tempTip.waitingTip('提交Excel中...');
+                                let expireHandler = setTimeout(function () {
+                                    window.tempTip.cancelWaitingTip();
+                                    window.tempTip.setDuration(1500);
+                                    window.tempTip.show('响应超时! 请检查网络,确保可以连接后再重试。');
+                                },9000);
+                                let url='{{url("store/countGoodsAndReceive/createExcel")}}';
+                                axios.post(url,{'goodses':data.goodses,'filename':val})
+                                    .then(function(response){
+                                        if(response.data.result==='success'){
+                                            data.removeDisable();//收货解锁asnno input标签
+                                            data.assignRegroupGoods();//结束清点,重组收货所需数据
+                                            data.goodses=[];
+                                            data.cleanInputs();
+                                            window.tempTip.cancelWaitingTip();
+                                            window.tempTip.setDuration(1500);
+                                            window.tempTip.showSuccess('成功生成EXCEL,可在列表页查看');
+                                        }else{
+                                            window.tempTip.setDuration(1500);
+                                            window.tempTip.show('生成EXCEL失败');
+                                            data.focusDocument();
+                                            data.alertVibrate()
+                                        }
+                                        clearInterval(expireHandler);
+                                    })
+                                    .catch(function (err) {
+                                        window.tempTip.setDuration(3500);
+                                        window.tempTip.show('网络或系统错误,请将以下信息提交给开发者:'+err);
+                                        clearInterval(expireHandler);
+                                        data.alertVibrate();
+                                    });
+                            });
+                        },function () {
+                            data.focusDocument();
+                        })
+                },
+                finishReceive(){
+                    if(!confirm('确定要结束收货吗?'))return;
+                    setTimeout(function (){window.location.reload()},10)
+                }
+            },
+        });
+    </script>
+@endsection

+ 16 - 0
routes/web.php

@@ -545,6 +545,7 @@ Route::group(['prefix'=>'package'],function(){
             Route::post('changeAsnRule','StorageController@changeAsnRule');
             Route::post('callRobot','StorageController@callRobot');
         });
+        /** 手持入库 */
         Route::group(['prefix'=>'handInStorage'],function() {
             Route::get('receive',function (){return view('store.handInStorage.receive');});//收货页面
             Route::get('putaway',function (){return view('store.handInStorage.putaway');});//上架页面
@@ -561,6 +562,14 @@ Route::group(['prefix'=>'package'],function(){
             Route::post('handFluxPa','HandInStorageController@handFluxPa');
             Route::get('receiveDetailPage/{asnno}/{customerid}','HandInStorageController@receiveDetailPage');
         });
+
+        Route::group(['prefix'=>'countGoodsAndReceive'],function() {
+            Route::get('index', 'StoreCountGoodsAndReceiveController@index');
+            Route::get('excel', 'StoreCountGoodsAndReceiveController@excel');
+            Route::post('createExcel', 'StoreCountGoodsAndReceiveController@createExcel');
+            Route::any('fluxReceive','StoreCountGoodsAndReceiveController@fluxReceive');
+            Route::post('getReceiveTaskByAsnNoAndBarcodes', 'StoreCountGoodsAndReceiveController@getReceiveTaskByAsnNoAndBarcodes');
+        });
         Route::group(['prefix'=>'fast'],function() {
             Route::resource('storeItem','StoreItemController');
         });
@@ -730,6 +739,12 @@ Route::group(['prefix'=>'package'],function(){
     /** 库存 */
     $route->group(['prefix'=>'inventory'],function(){
         /** 说明 */
+        Route::group(['prefix' => 'stockOut'], function () {
+            Route::get('/', 'ReplenishmentController@index');
+            Route::post('/getReplenishmentInfoByCustomer', 'ReplenishmentController@getReplenishmentInfoByCustomer');
+            Route::get('/export', 'ReplenishmentController@export');
+        });
+
         Route::group(['prefix'=>'statement'],function(){
             /** 动库报表 */
             Route::group(['prefix'=>'changeInventory'],function(){
@@ -1111,6 +1126,7 @@ Route::group(['prefix'=>'package'],function(){
     );
     Route::group(['prefix' => 'kpi'], function () {
         Route::get( 'month', 'KpiController@monthIndex');
+        Route::get( 'day', 'KpiController@dayIndex');
     });
 });