ProcessController.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Exports\WaybillExport;
  4. use App\Owner;
  5. use App\Process;
  6. use App\ProcessDaily;
  7. use App\ProcessDailyParticipant;
  8. use App\Tutorial;
  9. use App\UserDetail;
  10. use App\UserDutyCheck;
  11. use Carbon\Carbon;
  12. use Illuminate\Database\Eloquent\Builder;
  13. use Illuminate\Http\Request;
  14. use Illuminate\Support\Facades\Auth;
  15. use Illuminate\Support\Facades\DB;
  16. use Illuminate\Support\Facades\Gate;
  17. use Illuminate\Support\Facades\Validator;
  18. use Maatwebsite\Excel\Facades\Excel;
  19. class ProcessController extends Controller
  20. {
  21. public function conditionQuery(Request $request,$processes){
  22. if(!Gate::allows('二次加工管理-查询')){ return redirect(url('/')); }
  23. $today=Carbon::now()->subDays(15);
  24. if ($request->input('commodity_barcode')){
  25. $barcode=$request->input('commodity_barcode');
  26. $processes=$processes->with('commodity')->whereHas('commodity',function (Builder $query)use($barcode){
  27. $query->where('barcode','like',$barcode.'%');
  28. });
  29. }
  30. if ($request->input('date_start')){
  31. $processes=$processes->where('created_at','>=',$request->input('date_start'));
  32. }
  33. if ($request->input('date_end')){
  34. $processes=$processes->where('created_at','<=',$request->input('date_end'));
  35. }
  36. if ($request->input('owner_id')){
  37. $processes=$processes->where('owner_id',$request->input('owner_id'));
  38. }
  39. if ($request->input('wms_code')){
  40. $processes=$processes->where('wms_code','like','%'.$request->input('wms_code').'%')->where('created_at','>',$today->format('Y-m-d'));
  41. }
  42. $processes=$processes->paginate($request->input('paginate')??50);
  43. return $processes;
  44. }
  45. /**
  46. * Display a listing of the resource.
  47. * @param Request $request
  48. * @return \Illuminate\Http\Response
  49. */
  50. public function index(Request $request)
  51. {
  52. if(!Gate::allows('二次加工管理-查询')){ return redirect(url('/')); }
  53. $processes=Process::with(['tutorials','processesContents'])->orderBy('processes.id','DESC');
  54. if ($request->input('checkSign')){
  55. $excel=$this->isExport($request,$processes);
  56. return $excel;
  57. }
  58. $processes=$this->conditionQuery($request,$processes);
  59. $owners=Owner::select('id','name')->get();
  60. return view('process.index',['processes'=>$processes,'owners'=>$owners]);
  61. }
  62. //获取导出数据
  63. public function isExport(Request $request,$processes){
  64. if(!Gate::allows('二次加工管理-查询')){ return redirect(url('/')); }
  65. if ($request->input('checkSign')=="-1"){
  66. $processes=$this->conditionQuery($request,$processes);
  67. $excel=$this->export($processes);
  68. return $excel;
  69. }
  70. $id = explode( ',',$request->input('checkSign'));
  71. $processes=$processes->whereIn('id',$id)->get();
  72. $excel=$this->export($processes);
  73. return $excel;
  74. }
  75. //获取每日参与人
  76. public function getDailyParticipant(Request $request){
  77. if(!Gate::allows('二次加工管理-登记工时')){ return redirect(url('/')); }
  78. $today=Carbon::now()->format('Y-m-d');
  79. $id=$request->input('id');
  80. $processDailies=ProcessDaily::with(['processDailyParticipants','process'])->orderBy('date','DESC')
  81. ->where('process_id',$id)->get();
  82. if ($processDailies){
  83. $result=$this->createDeficiencyData($processDailies,$today);
  84. if ($result){
  85. $processDailies=ProcessDaily::with(['processDailyParticipants','process'])
  86. ->orderBy('date','DESC')->where('process_id',$id)->get();
  87. }
  88. $processDailies=$this->countManHour($processDailies);
  89. }
  90. return $processDailies;
  91. }
  92. //根据参与人查找打卡记录计算工时信息
  93. public function countManHour($processDailies){
  94. foreach ($processDailies as $processDaily){
  95. $date=$processDaily->date;
  96. foreach ($processDaily->processDailyParticipants as $processDailyParticipant){
  97. $processDailyParticipant->started_at=Carbon::parse($processDailyParticipant->started_at)->format('H:i');
  98. $processDailyParticipant->ended_at=Carbon::parse($processDailyParticipant->ended_at)->format('H:i');
  99. $processDailyParticipant=$this->countParticipantManHour($processDailyParticipant,$date);
  100. }
  101. }
  102. return $processDailies;
  103. }
  104. //计算单参与人工时信息
  105. public function countParticipantManHour($processDailyParticipant,$date){
  106. $user=$processDailyParticipant->user_id;
  107. $userDutyCheckStart=UserDutyCheck::select('id','checked_at')->where('user_id',$user)
  108. ->where('checked_at','like',$date.'%')->where('type','登入')->orderBy('id')->first();
  109. $userDutyCheckEnd=UserDutyCheck::select('id','checked_at')->where('user_id',$user)
  110. ->where('checked_at','like',$date.'%')->where('type','登出')->orderBy('id','desc')->first();
  111. //跨日情况寻找下一天
  112. if (!$userDutyCheckEnd){
  113. $date=date("Y-m-d",strtotime("+1 day",strtotime($date)));
  114. $userDutyCheckEnd=UserDutyCheck::select('id','checked_at')->where('user_id',$user)
  115. ->where('checked_at','like',$date.'%')->where('type','登出')->orderBy('id','desc')->first();
  116. }
  117. if (!$userDutyCheckStart || !$userDutyCheckEnd){
  118. return $processDailyParticipant;
  119. }
  120. $dateStart=Carbon::parse($userDutyCheckStart->checked_at);
  121. $dateEnd=Carbon::parse($userDutyCheckEnd->checked_at);
  122. $hour=($dateEnd->diffInSeconds($dateStart))/3600; //打卡工时
  123. if ($processDailyParticipant->dinner_duration)$hour=$hour-(($processDailyParticipant->dinner_duration)/60); //减晚饭时间
  124. $hour=$this->isHour($userDutyCheckStart,$hour); //去除休息时间
  125. $processDailyParticipant->hour=round($hour,2);
  126. if ($hour&&$processDailyParticipant->hour_count){
  127. $diff=abs(round($processDailyParticipant->hour_count-$hour,2));
  128. $processDailyParticipant->diff=$diff;
  129. }
  130. //计件工
  131. if ($processDailyParticipant->unit_price){
  132. return $processDailyParticipant;
  133. }
  134. if ($hour&&$hour>8){
  135. $processDailyParticipant->billingHour=8;
  136. return $processDailyParticipant;
  137. }
  138. if ($hour&&$hour<=8){
  139. $processDailyParticipant->billingHour=round($hour,2);
  140. }
  141. return $processDailyParticipant;
  142. }
  143. //打卡工时减休息时间
  144. public function isHour($userDutyCheckStart,$hour){
  145. $date=$userDutyCheckStart->checked_at;
  146. $date=Carbon::parse($date)->format('H');
  147. if ((int)$date<=11){
  148. $hour=$hour-1;
  149. }
  150. return $hour;
  151. }
  152. //生成二次加工单缺失时间记录及本日记录
  153. public function createDeficiencyData($processDailies,$today){
  154. if (!$processDailies||!$today)return false;
  155. $processDailiesArr=[];
  156. foreach ($processDailies as $processDaily){
  157. $processDailiesArr[$processDaily->date]=$processDaily;
  158. }
  159. $processDailyOne=$processDailies[count($processDailies)-1];
  160. $startDate=Carbon::parse($processDailyOne->date);
  161. $diffDay=$startDate->diffInDays($today,true);
  162. $remain=$processDailyOne->remain;
  163. $processId=$processDailyOne->process_id;
  164. for ($i=1;$i<=$diffDay;$i++){
  165. $date=date("Y-m-d",strtotime('+'.strval($i)." day",strtotime($startDate)));
  166. if (!isset($processDailiesArr[$date])){
  167. $processDaily=new ProcessDaily([
  168. 'process_id'=>$processId,
  169. 'date'=>$date,
  170. 'output'=>0,
  171. 'remain'=>$remain
  172. ]);
  173. $processDaily->save();
  174. }
  175. if (isset($processDailiesArr[$date])){
  176. $remain=$remain-($processDailiesArr[$date]->output);
  177. }
  178. }
  179. return true;
  180. }
  181. //驳回二次加工单
  182. public function reject($id){
  183. if(!Gate::allows('二次加工管理-接单与驳回')){ return redirect(url('/')); }
  184. $process=Process::select('id','status')->find($id);
  185. $process->status="驳回";
  186. $process->update();
  187. $this->log(__METHOD__,"驳回二次加工单_".__FUNCTION__,json_encode($process),Auth::user()['id']);
  188. return $process;
  189. }
  190. //接单
  191. public function receive($id){
  192. if(!Gate::allows('二次加工管理-接单与驳回')){ return redirect(url('/')); }
  193. $process=Process::select('id','status')->find($id);
  194. $process->status="待加工";
  195. $process->update();
  196. $this->log(__METHOD__,"接单二次加工单_".__FUNCTION__,json_encode($process),Auth::user()['id']);
  197. return $process;
  198. }
  199. //完成
  200. public function accomplish($id){
  201. if(!Gate::allows('二次加工管理-验收完成')){ return redirect(url('/')); }
  202. $process=Process::select('id','status')->find($id);
  203. $process->status="已完成";
  204. $process->update();
  205. $this->log(__METHOD__,"完成二次加工单_".__FUNCTION__,json_encode($process),Auth::user()['id']);
  206. return $process;
  207. }
  208. //修改当日产量
  209. public function updateDailyOutput(Request $request){
  210. if(!Gate::allows('二次加工管理-登记工时')){ return redirect(url('/')); }
  211. $errors=$this->validator($request)->errors();
  212. if (count($errors)>0)return ['status'=>"error",'data'=>$errors];
  213. $id=$request->input('id');
  214. $output=$request->input('output');
  215. $processDaily=ProcessDaily::with('process')->find($id);
  216. $remain=$this->countRemain($processDaily);
  217. $processDaily->output=$output;
  218. $processDaily->remain=$remain;
  219. $processDaily->update();
  220. $this->log(__METHOD__,"修改当日产量".__FUNCTION__,json_encode($processDaily),Auth::user()['id']);
  221. return ['status'=>"success",'data'=>$processDaily];
  222. }
  223. //计算当日剩余 根据日期
  224. public function countRemain($processDaily){
  225. if (!$processDaily || !$processDaily->process) return;
  226. $processDailies=ProcessDaily::where('process_id',$processDaily->process_id)
  227. ->where('date','<=',$processDaily->date)->get();
  228. $sum=0;
  229. foreach ($processDailies as $processDaily){
  230. $sum=$sum+($processDaily->output);
  231. }
  232. return ($processDaily->process->amount)-$sum;
  233. }
  234. //添加参与人
  235. public function shortProcessDailyParticipant(Request $request){
  236. if(!Gate::allows('二次加工管理-登记工时')){ return redirect(url('/')); }
  237. $errors=$this->validatorProcessDailyParticipant($request)->errors();
  238. if (count($errors)>0)return ['status'=>"error",'data'=>$errors];
  239. $user_id=$request->input('user_id');
  240. $started_at=$request->input('started_at');
  241. $ended_at=$request->input('ended_at');
  242. $daily_id=$request->input('daily_id');
  243. $hour_count=$request->input('hour_count');
  244. $unit_count=$request->input('unit_count');
  245. $hour_price=$request->input('hour_price');
  246. $unit_price=$request->input('unit_price');
  247. $dinner_duration=$request->input('dinner_duration');
  248. $remark=$request->input('remark');
  249. $processDailyParticipant=new ProcessDailyParticipant([
  250. 'process_daily_id'=>$daily_id,
  251. 'user_id'=>$user_id,
  252. 'started_at'=>$started_at,
  253. 'ended_at'=>$ended_at,
  254. 'hour_price'=>$hour_price,
  255. 'hour_count'=>$hour_count,
  256. 'unit_price'=>$unit_price,
  257. 'unit_count'=>$unit_count,
  258. 'dinner_duration'=>$dinner_duration,
  259. 'remark'=>$remark,
  260. ]);
  261. $processDailyParticipant->save();
  262. $this->log(__METHOD__,"添加新参与人".__FUNCTION__,json_encode($processDailyParticipant),Auth::user()['id']);
  263. $processDaily=ProcessDaily::select('date')->find($daily_id);
  264. $date=$processDaily->date;
  265. $processDailyParticipant=$this->countParticipantManHour($processDailyParticipant,$date);
  266. return ['status'=>"success",'data'=>$processDailyParticipant];
  267. }
  268. //验证参与人
  269. public function verifyUserName(Request $request){
  270. $userName=$request->input('userName');
  271. if (!$userName) return;
  272. $result=$this->seekUserLabor($userName);
  273. return $result;
  274. }
  275. //根据全名查询临时工
  276. public function seekUserLabor($userName){
  277. $userDetails=UserDetail::with('user_labor')->where('type','临时工')->where('full_name',$userName)->get();
  278. if (!$userDetails)return;
  279. if (count($userDetails)==1){
  280. if (!$userDetails[0]->user_labor)return;
  281. return $userDetails[0];
  282. }
  283. //多个同名
  284. foreach ($userDetails as $userDetail){
  285. $userDutyCheck=UserDutyCheck::select('checked_at')->where("user_id",$userDetail->user_id)->orderBy('checked_at','DESC')->first();
  286. if ($userDutyCheck)$userDetail->checked_at=$userDutyCheck->checked_at;
  287. }
  288. if (!$userDetails)return;
  289. return $userDetails;
  290. }
  291. //修改参与人
  292. public function updateProcessDailyParticipant(Request $request){
  293. if(!Gate::allows('二次加工管理-登记工时')){ return redirect(url('/')); }
  294. $id=$request->input('id');
  295. if (!$id) return ['status'=>"error",'data'=>"修改失败,ID未传递"];
  296. $errors=$this->validatorProcessDailyParticipant($request)->errors();
  297. if (count($errors)>0)return ['status'=>"error",'data'=>$errors];
  298. $processDailyParticipant=ProcessDailyParticipant::with('process_daily')->find($id);
  299. if (!$processDailyParticipant || ! $processDailyParticipant->process_daily) return ['status'=>"error",'data'=>"修改失败,该信息不存在"];
  300. $processDailyParticipant->user_id=$request->input('user_id');
  301. $processDailyParticipant->started_at=$request->input('started_at');
  302. $processDailyParticipant->ended_at=$request->input('ended_at');
  303. $processDailyParticipant->hour_count=$request->input('hour_count');
  304. $processDailyParticipant->unit_count=$request->input('unit_count');
  305. $processDailyParticipant->hour_price=$request->input('hour_price');
  306. $processDailyParticipant->unit_price=$request->input('unit_price');
  307. $processDailyParticipant->dinner_duration=$request->input('dinner_duration');
  308. $processDailyParticipant->remark=$request->input('remark');
  309. $processDailyParticipant->update();
  310. $this->log(__METHOD__,"修改参与人".__FUNCTION__,json_encode($processDailyParticipant),Auth::user()['id']);
  311. $processDailyParticipant=$this->countParticipantManHour($processDailyParticipant,$processDailyParticipant->process_daily->date);
  312. return ['status'=>"success",'data'=>$processDailyParticipant];
  313. }
  314. //参与人审核
  315. public function processDailyParticipantAudit($id){
  316. if(!Gate::allows('二次加工管理-登记工时-审核')){ return redirect(url('/')); }
  317. $processDailyParticipant=ProcessDailyParticipant::select('id','status')->find($id);
  318. if (!$processDailyParticipant) return ['success'=>'false'];
  319. $processDailyParticipant->status='已审核';
  320. $processDailyParticipant->update();
  321. $this->log(__METHOD__,"登记工时参与人审核".__FUNCTION__,json_encode($processDailyParticipant),Auth::user()['id']);
  322. return ['success'=>'true','processDailyParticipant'=>$processDailyParticipant];
  323. }
  324. //临时工详情
  325. public function showUserDetail(Request $request){
  326. $id=$request->input('user_id');
  327. $userDetail=UserDetail::with('user_labor')->find($id);
  328. if (!$userDetail) return ['success'=>'false'];
  329. return ['success'=>'true','userDetail'=>$userDetail];
  330. }
  331. //获取全部教程
  332. public function getTutorials($id){
  333. $process=Process::with('tutorials')->find($id);
  334. $tutorials_id=[];
  335. if ($process->tutorials){
  336. foreach ($process->tutorials as $tutorial){
  337. array_push($tutorials_id,$tutorial->id);
  338. }
  339. }
  340. $tutorials=Tutorial::where('owner_id',$process->owner_id)->get();
  341. if ($tutorials_id && $tutorials) $tutorials=$tutorials->diff(Tutorial::whereIn('id',$tutorials_id)->get());
  342. return ['success'=>'true','data'=>$tutorials];
  343. }
  344. //添加教程关联
  345. public function selectedTutorial(Request $request){
  346. $process_id=$request->input('process_id');
  347. $tutorial_id=$request->input('tutorial_id');
  348. if (!$process_id || !$tutorial_id) return ['success'=>'false','data'=>'二次加工或教程传递错误!'];
  349. $tutorial=Tutorial::find($tutorial_id);
  350. if (!$tutorial)return ['success'=>'false','data'=>'未找到相关教程!'];
  351. $tutorial->processes()->syncWithoutDetaching([$process_id]);
  352. return ['success'=>'true','data'=>$tutorial];
  353. }
  354. //删除教程关联
  355. public function deleteTutorial(Request $request){
  356. $process_id=$request->input('process_id');
  357. $tutorial_id=$request->input('tutorial_id');
  358. if (!$process_id || !$tutorial_id) return ['success'=>'false','data'=>'二次加工或教程传递错误!'];
  359. DB::table('process_tutorial')->where('process_id',$process_id)->where('tutorial_id',$tutorial_id)->delete();
  360. return ['success'=>'true'];
  361. }
  362. /**
  363. * Show the form for creating a new resource.
  364. *
  365. * @return \Illuminate\Http\Response
  366. */
  367. public function create()
  368. {
  369. return view('process/create');
  370. }
  371. /**
  372. * Store a newly created resource in storage.
  373. *
  374. * @param \Illuminate\Http\Request $request
  375. * @return \Illuminate\Http\Response
  376. */
  377. public function store(Request $request)
  378. {
  379. //
  380. }
  381. /**
  382. * Display the specified resource.
  383. *
  384. * @param int $id
  385. * @return \Illuminate\Http\Response
  386. */
  387. public function show($id)
  388. {
  389. //
  390. }
  391. /**
  392. * Show the form for editing the specified resource.
  393. *
  394. * @param int $id
  395. * @return \Illuminate\Http\Response
  396. */
  397. public function edit($id)
  398. {
  399. //
  400. }
  401. /**
  402. * Update the specified resource in storage.
  403. *
  404. * @param \Illuminate\Http\Request $request
  405. * @param int $id
  406. * @return \Illuminate\Http\Response
  407. */
  408. public function update(Request $request, $id)
  409. {
  410. //
  411. }
  412. /**
  413. * Remove the specified resource from storage.
  414. *
  415. * @param int $id
  416. * @return \Illuminate\Http\Response
  417. */
  418. public function destroy($id)
  419. {
  420. //
  421. }
  422. //执行
  423. public function export($processes){
  424. if(!Gate::allows('二次加工管理-查询')){ return '没有权限'; }
  425. $row=[[
  426. 'id'=>'ID',
  427. 'code'=>'任务号',
  428. 'owner_name'=>'货主',
  429. 'bill_type'=>'单据类型',
  430. 'wms_code'=>'单据号',
  431. 'process_method_name'=>'加工类型',
  432. 'amount'=>'预期数量',
  433. 'unit_price'=>'单价',
  434. 'created_at'=>'提交日期',
  435. 'commodity_barcode'=>'商品编码',
  436. 'commodity_name'=>'商品名称',
  437. 'completed_amount'=>'实际数量',
  438. 'status'=>'状态',
  439. ]];
  440. $list=[];
  441. $i=0;
  442. foreach ($processes as $process){
  443. $w=[
  444. 'id'=>$process->id,
  445. 'code'=>$process->code ,
  446. 'owner_name'=>$process->owner_name ,
  447. 'bill_type'=>$process->bill_type ,
  448. 'wms_code'=>$process->wms_code ,
  449. 'process_method_name'=>$process->process_method_name,
  450. 'amount'=>$process->amount,
  451. 'unit_price'=>$process->unit_price,
  452. 'created_at'=>$process->created_at ,
  453. 'commodity_barcode'=>$process->commodity_barcode,
  454. 'commodity_name'=>$process->commodity_name ,
  455. 'completed_amount'=>$process->completed_amount,
  456. 'status'=>$process->status,
  457. ];
  458. $list[$i]=$w;
  459. $i++;
  460. }
  461. return Excel::download(new WaybillExport($row,$list),date('YmdHis', time()).'-二次加工单.xls');
  462. }
  463. public function validator(Request $request){
  464. $validator=Validator::make($request->input(),[
  465. 'id'=>['required','integer'],
  466. 'output'=>'required|min:0|max:999999|numeric',
  467. ],[
  468. 'required'=>':attribute 不应为空',
  469. 'min'=>':attribute 不得为0或为负',
  470. 'numeric'=>':attribute 必须为数字',
  471. 'max'=>':attribute 输入值过大',
  472. ],[
  473. 'output'=>'每日产量'
  474. ]);
  475. return $validator;
  476. }
  477. //参与人信息校验
  478. public function validatorProcessDailyParticipant(Request $request){
  479. $validator=Validator::make($request->input(),[
  480. 'daily_id'=>'filled',
  481. 'user_id'=>'required',
  482. 'started_at'=>'required|date_format:H:i',
  483. 'ended_at'=>'required|date_format:H:i',
  484. 'hour_price'=>'required_without:unit_price|min:0|max:999999|numeric',
  485. 'unit_price'=>'required_without:hour_price|min:0|max:999999|numeric',
  486. 'dinner_duration'=>'nullable|integer',
  487. 'hour_count'=>'required_with:hour_price|min:0|max:999999|numeric',
  488. 'unit_count'=>'required_with:unit_price|min:0|max:999999|numeric',
  489. 'remark'=>'nullable',
  490. ],[
  491. 'required'=>':attribute 不应为空',
  492. 'min'=>':attribute 不得为0或为负',
  493. 'numeric'=>':attribute 必须为数字',
  494. 'max'=>':attribute 输入值过大',
  495. 'required_without'=>':attribute 计时与计件至少填一项',
  496. 'date_format'=>':attribute 格式错误',
  497. 'integer'=>':attribute 选择错误',
  498. ],[
  499. 'daily_id'=>'所属每日单',
  500. 'user_id'=>'参与人',
  501. 'started_at'=>'开始时间',
  502. 'ended_at'=>'结束时间',
  503. 'hour_price'=>'计时工资',
  504. 'unit_price'=>'计件工资',
  505. 'dinner_duration'=>'晚饭时间',
  506. 'hour_count'=>'计时工时',
  507. 'unit_count'=>'计件数量',
  508. 'remark'=>'备注',
  509. ]);
  510. return $validator;
  511. }
  512. }