StoreService.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. namespace App\Services\Approval;
  3. use App\Models\Approval;
  4. use App\Models\ApprovalFlow;
  5. use App\Models\Enums\ApprovalFlowObjectType;
  6. use App\Models\Enums\ApprovalFlowType;
  7. use App\Models\Enums\ApprovalMode;
  8. use App\Models\Enums\ApprovalObjectType;
  9. use App\Models\Enums\ObjectAction;
  10. use App\Models\Enums\ObjectApprovalStatus;
  11. use App\Repositories\ActionRepository;
  12. use Illuminate\Support\Facades\Auth;
  13. class StoreService
  14. {
  15. public function store()
  16. {
  17. $request = request();
  18. $approvalObjectType = ApprovalObjectType::from($request->object_type);
  19. $approvalObject = $approvalObjectType->modelBuilderAllowed($request->object_id)->findOrFail($request->object_id);
  20. throw_validation_if(
  21. in_array($approvalObject?->approval_status, [ObjectApprovalStatus::DOING->value]),
  22. 'Do not initiate duplicate approvals'
  23. );
  24. $approvalFlow = $this->getApprovalFlow($approvalObjectType, $approvalObject);
  25. $this->createApproval($approvalFlow, $approvalObjectType, $approvalObject->id, $request->remark);
  26. $this->changeApprovalStatus($approvalObject);
  27. }
  28. protected function createApproval(
  29. ApprovalFlow $approvalFlow, ApprovalObjectType $approvalObjectType, int $objectId, string $remark = null
  30. ): void
  31. {
  32. $firstNode = $approvalFlow->nodes[1];
  33. $approval = Approval::query()->create([
  34. 'approval_flow_id' => $approvalFlow->id,
  35. 'object_type' => $approvalObjectType->flowType()->value,
  36. 'object_id' => $objectId,
  37. 'node_level' => $firstNode['level'],
  38. 'approval_mode' => $firstNode['approval_mode'],
  39. 'users' => sprintf(",%s,", implode(',', $firstNode['approval_users'])),
  40. 'remark' => $remark,
  41. 'created_by' => Auth::id(),
  42. 'status' => ObjectApprovalStatus::DOING,
  43. ]);
  44. $extraFields = [
  45. 'now' => 0,
  46. 'next' => 1,
  47. 'approval_mode' => $firstNode['approval_mode'],
  48. ];
  49. if ($approval->approval_mode == ApprovalMode::SEQUENTIAL_APPROVAL->value) {
  50. $extraFields['next_sequential_user'] = $firstNode['approval_users'][0];
  51. }
  52. ActionRepository::createByApproval(
  53. $approval,
  54. ObjectAction::APPROVAL_REQUEST,
  55. extraFields: $extraFields,
  56. );
  57. }
  58. protected function changeApprovalStatus($approvalObject): void
  59. {
  60. $approvalObject->approval_status = ObjectApprovalStatus::DOING;
  61. $approvalObject->save();
  62. }
  63. protected function triggerAction (string $comment = null): void
  64. {
  65. $objectAction = match ($this->approval->status) {
  66. ObjectApprovalStatus::APPROVED->value => ObjectAction::APPROVAL_APPROVED,
  67. ObjectApprovalStatus::DOING->value => ObjectAction::APPROVED_TO_NEXT_NODE,
  68. ObjectApprovalStatus::REJECTED->value => ObjectAction::APPROVAL_REJECTED,
  69. };
  70. }
  71. protected function getApprovalFlow(ApprovalObjectType $approvalObjectType, $approvalObject)
  72. {
  73. $approvalFlow = ApprovalFlow::query()
  74. ->where("type", $approvalObjectType->flowType())
  75. ->when(
  76. $approvalObjectType->flowType() == ApprovalFlowType::TASK,
  77. fn ($query) => $query->orWhere([
  78. 'object_type' => ApprovalFlowObjectType::PROJECT->value,
  79. 'object_id' => $approvalObject->id,
  80. ])
  81. )
  82. ->where("status", 1)
  83. ->orderByDesc("created_at")
  84. ->first();
  85. throw_validation_if(! $approvalFlow, 'Clearly set up approval flow rules first.');
  86. return $approvalFlow;
  87. }
  88. }