LaborApplyService.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. namespace App\Services;
  3. use App\LaborCompany;
  4. use App\LaborCompanyDispatch;
  5. use App\Traits\ServiceAppAop;
  6. use App\LaborApply;
  7. use App\Warehouse;
  8. use Illuminate\Database\Eloquent\Builder;
  9. use Illuminate\Database\Eloquent\Collection;
  10. use Illuminate\Support\Facades\Cache;
  11. use Illuminate\Support\Facades\DB;
  12. class LaborApplyService
  13. {
  14. //超时时间 默认为19:00
  15. const TIME_OUT_HOUR = 19;
  16. const LABOR_APPLY_STATUS = 'LABOR_APPLY_STATUS';
  17. const LABOR_APPLY_STATUS_TTL = 60 * 30;
  18. use ServiceAppAop;
  19. protected $modelClass = LaborApply::class;
  20. /**
  21. * 获取预约开放状态
  22. *
  23. * @return int 1 开放 2 禁止 3 临时开放
  24. */
  25. public function getCanCreateStatus(): int
  26. {
  27. $can_create_status = (now()->lte(now()->startOfDay()->addHours(self::TIME_OUT_HOUR))) ? LaborApply::CAN_CREATE_STATUS_OPEN : LaborApply::CAN_CREATE_STATUS_FORBID;
  28. if (Cache::has(self::LABOR_APPLY_STATUS)) {
  29. $can_create_status = Cache::get(self::LABOR_APPLY_STATUS);
  30. }
  31. return $can_create_status;
  32. }
  33. /**
  34. * 设置预约开放状态 1 开放 2 禁止 3 临时开放
  35. * @param int $status
  36. */
  37. public function setCanCreateStatus(int $status)
  38. {
  39. Cache::put(self::LABOR_APPLY_STATUS, $status, self::LABOR_APPLY_STATUS_TTL);
  40. }
  41. /**
  42. * 生产劳务派遣报表
  43. *
  44. * 查询全部仓库
  45. * 遍历仓库
  46. * 按照仓库,查询当日的的申请,将申请的男女工分别加和
  47. * 按照仓库查询对应的劳务所 按照优先级排序
  48. * 将男女工之和依次分配到 劳务所
  49. * 如果分配完成后 发现还有剩下的 则将状态设置为2
  50. */
  51. public function allocationLaborToLaborCompany(): array
  52. {
  53. //当前时间小于 1.00 禁止生成数据
  54. if (now()->lte(now()->startOfDay()->addHours(1))) return ['success' => false, 'error_message' => '当前时间禁止生成临时工派遣数据'];
  55. //派遣日期 为报表生成日期的后一天
  56. $dispatch_date = now()->addDay()->startOfDay()->toDateTimeString();
  57. //接口幂等性,删除旧的数据
  58. LaborCompanyDispatch::query()->where('dispatch_date', $dispatch_date)->delete();
  59. //查询全部仓库
  60. $warehouses = Warehouse::all();
  61. //给每个仓库计算分配数据 更改申请状态为指派成功
  62. foreach ($warehouses as $warehouse) {
  63. //查询当日的的申请,将申请的男女工分别加和
  64. $apply_man_nums = DB::table('labor_applies')
  65. ->selectRaw("sum(man_num) as man_num ,sum(woman_num) as woman_num")
  66. ->whereBetween('created_at', [now()->startOfDay(), now()->endOfDay()])
  67. ->where('warehouse_id', $warehouse->id)
  68. ->groupBy('warehouse_id')
  69. ->first();
  70. if (empty($apply_man_nums)) continue;
  71. //按照仓库查询对应的劳务所 按照优先级排序 单号正序 双号逆序
  72. $companies = $this->getCompaniesOrderByDay($warehouse);
  73. //需要的男工人数
  74. $man_num = $apply_man_nums->man_num;
  75. //需要的女工人数
  76. $woman_num = $apply_man_nums->woman_num;
  77. //插入的分配数据
  78. $laborCompanyDispatchInsertArray = $this->buildLaborCompanyDispatchInsertArray($companies, $man_num, $woman_num, $dispatch_date);
  79. //插入分配数据
  80. LaborCompanyDispatch::query()->insert($laborCompanyDispatchInsertArray);
  81. LaborApply::query()
  82. ->whereBetween('created_at', [now()->startOfDay(), now()->endOfDay()])
  83. ->where('warehouse_id', $warehouse->id)
  84. ->update([
  85. 'status' => 2,//指派成功
  86. ]);
  87. }
  88. return ['success' => true, 'message' => '生成临时工派遣数据成功'];
  89. }
  90. /**
  91. * 设置为状态为溢出
  92. * @param array $laborCompanyAppliesTarget
  93. * @return array
  94. */
  95. private function setExceedMaxLaborNumStatusExceedMaxLaborNum(array $laborCompanyAppliesTarget): array
  96. {
  97. return array_map(function (&$item) {
  98. $item['exceed_max_labor_num_status'] = LaborCompanyDispatch::EXCEED_MAX_LABOR_NUM;
  99. return $item;
  100. }, $laborCompanyAppliesTarget);
  101. }
  102. /**
  103. * 构建插入的分配数据
  104. * @param $companies
  105. * @param $man_num
  106. * @param $woman_num
  107. * @param string $dispatch_date
  108. * @return array
  109. */
  110. private function buildLaborCompanyDispatchInsertArray($companies, $man_num, $woman_num, string $dispatch_date): array
  111. {
  112. $laborCompanyDispatchInsertArray = [];
  113. //遍历劳务公司
  114. foreach ($companies as $company) {
  115. if ($man_num > 0 || $woman_num > 0) {
  116. //分配给指定劳务的男工人数
  117. $dispatch_man_num = $man_num > $company->man_num ? $company->man_num : $man_num;
  118. //分配给指定劳务的女工人数
  119. $dispatch_woman_num = $woman_num > $company->woman_num ? $company->woman_num : $woman_num;
  120. //待分配的男工
  121. $man_num -= $dispatch_man_num;
  122. //待分配的女工
  123. $woman_num -= $dispatch_woman_num;
  124. $laborCompanyDispatchInsertArray[] = [
  125. 'labor_company_id' => $company->id,
  126. 'man_num' => $dispatch_man_num,
  127. 'woman_num' => $dispatch_woman_num,
  128. 'dispatch_date' => $dispatch_date,
  129. 'exceed_max_labor_num_status' => LaborCompanyDispatch::NOT_EXCEED_MAX_LABOR_NUM,//没有超限额
  130. ];
  131. }
  132. }
  133. //全部劳务公司分配完后 还有剩余的男工/女工
  134. if ($man_num > 0 || $woman_num > 0) {
  135. //设置状态为超额
  136. $laborCompanyDispatchInsertArray = $this->setExceedMaxLaborNumStatusExceedMaxLaborNum($laborCompanyDispatchInsertArray);
  137. }
  138. return $laborCompanyDispatchInsertArray;
  139. }
  140. /**
  141. * 按照仓库查询对应的劳务所 按照优先级排序 单号正序 双号逆序
  142. * @param $warehouse
  143. * @return Builder[]|Collection
  144. */
  145. private function getCompaniesOrderByDay($warehouse)
  146. {
  147. $builder = LaborCompany::query()
  148. ->where('warehouse_id', $warehouse->id);
  149. if (now()->day % 2 === 0) {
  150. $builder->orderBy('priority');
  151. } else {
  152. $builder->orderBy('priority', 'desc');
  153. }
  154. return $builder->get();
  155. }
  156. }