Parcourir la source

临时工登记系统

ANG YU il y a 4 ans
Parent
commit
cd611c25a7
30 fichiers modifiés avec 1575 ajouts et 18 suppressions
  1. 3 0
      app/Console/Kernel.php
  2. 122 0
      app/Http/Controllers/LaborApplyController.php
  3. 65 0
      app/Http/Controllers/LaborCompanyDispatchController.php
  4. 10 0
      app/Http/Controllers/TestController.php
  5. 46 0
      app/Http/Requests/LaborApply/LaborApplyRequest.php
  6. 40 0
      app/Jobs/LaborApplyRecordJob.php
  7. 88 0
      app/LaborApply.php
  8. 2 0
      app/LaborCompany.php
  9. 41 0
      app/LaborCompanyDispatch.php
  10. 48 0
      app/LaborCompanyDispatchDetail.php
  11. 2 0
      app/Providers/AppServiceProvider.php
  12. 171 0
      app/Services/LaborApplyService.php
  13. 22 0
      database/factories/LaborApplyFactory.php
  14. 39 0
      database/migrations/2021_09_28_111205_create_labor_applies_table.php
  15. 36 0
      database/migrations/2021_09_28_162343_create_labor_company_dispatches_table.php
  16. 32 0
      database/migrations/2021_09_28_171020_add_column_max_labor_num_to_labor_companies_table.php
  17. 35 0
      database/migrations/2021_09_29_093320_create_labor_company_dispatch_details_table.php
  18. 36 0
      database/migrations/2021_09_29_175454_add_column_man_num_and_woman_num_to_labor_companies_table.php
  19. 16 0
      database/seeds/LaborApplySeeder.php
  20. 27 9
      resources/views/maintenance/laborCompany/create.blade.php
  21. 17 8
      resources/views/maintenance/laborCompany/edit.blade.php
  22. 4 1
      resources/views/maintenance/laborCompany/index.blade.php
  23. 105 0
      resources/views/personnel/laborApply/create.blade.php
  24. 80 0
      resources/views/personnel/laborApply/dispatch/detail/create.blade.php
  25. 81 0
      resources/views/personnel/laborApply/dispatch/detail/edit.blade.php
  26. 116 0
      resources/views/personnel/laborApply/dispatch/index.blade.php
  27. 85 0
      resources/views/personnel/laborApply/edit.blade.php
  28. 146 0
      resources/views/personnel/laborApply/index.blade.php
  29. 16 0
      routes/web.php
  30. 44 0
      tests/Services/LaborApplyService/AllocationLaborToLaborCompanyTest.php

+ 3 - 0
app/Console/Kernel.php

@@ -20,6 +20,7 @@ use App\Console\Commands\SyncWMSOrderTask;
 use App\Console\Commands\TestTemp;
 use App\Console\Commands\WasSyncWmsAsnInformation;
 use App\Console\Commands\WASSyncWMSOrderInformation;
+use App\Jobs\LaborApplyRecordJob;
 use Illuminate\Console\Scheduling\Schedule;
 use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
 use Illuminate\Foundation\Console\ModelMakeCommand;
@@ -83,6 +84,8 @@ class  Kernel extends ConsoleKernel
         $schedule->command('orderCountingRecordTask')->dailyAt("1:00");
         //$schedule->command('check:cacheRack')->everyMinute();
         $schedule->command('AccordingToOwnersManualBack')->everyThirtyMinutes()->between('9:00','16:30');
+
+        $schedule->job(new LaborApplyRecordJob())->dailyAt('19:00');//生成临时工派遣数据
     }
 
     /**

+ 122 - 0
app/Http/Controllers/LaborApplyController.php

@@ -0,0 +1,122 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Requests\LaborApply\LaborApplyRequest;
+use App\Jobs\LaborApplyRecordJob;
+use App\LaborApply;
+use App\Services\LaborApplyService;
+use App\UserWorkgroup;
+use App\Warehouse;
+use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
+use Illuminate\Routing\Redirector;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Gate;
+
+class LaborApplyController extends Controller
+{
+    public function index()
+    {
+
+
+        $builder = LaborApply::query()
+            ->with(['warehouse', 'userWorkGroup', 'applyUser']);
+        if (!(\auth()->user()->isSuperAdmin() || Gate::allows('宝时人事部'))) {
+            $builder->where('apply_user_id', \auth()->id());
+        }
+        $labor_applies = $builder
+            ->orderByDesc('created_at')
+            ->paginate();
+        return view('personnel.laborApply.index', compact('labor_applies'));
+    }
+
+    public function create()
+    {
+        $warehouses = Warehouse::all();
+        $userWorkGroups = UserWorkgroup::all();
+        /** @var LaborApplyService $service */
+        $service = app('LaborApplyService');
+        //获取开放状态
+        $can_create_status = $service->getCanCreateStatus();
+        return view('personnel.laborApply.create', compact('userWorkGroups', 'warehouses', 'can_create_status'));
+    }
+
+    public function store(LaborApplyRequest $request, LaborApply $laborApply)
+    {
+        $laborApply->fill($request->all());
+        $laborApply->apply_user_id = Auth::id();
+        $laborApply->status = '创建';
+        $laborApply->save();
+        return redirect(route('laborApply.index'))->with('success', '申请成功!');
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param \App\LaborApply $laborApply
+     * @return \Illuminate\Http\Response
+     */
+    public function show(LaborApply $laborApply)
+    {
+        //
+    }
+
+
+    public function edit(LaborApply $laborApply)
+    {
+        $warehouses = Warehouse::all();
+        $userWorkGroups = UserWorkgroup::all();
+        return view('personnel.laborApply.edit', compact('laborApply', 'warehouses', 'userWorkGroups'));
+    }
+
+    public function update(Request $request, LaborApply $laborApply)
+    {
+        $laborApply->actual_num = $request->input('actual_num');
+        $laborApply->status = '任务完结';
+        $laborApply->save();
+        return redirect(route('laborApply.index'))->with('success', '填写实到人数成功!');
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param \App\LaborApply $laborApply
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(LaborApply $laborApply)
+    {
+        //
+    }
+
+    /**
+     * 临时开放按钮
+     * @return Application|RedirectResponse|Redirector
+     */
+    public function temporaryOpen()
+    {
+        /** @var LaborApplyService $service */
+        $service = app('LaborApplyService');
+        $service->setCanCreateStatus(LaborApply::CAN_CREATE_STATUS_TEMPORARY_OPEN);
+        $ttl = LaborApplyService::LABOR_APPLY_STATUS_TTL;
+        //调用定时任务 开放时间过了自动生成报表
+        LaborApplyRecordJob::dispatch()->delay(now()->addSeconds($ttl));
+        return redirect(route('laborApply.create'))->with('success', "临时开放成功,有效时间为:{$ttl}S ");
+    }
+
+    /**
+     *手动生成劳务分配
+     */
+    public function createDispatch()
+    {
+        /** @var LaborApplyService $laborApplyService */
+        $laborApplyService = app('LaborApplyService');
+        $response = $laborApplyService->allocationLaborToLaborCompany();
+        if ($response['success']) {
+            return redirect(route('laborApplyDispatch.index'))->with('success', '重新生成劳务派遣数据成功!');
+        }else{
+            return redirect(route('laborApplyDispatch.index'))->with('danger', $response['error_message']);
+        }
+    }
+}

+ 65 - 0
app/Http/Controllers/LaborCompanyDispatchController.php

@@ -0,0 +1,65 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\LaborApply;
+use App\LaborCompany;
+use App\LaborCompanyDispatch;
+use App\User;
+use Illuminate\Http\Request;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Gate;
+
+class LaborCompanyDispatchController extends Controller
+{
+    public function index()
+    {
+        //按照分配日期倒序
+        $builder = LaborCompanyDispatch::query()
+            ->with(['laborCompany', 'laborCompanyDispatchDetails']);
+
+        if (!(\auth()->user()->isSuperAdmin() || Gate::allows('宝时人事部'))) {
+            /** @var User $user */
+            $user = auth()->user();
+            //获取用户的劳务角色 劳务角色名 与 劳务所名称相同
+            $laborCompanyNames = $user->roles()->where('name', 'LIKE', '劳务')->pluck('name');
+            //根据劳务所名称相同 查询劳务所Id
+            $laborCompanyIds = LaborCompany::query()->whereIn('name', $laborCompanyNames)->pluck('id');
+            $builder->whereIn('labor_company_id', $laborCompanyIds);
+        }
+        $labor_company_dispatches = $builder
+            ->orderByDesc('dispatch_date')
+            ->paginate();
+
+        return view('personnel.laborApply.dispatch.index', compact('labor_company_dispatches'));
+    }
+
+    public function createDetail(Request $request, LaborCompanyDispatch $laborCompanyDispatch)
+    {
+        return view('personnel.laborApply.dispatch.detail.create', compact('laborCompanyDispatch'));
+    }
+
+    public function editDetail(Request $request, LaborCompanyDispatch $laborCompanyDispatch)
+    {
+        $laborCompanyDispatch->loadMissing('laborCompanyDispatchDetails');
+        return view('personnel.laborApply.dispatch.detail.edit', compact('laborCompanyDispatch'));
+    }
+
+    public function storeDetail(Request $request, LaborCompanyDispatch $laborCompanyDispatch)
+    {
+        $laborCompanyDispatch->laborCompanyDispatchDetails()->delete();
+        $laborCompanyDispatch->laborCompanyDispatchDetails()->createMany(
+            $request->input('users')
+        );
+        /** @var Carbon $dispatch_date */
+        $dispatch_date = $laborCompanyDispatch->dispatch_date;
+
+        LaborApply::query()
+            ->whereDate('created_at', $dispatch_date->subDay()->toDateString())
+            ->where('warehouse_id', $laborCompanyDispatch->laborCompany->warehouse_id)
+            ->update([
+                'status' => 3, //劳务接单
+            ]);
+        return redirect(route('laborApplyDispatch.index'))->with('success', '添加临时工详情成功!');
+    }
+}

+ 10 - 0
app/Http/Controllers/TestController.php

@@ -21,6 +21,7 @@ use App\Jobs\SettlementBillReportJob;
 use App\Jobs\StoreCreateInstantBill;
 use App\Jobs\TestJob;
 use App\Jobs\WeightUpdateInstantBill;
+use App\LaborCompanyDispatch;
 use App\LaborReport;
 use App\LaborReportStatus;
 use App\MaterialBox;
@@ -727,4 +728,13 @@ sql;
         app('OrderPackageService')->sortOrderPackageTransferStatus($orderPackage);
         dd($orderPackage);
     }
+
+    public function clear_work_space()
+    {
+        \App\LaborApply::query()->truncate();
+
+        LaborCompanyDispatch::query()->truncate();
+
+        \App\LaborCompanyDispatchDetail::query()->truncate();
+    }
 }

+ 46 - 0
app/Http/Requests/LaborApply/LaborApplyRequest.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace App\Http\Requests\LaborApply;
+
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Support\Facades\Auth;
+
+class LaborApplyRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        return [
+            'warehouse_id' => 'required',
+            'user_workgroup_id' => 'required',
+            'man_num' => 'required',
+            'woman_num' => 'required',
+            'remark' => 'required',
+        ];
+    }
+
+    public function messages()
+    {
+        return [
+            'warehouse_id.required' =>'不能为空。',
+            'user_workgroup_id.required' => '不能为空。',
+            'man_num.required' => '不能为空。',
+            'woman_num.required' => '不能为空。',
+            'remark.required' => '不能为空。',
+        ];
+    }
+}

+ 40 - 0
app/Jobs/LaborApplyRecordJob.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Exceptions\WarningException;
+use App\Services\LaborApplyService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+
+class LaborApplyRecordJob implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    /** @var $service LaborApplyService */
+    private $service;
+
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        $this->service = app('LaborApplyService');
+    }
+
+    /**
+     * Execute the job.
+     * @return void
+     * @throws WarningException
+     */
+    public function handle()
+    {
+        $response = $this->service->allocationLaborToLaborCompany();
+        if (!$response['success']) throw new WarningException($response['error_message']);
+    }
+}

+ 88 - 0
app/LaborApply.php

@@ -0,0 +1,88 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+
+class LaborApply extends Model
+{
+    const CAN_CREATE_STATUS_OPEN = 1;
+    const CAN_CREATE_STATUS_FORBID = 2;
+    const CAN_CREATE_STATUS_TEMPORARY_OPEN = 3;
+    use ModelLogChanging;
+    use ModelTimeFormat;
+
+    public $fillable = [
+        'status',//状态
+        'warehouse_id',//仓库
+        'user_workgroup_id',//仓库小组
+        'apply_user_id',//申请人
+        'man_num',//男工数量
+        'woman_num',//女工数量
+        'actual_num',//到岗人数
+        'remark',//用工要求
+    ];
+
+
+    protected $appends = ['arrive_rate'];
+
+    static public $enums = [
+        'status' => [
+            '' => 0,
+            '创建' => 1,
+            '指派成功' => 2,
+            '劳务接单' => 3,
+            '任务完结' => 4,
+        ],
+    ];
+
+    function __construct(array $attributes = [])
+    {
+        foreach (self::$enums as &$enum) {
+            $enum = $enum + array_flip($enum);
+        }
+        parent::__construct($attributes);
+    }
+
+
+    public function getStatusAttribute($value)
+    {
+        if (!$value) return '';
+        return self::$enums['status'][$value];
+    }
+
+    public function setStatusAttribute($value)
+    {
+        if (!$value) return 0;
+        $this->attributes['status'] = self::$enums['status'][$value];
+    }
+
+    public function warehouse(): BelongsTo
+    {
+        return $this->belongsTo(Warehouse::class);
+    }
+
+    public function userWorkGroup(): BelongsTo
+    {
+        return $this->belongsTo(UserWorkgroup::class, 'user_workgroup_id', 'id');
+    }
+
+    public function applyUser(): BelongsTo
+    {
+        return $this->belongsTo(User::class, 'apply_user_id', 'id');
+    }
+
+    public function getArriveRateAttribute()
+    {
+        if (0 === $this->actual_num) {
+            return '';
+        }
+        $apply_num = $this->man_num + $this->woman_num;
+        $arrive_rate = $this->actual_num / $apply_num * 100;
+        return number_format($arrive_rate, 1) . '%';
+    }
+}

+ 2 - 0
app/LaborCompany.php

@@ -20,6 +20,8 @@ class LaborCompany extends Model
         'warehouse_id',//仓库ID
         'priority',//优先级 数字越大优先级越高
         'mail',//邮箱
+        'man_num',//男工人数
+        'woman_num',//女工人数
     ];
 
     /**

+ 41 - 0
app/LaborCompanyDispatch.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\HasMany;
+
+class LaborCompanyDispatch extends Model
+{
+    const EXCEED_MAX_LABOR_NUM = 2;
+    const NOT_EXCEED_MAX_LABOR_NUM = 1;
+    use ModelLogChanging;
+
+    use ModelTimeFormat;
+
+    public $fillable = [
+        'labor_company_id',//劳务公司ID
+        'man_num',//男工数量
+        'woman_num',//女工数量
+        'dispatch_date',//分配日期
+        'exceed_max_labor_num_status',//是否超过最大允许值 1 未超过 2 超过
+    ];
+
+    public $dates = [
+        'dispatch_date'
+    ];
+
+    public function laborCompany(): BelongsTo
+    {
+        return $this->belongsTo(LaborCompany::class);
+    }
+
+    public function laborCompanyDispatchDetails(): HasMany
+    {
+        return $this->hasMany(LaborCompanyDispatchDetail::class);
+    }
+}

+ 48 - 0
app/LaborCompanyDispatchDetail.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class LaborCompanyDispatchDetail extends Model
+{
+    use ModelLogChanging;
+
+    public $fillable = [
+        'labor_company_dispatch_id',//劳务公司派遣ID
+        'name',//临时工姓名
+        'gender',//性别
+        'age',//年龄
+    ];
+
+    static public $enums = [
+        'gender' => [
+            '' => 0,
+            '男' => 1,
+            '女' => 2,
+        ],
+    ];
+
+    function __construct(array $attributes = [])
+    {
+        foreach (self::$enums as &$enum) {
+            $enum = $enum + array_flip($enum);
+        }
+        parent::__construct($attributes);
+    }
+
+
+    public function getGenderAttribute($value)
+    {
+        if (!$value) return '';
+        return self::$enums['gender'][$value];
+    }
+
+    public function setGenderAttribute($value)
+    {
+        if (!$value) return 0;
+        $this->attributes['gender'] = self::$enums['gender'][$value];
+    }
+}

+ 2 - 0
app/Providers/AppServiceProvider.php

@@ -184,6 +184,7 @@ use App\Services\WorkOrderTypeService;
 use App\Services\OrderPackageRemarkService;
 use App\Services\LaborCompanyService;
 use App\Services\NotificationService;
+use App\Services\LaborApplyService;
 
 class AppServiceProvider extends ServiceProvider
 {
@@ -249,6 +250,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('InventoryCompareService', InventoryCompareService::class);
         app()->singleton('InventoryDailyLogService', InventoryDailyLogService::class);
         app()->singleton('JDDeliveryService',JDDeliveryService::class);
+        app()->singleton('LaborApplyService',LaborApplyService::class);
         app()->singleton('LaborCompanyService',LaborCompanyService::class);
         app()->singleton('LaborReportsCountingRecordService', LaborReportsCountingRecordService::class);
         app()->singleton('LogService', LogService::class);

+ 171 - 0
app/Services/LaborApplyService.php

@@ -0,0 +1,171 @@
+<?php
+
+namespace App\Services;
+
+use App\LaborCompany;
+use App\LaborCompanyDispatch;
+use App\Traits\ServiceAppAop;
+use App\LaborApply;
+use App\Warehouse;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\DB;
+
+class LaborApplyService
+{
+    //超时时间 默认为19:00
+    const TIME_OUT_HOUR = 19;
+    const LABOR_APPLY_STATUS = 'LABOR_APPLY_STATUS';
+    const LABOR_APPLY_STATUS_TTL = 60 * 30;
+    use ServiceAppAop;
+
+    protected $modelClass = LaborApply::class;
+
+    /**
+     * 获取预约开放状态
+     *
+     * @return int 1 开放 2 禁止 3 临时开放
+     */
+    public function getCanCreateStatus(): int
+    {
+        $can_create_status = (now()->lte(now()->startOfDay()->addHours(self::TIME_OUT_HOUR))) ? LaborApply::CAN_CREATE_STATUS_OPEN : LaborApply::CAN_CREATE_STATUS_FORBID;
+        if (Cache::has(self::LABOR_APPLY_STATUS)) {
+            $can_create_status = Cache::get(self::LABOR_APPLY_STATUS);
+        }
+        return $can_create_status;
+    }
+
+    /**
+     * 设置预约开放状态 1 开放 2 禁止 3 临时开放
+     * @param int $status
+     */
+    public function setCanCreateStatus(int $status)
+    {
+        Cache::put(self::LABOR_APPLY_STATUS, $status, self::LABOR_APPLY_STATUS_TTL);
+    }
+
+    /**
+     * 生产劳务派遣报表
+     *
+     * 查询全部仓库
+     * 遍历仓库
+     * 按照仓库,查询当日的的申请,将申请的男女工分别加和
+     * 按照仓库查询对应的劳务所 按照优先级排序
+     * 将男女工之和依次分配到 劳务所
+     * 如果分配完成后 发现还有剩下的 则将状态设置为2
+     */
+    public function allocationLaborToLaborCompany(): array
+    {
+
+        //当前时间小于 1.00 禁止生成数据
+        if (now()->lte(now()->startOfDay()->addHours(1))) return ['success' => false, 'error_message' => '当前时间禁止生成临时工派遣数据'];
+        //派遣日期 为报表生成日期的后一天
+        $dispatch_date = now()->addDay()->startOfDay()->toDateTimeString();
+
+        //接口幂等性,删除旧的数据
+        LaborCompanyDispatch::query()->where('dispatch_date', $dispatch_date)->delete();
+
+        //查询全部仓库
+        $warehouses = Warehouse::all();
+        //按照仓库,
+        foreach ($warehouses as $warehouse) {
+            //查询当日的的申请,将申请的男女工分别加和
+            $apply_man_nums = 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)
+                ->groupBy('warehouse_id')
+                ->first();
+            if (empty($apply_man_nums)) continue;
+            //按照仓库查询对应的劳务所 按照优先级排序 单号正序 双号逆序
+            $companies = $this->getCompaniesOrderByDay($warehouse);
+            //需要的男工人数
+            $man_num = $apply_man_nums->man_num;
+            //需要的女工人数
+            $woman_num = $apply_man_nums->woman_num;
+            //插入的分配数据
+            $laborCompanyDispatchInsertArray = $this->buildLaborCompanyDispatchInsertArray($companies, $man_num, $woman_num, $dispatch_date);
+            //插入分配数据
+            LaborCompanyDispatch::query()->insert($laborCompanyDispatchInsertArray);
+
+            LaborApply::query()
+                ->whereBetween('created_at', [now()->startOfDay(), now()->endOfDay()])
+                ->where('warehouse_id', $warehouse->id)
+                ->update([
+                    'status' => 2,//指派成功
+                ]);
+        }
+        return ['success' => true, 'message' => '生成临时工派遣数据成功'];
+    }
+
+    /**
+     * 设置为状态为溢出
+     * @param array $laborCompanyAppliesTarget
+     * @return array
+     */
+    private function setExceedMaxLaborNumStatusExceedMaxLaborNum(array $laborCompanyAppliesTarget): array
+    {
+        return array_map(function (&$item) {
+            $item['exceed_max_labor_num_status'] = LaborCompanyDispatch::EXCEED_MAX_LABOR_NUM;
+            return $item;
+        }, $laborCompanyAppliesTarget);
+    }
+
+    /**
+     * 构建插入的分配数据
+     * @param $companies
+     * @param $man_num
+     * @param $woman_num
+     * @param string $dispatch_date
+     * @return array
+     */
+    private function buildLaborCompanyDispatchInsertArray($companies, $man_num, $woman_num, string $dispatch_date): array
+    {
+        $laborCompanyDispatchInsertArray = [];
+        //遍历劳务公司
+        foreach ($companies as $company) {
+            if ($man_num > 0 || $woman_num > 0) {
+                //分配给指定劳务的男工人数
+                $dispatch_man_num = $man_num > $company->man_num ? $company->man_num : $man_num;
+                //分配给指定劳务的女工人数
+                $dispatch_woman_num = $woman_num > $company->woman_num ? $company->woman_num : $woman_num;
+                //待分配的男工
+                $man_num -= $dispatch_man_num;
+                //待分配的女工
+                $woman_num -= $dispatch_woman_num;
+                $laborCompanyDispatchInsertArray[] = [
+                    'labor_company_id' => $company->id,
+                    'man_num' => $dispatch_man_num,
+                    'woman_num' => $dispatch_woman_num,
+                    'dispatch_date' => $dispatch_date,
+                    'exceed_max_labor_num_status' => LaborCompanyDispatch::NOT_EXCEED_MAX_LABOR_NUM,//没有超限额
+                ];
+            }
+
+        }
+        //全部劳务公司分配完后 还有剩余的男工/女工
+        if ($man_num > 0 || $woman_num > 0) {
+            //设置状态为超额
+            $laborCompanyDispatchInsertArray = $this->setExceedMaxLaborNumStatusExceedMaxLaborNum($laborCompanyDispatchInsertArray);
+        }
+        return $laborCompanyDispatchInsertArray;
+    }
+
+    /**
+     * 按照仓库查询对应的劳务所 按照优先级排序 单号正序 双号逆序
+     * @param $warehouse
+     * @return Builder[]|Collection
+     */
+    private function getCompaniesOrderByDay($warehouse)
+    {
+        $builder = LaborCompany::query()
+            ->where('warehouse_id', $warehouse->id);
+        if (now()->day % 2 === 0) {
+            $builder->orderBy('priority');
+        } else {
+            $builder->orderBy('priority', 'desc');
+        }
+        return $builder->get();
+    }
+}

+ 22 - 0
database/factories/LaborApplyFactory.php

@@ -0,0 +1,22 @@
+<?php
+
+/** @var \Illuminate\Database\Eloquent\Factory $factory */
+
+use App\LaborApply;
+use App\UserWorkgroup;
+use App\Warehouse;
+use Faker\Generator as Faker;
+
+$factory->define(LaborApply::class, function (Faker $faker) {
+    $warehouse_ids = Warehouse::query()->pluck('id')->toArray();
+    $user_workgroup_ids = UserWorkgroup::query()->pluck('id')->toArray();
+    return [
+        'status' => 1,//状态
+        'warehouse_id' => $faker->randomElement($warehouse_ids),//仓库
+        'user_workgroup_id' => $faker->randomElement($user_workgroup_ids),//仓库小组
+        'apply_user_id' => random_int(1, 10),//申请人
+        'apply_num' => random_int(1, 30),//申请人数
+        'actual_num' => 0,//到岗人数
+        'remark' => $faker->sentence,//用工要求
+    ];
+});

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

@@ -0,0 +1,39 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateLaborAppliesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('labor_applies', function (Blueprint $table) {
+            $table->id();
+            $table->integer('status')->comment('状态');
+            $table->integer('warehouse_id')->comment('仓库');
+            $table->integer('user_workgroup_id')->comment('仓库小组');
+            $table->integer('apply_user_id')->comment('申请人');
+            $table->integer('man_num')->comment('男工数量');
+            $table->integer('woman_num')->comment('女工数量');
+            $table->integer('actual_num')->comment('到岗人数');
+            $table->string('remark')->comment('用工要求');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('labor_applies');
+    }
+}

+ 36 - 0
database/migrations/2021_09_28_162343_create_labor_company_dispatches_table.php

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateLaborCompanyDispatchesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('labor_company_dispatches', function (Blueprint $table) {
+            $table->id();
+            $table->integer('labor_company_id')->comment('劳务公司ID');
+            $table->integer('man_num')->comment('男工数量');
+            $table->integer('woman_num')->comment('女工数量');;
+            $table->timestamp('dispatch_date')->comment('分配日期');
+            $table->integer('exceed_max_labor_num_status')->comment('是否超过最大允许值 1 未超过 2 超过');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('labor_company_dispatches');
+    }
+}

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

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddColumnMaxLaborNumToLaborCompaniesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('labor_companies', function (Blueprint $table) {
+            $table->integer('max_labor_num')->comment('最大允许人数');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('labor_companies', function (Blueprint $table) {
+            $table->dropColumn('max_labor_num');
+        });
+    }
+}

+ 35 - 0
database/migrations/2021_09_29_093320_create_labor_company_dispatch_details_table.php

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateLaborCompanyDispatchDetailsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('labor_company_dispatch_details', function (Blueprint $table) {
+            $table->id();
+            $table->integer('labor_company_dispatch_id')->comment('劳务公司派遣ID');
+            $table->string('name')->comment('临时工姓名');
+            $table->integer('gender')->comment('性别');
+            $table->integer('age')->nullable()->comment('年龄');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('labor_company_dispatch_details');
+    }
+}

+ 36 - 0
database/migrations/2021_09_29_175454_add_column_man_num_and_woman_num_to_labor_companies_table.php

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddColumnManNumAndWomanNumToLaborCompaniesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('labor_companies', function (Blueprint $table) {
+            $table->integer('man_num')->comment('男工数量');
+            $table->integer('woman_num')->comment('女工数量');
+            $table->dropColumn('max_labor_num');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('labor_companies', function (Blueprint $table) {
+            $table->dropColumn('man_num');
+            $table->dropColumn('woman_num');
+            $table->integer('max_labor_num');
+        });
+    }
+}

+ 16 - 0
database/seeds/LaborApplySeeder.php

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

+ 27 - 9
resources/views/maintenance/laborCompany/create.blade.php

@@ -14,7 +14,8 @@
                         <label for="name" class="col-2 col-form-label text-right">劳务所名称</label>
                         <div class="col-8">
                             <input type="text" class="form-control @error('name') is-invalid @enderror"
-                                   name="name" autocomplete="off" value="{{ old('name') }}" required>
+                                   name="name" autocomplete="off"
+                                   id="name" value="{{ old('name') }}" required>
                             @error('name')
                             <span class="invalid-feedback" role="alert">
                                 <strong>{{ $message }}</strong>
@@ -22,31 +23,48 @@
                             @enderror
                         </div>
                     </div>
-                    <div class="from-group row">
-                        <label for="priority" title="数字越大优先级越高" class="col-2 col-form-label text-right">优先级</label>
+
+                    <div class="from-group row mt-3">
+                        <label for="priority" title="优先级" class="col-2 col-form-label text-right">优先级</label>
+                        <div class="col-8">
+                            <input type="number" class="form-control" name="priority"
+                                   value="{{ old('priority') }}"
+                                   required id="priority">
+                        </div>
+                    </div>
+
+                    <div class="from-group row mt-3">
+                        <label for="man_num" title="男工人数" class="col-2 col-form-label text-right">男工人数</label>
                         <div class="col-8">
-                            <input type="number" class="form-control" name="priority" value="{{ old('priority') }}"
-                                   required>
+                            <input type="number" class="form-control" name="man_num"
+                                   value="{{ old('man_num') }}"
+                                   required id="man_num">
+                        </div>
+                    </div>
+                    <div class="from-group row mt-3">
+                        <label for="woman_num" title="女工人数" class="col-2 col-form-label text-right">女工人数</label>
+                        <div class="col-8">
+                            <input type="number" class="form-control" name="woman_num"
+                                   value="{{ old('woman_num') }}"
+                                   required id="woman_num">
                         </div>
                     </div>
                     <div class="from-group row mt-3">
                         <label for="mail" title="邮箱" class="col-2 col-form-label text-right">邮箱</label>
                         <div class="col-8">
-                            <input type="email" class="form-control" name="mail" value="{{ old('mail') }}">
+                            <input id="mail" type="email" class="form-control" name="mail" value="{{ old('mail') }}">
                         </div>
                     </div>
                     <div class="from-group row mt-3">
                         <label for="warehouse_id" class="col-2 col-form-label text-right">仓库</label>
                         <div class="col-8">
                             <select class="form-control" id="warehouse_id" name="warehouse_id" required>
-                                <option value="" hidden disabled selected >请选择仓库</option>
+                                <option value="" hidden disabled selected>请选择仓库</option>
                                 @foreach($warehouses as $warehouse)
                                     <option value="{{$warehouse->id}}">{{ $warehouse->name }}</option>
                                 @endforeach
                             </select>
                         </div>
-
-
                     </div>
                     <div class="form-group row mt-5">
                         <div class="col-8 offset-2">

+ 17 - 8
resources/views/maintenance/laborCompany/edit.blade.php

@@ -24,19 +24,28 @@
                             @enderror
                         </div>
                     </div>
-
-                    <div class="from-group row">
-                        <label for="priority" title="数字越大优先级越高" class="col-2 col-form-label text-right">优先级</label>
+                    <div class="from-group row mt-3">
+                        <label for="mail" title="邮箱" class="col-2 col-form-label text-right">邮箱</label>
                         <div class="col-8">
-                            <input type="number" class="form-control" name="priority"
-                                   value="{{ $laborCompany->priority }}"
-                                   required>
+                            <input type="email" class="form-control" name="mail" value="{{ $laborCompany->mail }}">
                         </div>
                     </div>
                     <div class="from-group row mt-3">
-                        <label for="mail" title="邮箱" class="col-2 col-form-label text-right">邮箱</label>
+                        <label for="priority" title="优先级" class="col-2 col-form-label text-right">优先级</label>
                         <div class="col-8">
-                            <input type="email" class="form-control" name="mail" value="{{ $laborCompany->mail }}">
+                            <input type="number" class="form-control" name="priority" value="{{ $laborCompany->priority }}">
+                        </div>
+                    </div>
+                    <div class="from-group row mt-3">
+                        <label for="man_num" title="男工人数" class="col-2 col-form-label text-right">男工人数</label>
+                        <div class="col-8">
+                            <input type="number" class="form-control" name="man_num" value="{{ $laborCompany->man_num }}">
+                        </div>
+                    </div>
+                    <div class="from-group row mt-3">
+                        <label for="woman_num" title="女工人数" class="col-2 col-form-label text-right">女工人数</label>
+                        <div class="col-8">
+                            <input type="number" class="form-control" name="woman_num" value="{{ $laborCompany->woman_num }}">
                         </div>
                     </div>
                     <div class="from-group row mt-3">

+ 4 - 1
resources/views/maintenance/laborCompany/index.blade.php

@@ -15,7 +15,8 @@
                         <th>仓库</th>
                         <th>邮箱</th>
                         <th>优先级</th>
-                        <th>创建时间</th>
+                        <th>男工人数</th>
+                        <th>女工人数</th>
                         <th>操作</th>
                     </tr>
                     <tr v-for="(laborCompany,i) in laborCompanys"  @click="selectTr===i+1?selectTr=0:selectTr=i+1" :class="selectTr===i+1?'focusing' : ''">
@@ -24,6 +25,8 @@
                         <td>@{{laborCompany.warehouse && laborCompany.warehouse.name}}</td>
                         <td>@{{laborCompany.mail}}</td>
                         <td>@{{laborCompany.priority}}</td>
+                        <td>@{{laborCompany.man_num}}</td>
+                        <td>@{{laborCompany.woman_num}}</td>
                         <td class="text-muted">@{{laborCompany.created_at}}</td>
                         <td>
                             @can('劳务所-编辑')

+ 105 - 0
resources/views/personnel/laborApply/create.blade.php

@@ -0,0 +1,105 @@
+@extends('layouts.app')
+@section('title')录入-临时工申请协调@endsection
+
+@section('content')
+    <div class="container-fluid" id="list">
+        <div class="card col-md-8 offset-md-2">
+            <div class="card-body">
+                <!--
+                   can_create_status
+                   1 开放
+                   2 禁止开放
+                   3 临时开放
+                -->
+                @can('人事管理')
+                <form v-if="can_create_status === 2" action="{{ route('laborApply.temporaryOpen') }}" method="post" accept-charset="UTF-8">
+                    {{ csrf_field() }}
+                    {{ method_field('PUT') }}
+                    <div class="form-group">
+                        <button type="submit" class="btn btn-outline-secondary btn-sm">
+                            <i class="far fa-trash-alt"></i> 临时开放
+                        </button>
+                    </div>
+                </form>
+                @endcan
+                <h2 v-if="can_create_status === 2"
+                    style="text-align: center;color: red;font-size: 28px">超过申请时间无法提交申请,联系管理员:152 2169 4191 , 173 1630 6907 </h2>
+                <h2 v-if="can_create_status === 3"
+                    style="text-align: center;color: red;font-size: 28px">系统临时开放,请尽快提交</h2>
+                <form v-if="(can_create_status === 1) || (can_create_status === 3)" action="{{ route('laborApply.store') }}" method="POST" accept-charset="UTF-8">
+                    @csrf
+                    @include('shared._error')
+                    {{--仓库--}}
+                    <div class="from-group row mt-3">
+                        <label for="warehouse_id" class="col-2 col-form-label text-right">仓库</label>
+                        <div class="col-8">
+                            <select class="form-control" id="warehouse_id" name="warehouse_id" required>
+                                <option value="" hidden disabled selected>请选择仓库</option>
+                                @foreach($warehouses as $warehouse)
+                                    <option value="{{$warehouse->id}}">{{ $warehouse->name }}</option>
+                                @endforeach
+                            </select>
+                        </div>
+                    </div>
+                    {{--所属组别--}}
+                    <div class="from-group row mt-3">
+                        <label for="user_workgroup_id" class="col-2 col-form-label text-right">所属组别</label>
+                        <div class="col-8">
+                            <select class="form-control" id="user_workgroup_id" name="user_workgroup_id" required>
+                                <option value="" hidden disabled selected>请选择所属组别</option>
+                                @foreach($userWorkGroups as $userWorkGroup)
+                                    <option value="{{$userWorkGroup->id}}">{{ $userWorkGroup->name }}</option>
+                                @endforeach
+                            </select>
+                        </div>
+                    </div>
+                    {{--男工人数--}}
+                    <div class="from-group row mt-3">
+                        <label for="man_num" class="col-2 col-form-label text-right">男工人数</label>
+                        <div class="col-8">
+                            <input type="number" class="form-control" id="man_num" name="man_num" required>
+                        </div>
+                    </div>
+                    {{--女工人数--}}
+                    <div class="from-group row mt-3">
+                        <label for="woman_num" class="col-2 col-form-label text-right">女工人数</label>
+                        <div class="col-8">
+                            <input type="number" class="form-control" id="woman_num" name="woman_num" required>
+                        </div>
+                    </div>
+                    {{--用工要求--}}
+                    <div class="from-group row mt-3">
+                        <label for="remark" class="col-2 col-form-label text-right">用工要求</label>
+                        <div class="col-8">
+                            <textarea class="form-control" rows="3"
+                                      placeholder required
+                                      name="remark" id="remark"></textarea>
+                        </div>
+                    </div>
+                    {{--提交--}}
+                    <div class="form-group row mt-5">
+                        <div class="col-8 offset-2">
+                            <input type="submit" class="btn btn-success form-control">
+                        </div>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        new Vue({
+            el: "#list",
+            data: {
+                can_create_status: {!! $can_create_status !!}
+            },
+            mounted() {
+
+            },
+
+            methods: {}
+        });
+    </script>
+@endsection

+ 80 - 0
resources/views/personnel/laborApply/dispatch/detail/create.blade.php

@@ -0,0 +1,80 @@
+@extends('layouts.app')
+@section('title')录入-劳务派遣明细详情@endsection
+
+@section('content')
+    <div class="container-fluid" id="list">
+        <div class="card col-md-8 offset-md-2">
+            <div class="card-body">
+                <form action="{{ route('laborApplyDispatch.storeDetail', $laborCompanyDispatch->id) }}" method="post"
+                      style="display: inline-block;"
+                      onsubmit="return confirm('您确定要提交吗?');">
+                    {{ csrf_field() }}
+                    <div class="form-group">
+                        <template v-for="(item,i) in items">
+                            <div class="row mt-3">
+                                <label class="col-1 col-form-label text-right" :for="'users['+i+'][name]'">姓名</label>
+                                <div class="col-2">
+                                    <input class="form-control" type="text" :name="'users['+i+'][name]'"
+                                           :id="'users['+i+'][name]'" required>
+                                </div>
+                                <label class="col-1 col-form-label text-right" :for="'users['+i+'][gender]'">性别</label>
+                                <div class="col-2">
+                                    <select class="form-control" :name="'users['+i+'][gender]'"
+                                            required>
+                                        <option value="" hidden disabled selected>性别</option>
+                                        <option value="男">男</option>
+                                        <option value="女">女</option>
+                                    </select>
+                                </div>
+                                <label class="col-1 col-form-label text-right" :for="'users['+i+'][age]'">年龄</label>
+                                <div class="col-2">
+                                    <input class="form-control" type="number" :name="'users['+i+'][age]'"
+                                           :id="'users['+i+'][age]'">
+                                </div>
+
+                                <div v-if="i!==0" class="col-1 ml-1">
+                                    <button class="btn btn-sm btn-primary float-right" type="button"
+                                            @click="items.splice(i,1)">-
+                                    </button>
+                                </div>
+                            </div>
+
+                        </template>
+                        <button class="btn btn-sm btn-primary float-right" type="button"
+                                @click="addItem();">添加
+                        </button>
+                    </div>
+                    <button type="submit" class="btn btn-success btn-sm">
+                        <i class="far fa-trash-alt"></i> 提交
+                    </button>
+                </form>
+            </div>
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        new Vue({
+            el: "#list",
+            data: {
+                items: [{}],
+                labor_company_dispatch: {!! $laborCompanyDispatch !!},
+            },
+            mounted() {
+
+            },
+
+            methods: {
+                addItem() {
+                    if (this.items.length <= this.labor_company_dispatch.labor_worker_num -1 ) {
+                        this.items.push({});
+                    } else {
+                        window.tempTip.show("不能超过最大人数限制!");
+                    }
+                }
+            }
+        });
+
+    </script>
+@endsection

+ 81 - 0
resources/views/personnel/laborApply/dispatch/detail/edit.blade.php

@@ -0,0 +1,81 @@
+@extends('layouts.app')
+@section('title')修改-劳务派遣明细详情@endsection
+
+@section('content')
+    <div class="container-fluid" id="list">
+        <div class="card col-md-8 offset-md-2">
+            <div class="card-body">
+                <form action="{{ route('laborApplyDispatch.storeDetail', $laborCompanyDispatch->id) }}" method="post"
+                      style="display: inline-block;"
+                      onsubmit="return confirm('您确定要提交吗?');">
+                    {{ csrf_field() }}
+                    <div class="form-group">
+                        <template v-for="(item,i) in items">
+                            <div class="row mt-3">
+                                <label class="col-1 col-form-label text-right" :for="'users['+i+'][name]'">姓名</label>
+                                <div class="col-2">
+                                    <input class="form-control" type="text" :name="'users['+i+'][name]'"
+                                           :value="item.name"
+                                           :id="'users['+i+'][name]'" required>
+                                </div>
+                                <label class="col-1 col-form-label text-right" :for="'users['+i+'][gender]'">性别</label>
+                                <div class="col-2">
+                                    <select class="form-control" :name="'users['+i+'][gender]'"
+                                            required>
+                                        <option value="男" :selected="item.gender==='男'">男</option>
+                                        <option value="女" :selected="item.gender==='女'">女</option>
+                                    </select>
+                                </div>
+                                <label class="col-1 col-form-label text-right" :for="'users['+i+'][age]'">年龄</label>
+                                <div class="col-2">
+                                    <input class="form-control" type="number" :name="'users['+i+'][age]'"
+                                           :value="item.age"
+                                           :id="'users['+i+'][age]'">
+                                </div>
+
+                                <div v-if="i!==0" class="col-1 ml-1">
+                                    <button class="btn btn-sm btn-primary float-right" type="button"
+                                            @click="items.splice(i,1)">-
+                                    </button>
+                                </div>
+                            </div>
+
+                        </template>
+                        <button class="btn btn-sm btn-primary float-right" type="button"
+                                @click="addItem();">添加
+                        </button>
+                    </div>
+                    <button type="submit" class="btn btn-success btn-sm">
+                        <i class="far fa-trash-alt"></i> 提交
+                    </button>
+                </form>
+            </div>
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        new Vue({
+            el: "#list",
+            data: {
+                items: {!! $laborCompanyDispatch->laborCompanyDispatchDetails !!},
+                labor_company_dispatch: {!! $laborCompanyDispatch !!},
+            },
+            mounted() {
+
+            },
+
+            methods: {
+                addItem() {
+                    if (this.items.length <= this.labor_company_dispatch.labor_worker_num - 1) {
+                        this.items.push({});
+                    } else {
+                        window.tempTip.show("不能超过最大人数限制!");
+                    }
+                }
+            }
+        });
+
+    </script>
+@endsection

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

@@ -0,0 +1,116 @@
+@extends('layouts.app')
+@section('title')查看-劳务派遣明细@endsection
+
+@section('content')
+    <div id="list" class="d-none">
+        <div class="container-fluid">
+            <div id="form_div"></div>
+            @include('shared._messages')
+            <table class="table table-striped table-bordered table-hover card-body td-min-width-80" id="table">
+                <tr v-for="(labor_company_dispatch,i) in labor_company_dispatches"
+                    @click="selectTr===i+1?selectTr=0:selectTr=i+1"
+                    :class="selectTr===i+1?'focusing' : ''">
+                    <td>
+                        <input class="checkItem" type="checkbox" :value="labor_company_dispatch.id">
+                    </td>
+                    <td>@{{ i+1 }}</td>
+                    <td>@{{ labor_company_dispatch.labor_company.name }}</td>
+                    <td>@{{ labor_company_dispatch.man_num }}</td>
+                    <td>@{{ labor_company_dispatch.woman_num }}</td>
+                    <td>
+                        <div v-if="labor_company_dispatch.labor_company_dispatch_details.length >0">
+                            <table v-if="labor_company_dispatch.showMore" style="margin: 0;padding: 0">
+                                <tr v-for="(v,k) of labor_company_dispatch.labor_company_dispatch_details" :key="k">
+                                    <td>@{{ v.name }}</td>
+                                    <td>@{{ v.gender }}</td>
+                                    <td>@{{ v.age }}</td>
+                                </tr>
+                            </table>
+                            <table v-else style="margin: 0;padding: 0">
+                                <tr>
+                                    <td>@{{ labor_company_dispatch.labor_company_dispatch_details[0].name }}</td>
+                                    <td>@{{ labor_company_dispatch.labor_company_dispatch_details[0].gender }}</td>
+                                    <td>@{{ labor_company_dispatch.labor_company_dispatch_details[0].age }}</td>
+                                </tr>
+                            </table>
+                            <a href="javascript:void(0)"
+                               v-if="labor_company_dispatch.labor_company_dispatch_details.length >1"
+                               @click="labor_company_dispatch.showMore = !labor_company_dispatch.showMore">
+                                @{{ labor_company_dispatch.showMore?'收起':'显示更多' }}
+                            </a>
+                        </div>
+                    </td>
+                    <td>@{{ labor_company_dispatch.dispatch_date }}</td>
+                    <td>
+                        <a :href="getCreateOrEditDetailUrl(labor_company_dispatch)"
+                           class="btn btn-outline-secondary btn-sm" role="button">
+                            @{{ labor_company_dispatch.labor_company_dispatch_details.length>0?'修改临时工明细':'录入临时工明细' }}
+                        </a>
+                    </td>
+
+                </tr>
+            </table>
+            {{ $labor_company_dispatches->links() }}
+        </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>
+        new Vue({
+            el: "#list",
+            data: {
+                labor_company_dispatches: [
+                    @foreach( $labor_company_dispatches as $labor_company_dispatch )
+                        {!! $labor_company_dispatch !!},
+                    @endforeach
+                ],
+                selectTr: 0
+            },
+            mounted() {
+                $('#list').removeClass('d-none');
+                let _this = this;
+                $(".up").slideUp();
+                let data = []
+                _this.form = new query({
+                    el: '#form_div',
+                    condition: data,
+                    appendDom: "btn",
+                });
+                _this.form.init();
+                let column = [
+                    {name: 'index', value: '序号', neglect: true},
+                    {name: 'name', value: '劳务公司'},
+                    {name: 'man_num', value: '男工人数'},
+                    {name: 'woman_num', value: '女工人数'},
+                    {name: 'details', value: '派遣详情'},
+                    {name: 'dispatch_date', value: '分配日期'},
+                    {name: 'do', value: '操作'},
+                ];
+                new Header({
+                    el: "table",
+                    name: "labor_company_dispatches",
+                    column: column,
+                    data: this.labor_company_dispatches,
+                    restorationColumn: 'addtime',
+                    fixedTop: ($('#form_div').height()) + ($('#btn').height()) + 1,
+                }).init();
+            },
+
+            methods: {
+                getCreateOrEditDetailUrl(labor_company_dispatch) {
+                    let url = "";
+                    if (labor_company_dispatch.labor_company_dispatch_details.length > 0) {
+                        url = "{{ url('personnel/laborApply/dispatch') }}/" + labor_company_dispatch.id + '/detail/edit';
+                    } else {
+                        url = "{{ url('personnel/laborApply/dispatch') }}/" + labor_company_dispatch.id + '/detail/create';
+                    }
+                    return url;
+                }
+            },
+        });
+    </script>
+@endsection

+ 85 - 0
resources/views/personnel/laborApply/edit.blade.php

@@ -0,0 +1,85 @@
+@extends('layouts.app')
+@section('title')录入-临时工申请协调@endsection
+
+@section('content')
+    <div class="container-fluid" id="list">
+        <div class="card col-md-8 offset-md-2">
+            <div class="card-body">
+                <form action="{{ route('laborApply.store') }}" method="POST" accept-charset="UTF-8">
+                    @csrf
+                    @include('shared._error')
+                    {{--仓库--}}
+                    <div class="from-group row mt-3">
+                        <label for="warehouse_id" class="col-2 col-form-label text-right">仓库</label>
+                        <div class="col-8">
+                            <select class="form-control" id="warehouse_id" name="warehouse_id" required>
+                                <option value="" hidden disabled selected>请选择仓库</option>
+                                @foreach($warehouses as $warehouse)
+                                    <option {{ $warehouse->id == $laborApply->warehouse_id ? 'selected':''}}>{{ $warehouse->name }}</option>
+                                @endforeach
+                            </select>
+                        </div>
+                    </div>
+                    {{--所属组别--}}
+                    <div class="from-group row mt-3">
+                        <label for="user_workgroup_id" class="col-2 col-form-label text-right">所属组别</label>
+                        <div class="col-8">
+                            <select class="form-control" id="user_workgroup_id" name="user_workgroup_id" required>
+                                <option value="" hidden disabled selected>请选择所属组别</option>
+                                @foreach($userWorkGroups as $userWorkGroup)
+                                    <option {{ $userWorkGroup->id == $laborApply->user_workgroup_id ? 'selected':''}}>{{ $userWorkGroup->name }}</option>
+                                @endforeach
+                            </select>
+                        </div>
+                    </div>
+                    {{--男工人数--}}
+                    <div class="from-group row mt-3">
+                        <label for="man_num" class="col-2 col-form-label text-right">男工人数</label>
+                        <div class="col-8">
+                            <input type="number" class="form-control" id="man_num" name="man_num" value="{{ $laborApply->man_num }}" required>
+                        </div>
+                    </div>
+
+                    {{--女工人数--}}
+                    <div class="from-group row mt-3">
+                        <label for="woman_num" class="col-2 col-form-label text-right">女工人数</label>
+                        <div class="col-8">
+                            <input type="number" class="form-control" id="woman_num" name="woman_num" value="{{ $laborApply->woman_num }}" required>
+                        </div>
+                    </div>
+                    {{--用工要求--}}
+                    <div class="from-group row mt-3">
+                        <label for="remark" class="col-2 col-form-label text-right">用工要求</label>
+                        <div class="col-8">
+                            <textarea class="form-control" rows="3"
+                                      placeholder required
+                                      name="remark" id="remark"> {{ $laborApply->remark }} </textarea>
+                        </div>
+                    </div>
+                    {{--提交--}}
+                    <div class="form-group row mt-5">
+                        <div class="col-8 offset-2">
+                            <input type="submit" class="btn btn-success form-control">
+                        </div>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        new Vue({
+            el: "#list",
+            data: {
+                {{--can_create_status: {!! $can_create_status !!}--}}
+            },
+            mounted() {
+
+            },
+
+            methods: {}
+        });
+    </script>
+@endsection

+ 146 - 0
resources/views/personnel/laborApply/index.blade.php

@@ -0,0 +1,146 @@
+@extends('layouts.app')
+@section('title')查看-临时工申请协调@endsection
+
+@section('content')
+    <div id="list" class="d-none">
+        <div class="container-fluid">
+            <div id="form_div"></div>
+            <div class="ml-3 form-inline" id="btn">
+                @can('人事管理')
+                    <span class="ml-1">
+                        <a href="{{ route('laborApply.createDispatch') }}" type="button"
+                           class="btn btn-sm ml-2 btn-outline-danger">重新生成劳务派遣数据</a>
+                    </span>
+                @endcan
+            </div>
+            @include('shared._messages')
+            <table class="table table-striped table-bordered table-hover card-body td-min-width-80" id="table">
+                <tr v-for="(labor_apply,i) in labor_applies" @click="selectTr===i+1?selectTr=0:selectTr=i+1"
+                    :class="selectTr===i+1?'focusing' : ''">
+                    <td>
+                        <input class="checkItem" type="checkbox" :value="labor_apply.id">
+                    </td>
+                    <td>@{{ i+1 }}</td>
+                    <td>@{{ labor_apply.id }}</td>
+                    <td>@{{ labor_apply.status }}</td>
+                    <td>@{{ labor_apply.created_at }}</td>
+                    <td>@{{ labor_apply.remark }}</td>
+                    <td>@{{ labor_apply.warehouse && labor_apply.warehouse.name }}</td>
+                    <td>@{{ labor_apply.user_work_group && labor_apply.user_work_group.name }}</td>
+                    <td>@{{ labor_apply.apply_user && labor_apply.apply_user.name }}</td>
+                    <td>@{{ labor_apply.man_num }}</td>
+                    <td>@{{ labor_apply.woman_num }}</td>
+                    <td>@{{ labor_apply.actual_num }}</td>
+                    <td>@{{ labor_apply.arrive_rate }}</td>
+                    <td>
+                        <a v-if="labor_apply.status === '创建'" :href="getEditlUrl(labor_apply)"
+                           class="btn btn-outline-secondary btn-sm" role="button">修改</a>
+
+                        <form v-if="labor_apply.status === '劳务接单'" :action="getUpdatelUrl(labor_apply)" method="post"
+                              style="display: inline-block;">
+                        {{ csrf_field() }}
+                        {{ method_field('PATCH') }}
+                        <!-- Button trigger modal -->
+                            <button type="button" class="btn btn-primary" data-toggle="modal"
+                                    data-target="#actualNumModal">
+                                实到人数
+                            </button>
+
+                            <!-- Modal -->
+                            <div class="modal fade" id="actualNumModal" tabindex="-1"
+                                 aria-labelledby="actualNumModalLabel" aria-hidden="true">
+                                <div class="modal-dialog">
+                                    <div class="modal-content">
+                                        <div class="modal-header">
+                                            <h5 class="modal-title" id="actualNumModalLabel">实到人数</h5>
+                                            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                                                <span aria-hidden="true">&times;</span>
+                                            </button>
+                                        </div>
+                                        <div class="modal-body">
+                                            <div class="form-group">
+                                                <input type="number" class="form-control" name="actual_num">
+                                            </div>
+                                        </div>
+                                        <div class="modal-footer">
+                                            <button type="button" class="btn btn-secondary" data-dismiss="modal">取消
+                                            </button>
+                                            <button type="submit" class="btn btn-primary">确认</button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </form>
+                    </td>
+                </tr>
+            </table>
+            {{ $labor_applies->links() }}
+        </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>
+        new Vue({
+            el: "#list",
+            data: {
+                labor_applies: [
+                    @foreach( $labor_applies as $labor_apply )
+                        {!! $labor_apply !!},
+                    @endforeach
+                ],
+                selectTr: 0
+            },
+            mounted() {
+                console.log(this.labor_applies);
+                $('#list').removeClass('d-none');
+                let _this = this;
+                $(".up").slideUp();
+                let data = []
+                _this.form = new query({
+                    el: '#form_div',
+                    condition: data,
+                    appendDom: "btn",
+                });
+                _this.form.init();
+                let column = [
+                    {name: 'index', value: '序号', neglect: true},
+                    {name: 'id', value: '任务号'},
+                    {name: 'status', value: '状态'},
+                    {name: 'created_at', value: '申请日期'},
+                    {name: 'remark', value: '用工要求'},
+                    {name: 'warehouse', value: '仓库'},
+                    {name: 'user_workgroup_id', value: '仓库小组'},
+                    {name: 'apply_user', value: '申请人'},
+                    {name: 'man_num', value: '男工人数'},
+                    {name: 'woman_num', value: '女工人数'},
+                    {name: 'actual_num', value: '到岗人数'},
+                    {name: 'arrive_rate', value: '到岗率'},
+                    {name: 'do', value: '操作'},
+
+                ];
+                new Header({
+                    el: "table",
+                    name: "labor_applies",
+                    column: column,
+                    data: this.labor_applies,
+                    restorationColumn: 'addtime',
+                    fixedTop: ($('#form_div').height()) + ($('#btn').height()) + 1,
+                }).init();
+            },
+
+            methods: {
+                getEditlUrl(obj) {
+                    return "{{ url('personnel/laborApply') }}/" + obj.id + '/edit';
+                },
+                getUpdatelUrl(obj) {
+                    return "{{ url('personnel/laborApply') }}/" + obj.id;
+                },
+
+            }
+        });
+    </script>
+@endsection

+ 16 - 0
routes/web.php

@@ -48,6 +48,22 @@ Route::get('personnel/checking-in/goGetQRCode','QRCodeController@goGetQRCode');
 Route::get('personnel/checking-in/QRCode','QRCodeController@QRCode');
 Route::get('personnel/checking-in/importAndExportQRCode','QRCodeController@importAndExportQRCode');
 Route::post('personnel/checking-in/refreshQRCode','QRCodeController@refreshQRCode');
+
+//人事管理
+Route::group(['prefix'=>'personnel'],function() {
+    //临时开放录入
+    Route::put('laborApply/temporaryOpen','LaborApplyController@temporaryOpen')->name('laborApply.temporaryOpen');
+    Route::get('laborApply/createDispatch','LaborApplyController@createDispatch')->name('laborApply.createDispatch');
+    //劳务派遣查看
+    Route::get('laborApply/dispatch','LaborCompanyDispatchController@index')->name('laborApplyDispatch.index');
+    Route::get('laborApply/dispatch/{laborCompanyDispatch}/detail/create','LaborCompanyDispatchController@createDetail')->name('laborApplyDispatch.createDetail');
+    Route::get('laborApply/dispatch/{laborCompanyDispatch}/detail/edit','LaborCompanyDispatchController@editDetail')->name('laborApplyDispatch.editDetail');
+    Route::post('laborApply/dispatch/{laborCompanyDispatch}/detail','LaborCompanyDispatchController@storeDetail')->name('laborApplyDispatch.storeDetail');
+
+    Route::resource('laborApply', 'LaborApplyController');
+
+});
+
 //监视器
 Route::get('station/monitor/{station}','StationController@monitorShow');
 //打卡记录

+ 44 - 0
tests/Services/LaborApplyService/AllocationLaborToLaborCompanyTest.php

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