object_type); $approvalObject = $approvalObjectType->modelBuilderAllowed($request->object_id)->findOrFail($request->object_id); throw_validation_if( in_array($approvalObject?->approval_status, [ObjectApprovalStatus::DOING->value]), 'Do not initiate duplicate approvals' ); $approvalFlow = $this->getApprovalFlow($approvalObjectType, $approvalObject); $this->createApproval($approvalFlow, $approvalObjectType, $approvalObject->id, $request->remark); $this->changeApprovalStatus($approvalObject); } protected function createApproval( ApprovalFlow $approvalFlow, ApprovalObjectType $approvalObjectType, int $objectId, string $remark = null ): void { $firstNode = $approvalFlow->nodes[1]; $approval = Approval::query()->create([ 'approval_flow_id' => $approvalFlow->id, 'object_type' => $approvalObjectType->flowType()->value, 'object_id' => $objectId, 'node_level' => $firstNode['level'], 'approval_mode' => $firstNode['approval_mode'], 'users' => sprintf(",%s,", implode(',', $firstNode['approval_users'])), 'remark' => $remark, 'created_by' => Auth::id(), 'status' => ObjectApprovalStatus::DOING, 'company_id' => Auth::user()->company_id, ]); $extraFields = [ 'now' => 0, 'next' => 1, 'approval_mode' => $firstNode['approval_mode'], ]; if ($approval->approval_mode == ApprovalMode::SEQUENTIAL_APPROVAL->value) { $extraFields['next_sequential_user'] = $firstNode['approval_users'][0]; } ActionRepository::createByApproval( $approval, ObjectAction::APPROVAL_REQUEST, extraFields: $extraFields, ); } protected function changeApprovalStatus($approvalObject): void { $approvalObject->approval_status = ObjectApprovalStatus::DOING; $approvalObject->save(); } protected function triggerAction (string $comment = null): void { $objectAction = match ($this->approval->status) { ObjectApprovalStatus::APPROVED->value => ObjectAction::APPROVAL_APPROVED, ObjectApprovalStatus::DOING->value => ObjectAction::APPROVED_TO_NEXT_NODE, ObjectApprovalStatus::REJECTED->value => ObjectAction::APPROVAL_REJECTED, }; } protected function getApprovalFlow(ApprovalObjectType $approvalObjectType, $approvalObject) { $approvalFlow = ApprovalFlow::query() ->where("type", $approvalObjectType->flowType()) ->when( $approvalObjectType->flowType() == ApprovalFlowType::TASK, fn ($query) => $query->orWhere([ 'object_type' => ApprovalFlowObjectType::PROJECT->value, 'object_id' => $approvalObject->id, ]) ) ->where("status", 1) ->orderByDesc("created_at") ->first(); throw_validation_if(! $approvalFlow, 'Clearly set up approval flow rules first.'); return $approvalFlow; } }