Open haidv1992 opened 1 month ago
4.35.0
8.2
Laravel
v10.48.10
php artisan scribe:config:diff laravel.middleware.0 => "" try_it_out.use_csrf => true auth.enabled => true auth.default => true
namespace Modules\Plan\app\Http\Requests; use App\Models\PosUpdate; use App\Pos; use App\Support\Enum\ActionCode; use Carbon\Carbon; use Illuminate\Foundation\Http\FormRequest; use Modules\Plan\app\Models\Plan; use Modules\Plan\app\Models\PlanResult; use Modules\Plan\app\Services\PlanConfigurationService; class CheckinRequest extends FormRequest { protected $bodyParams = array(); /** * Get the validation rules that apply to the request. */ public function rules(): array { $configService = app(PlanConfigurationService::class); $config = $configService->getCheckinConfiguration(); $posChecklists = $configService->getChecklistsConfiguration(); $rules = [ 'plan_id' => 'sometimes|nullable|exists:plans,id', 'posCode' => 'required|exists:pos,posCode', ]; if (!empty($posChecklists)) { $checklistCount = count($posChecklists); $rules['checklist'] = ['required', 'array', 'min:'.$checklistCount, 'max:'.$checklistCount]; $checklistRules = [ '*.id' => 'required|integer|exists:pos_checklists,id', '*.status' => 'required|boolean', '*.note' => 'nullable|string', '*.photo' => 'nullable|file|mimetypes:image/jpeg,image/jpg,image/png,image/webp|max:500', ]; $rules['checklist.*'] = $checklistRules; foreach ($posChecklists as $item) { $this->bodyParams['checklist'][] = [ 'id' => [ 'description' => 'ID of the checklist item', 'example' => $item->id ], 'status' => [ 'description' => "Status of the checklist item {$item->name}", 'example' => true ], 'note' => [ 'description' => 'Note for the checklist item', 'example' => 'This is a sample note' ], 'photo' => [ 'description' => 'Optional photo for the checklist item', 'example' => new \Illuminate\Http\UploadedFile(public_path('assets/media/demo/checkin/img-1.png'), 'sample.jpg') ], ]; } } foreach ($config as $item) { $this->addConfigRules($rules, $item); } return $rules; } protected function prepareForValidation() { $checklistData = $this->input('checklist', []); foreach ($checklistData as $id => &$data) { if (isset($data['status'])) { $data['status'] = filter_var($data['status'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); } } $this->merge([ 'checklist' => $checklistData, ]); } public function withValidator($validator) { $validator->after(function ($validator) { if (!$validator->errors()->isEmpty()) { return $validator; } $this->handleChecklistsValidation($validator); $this->handlePostValidation($validator); }); } protected function handleChecklistsValidation($validator){ $configService = app(PlanConfigurationService::class); $requiredChecklistIds = $configService->getChecklistsConfiguration()->pluck('id')->sort()->values()->all(); $submittedChecklistIds = collect($this->input('checklist', [])) ->pluck('id') ->sort() ->values() ->all(); if ($requiredChecklistIds !== $submittedChecklistIds) { $validator->errors()->add('checklist', 'Tất cả các mục trong danh sách kiểm tra phải được bao gồm và khớp với ID được yêu cầu.'); } } protected function handlePostValidation($validator) { $mergeData = []; $planOrPos = $this->planOrPosExists(); $pendingUpdate = $this->checkForPendingUpdates($validator); if ($pendingUpdate) { $mergeData['pendingUpdate'] = $pendingUpdate; } if (!$this->input('plan_id')) { $this->handleNoPlanOrPos($validator, $mergeData); $lastAction = $mergeData['lastAction']; } elseif (!$planOrPos) { $validator->errors()->add('error', 'Không tìm thấy kế hoạch hoặc điểm bán phù hợp.'); return; } else { $mergeData['plan'] = $planOrPos; $mergeData['pos'] = $planOrPos->pos()->where('posCode', $this->posCode)->first(); $lastAction = $mergeData['pos']->visits()->latest()->first(); } if ($lastAction && $lastAction->action_code == ActionCode::ACTION_CHECK_IN) { $validator->errors()->add('action_code', 'Check-out is required before check-in.'); } $this->merge($mergeData); } protected function handleNoPlanOrPos($validator, &$mergeData) { $pos = Pos::where('posCode', $this->input('posCode'))->first(); if (!$pos) { $validator->errors()->add('posCode', 'No valid POS found with provided POS Code.'); return; // Exit early if no valid POS is found to prevent further processing } $lastAction = $pos->visits()->latest()->first(); $mergeData['pos'] = $pos; $mergeData['lastAction'] = $lastAction; // Store last action to use in post validation checks } private function planOrPosExists() { $posCode = $this->input('posCode'); return Plan::with('pos') ->where('month', Carbon::now()->format('Y-m')) ->where('status', Plan::STATUS_PLAN_APPROVED) ->whereHas('pos', function ($query) use ($posCode) { $query->where('posCode', $posCode); }) ->find($this->input('plan_id')); } private function checkForPendingUpdates($validator) { $posCode = $this->input('posCode'); $pendingUpdate = PosUpdate::where('pos_id', $posCode) ->where('status', PosUpdate::STATUS_PENDING) ->first(); if ($pendingUpdate) { $existingCheckin = PlanResult::where('posCode', $posCode) ->where('pos_update_id', $pendingUpdate->id) ->first(); if ($existingCheckin) { $validator->errors()->add('pos_update', 'Check-in không được phép do tồn tại một đề xuất đang chờ duyệt.'); } } return $pendingUpdate; } protected function addConfigRules(&$rules, $item) { switch ($item['type']) { case 'file': $this->handleFileRules($rules, $item); break; case 'coordinates': $rules['lat'] = 'required|numeric'; $rules['lon'] = 'required|numeric'; break; } } protected function handleFileRules(&$rules, $item) { $baseKey = $item['key']; $rules[$baseKey] = [ 'required', 'array', 'max:' . $item['max_photos'], ]; $rules[$baseKey . '.*'] = [ 'file', 'mimetypes:' . $item['rules']['mimetypes'], 'max:' . $item['rules']['max'], 'dimensions:max_width=' . $item['rules']['max_width'], ]; $this->bodyParams[$baseKey] = [ 'description' => "{$item['name']} - {$item['description']}", "required" => true, 'example' => new \Illuminate\Http\UploadedFile(public_path('assets/media/demo/checkin/img-1.png'), 'sample.jpg') ]; } public function bodyParameters() { return array_merge([ 'plan_id' => [ 'description' => 'ID kế hoạch', 'example' => 1 ], 'posCode' => [ 'description' => 'Mã điểm bán', 'example' => 124000010436 ], // 'checklist' => [ // 'description' => 'Điểm bán sẵn sàng để bán hàng?. [Get list](/docs#pos-GETapi-v1-pos-pos-readiness-checklists)', // ], ], $this->bodyParams); } }
php artisan scribe:generate
Scribe version
4.35.0
PHP version
8.2
Framework
Laravel
Framework version
v10.48.10
Scribe config
What happened?
File request
php artisan scribe:generate
Docs