ActionService.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. namespace App\Services\Approval;
  3. use App\Models\Approval;
  4. use App\Models\Enums\ApprovalMode;
  5. use App\Models\Enums\ApprovalObjectType;
  6. use App\Models\Enums\FileObjectType;
  7. use App\Models\Enums\ObjectAction;
  8. use App\Models\Enums\ObjectApprovalStatus;
  9. use App\Models\File;
  10. use App\Repositories\ActionRepository;
  11. use App\Services\File\Upload\FileUploadHelper;
  12. use Illuminate\Http\UploadedFile;
  13. use Illuminate\Support\Facades\Auth;
  14. class ActionService
  15. {
  16. use FileUploadHelper;
  17. protected ?Approval $approval = null;
  18. protected array $actionExtraFields = [];
  19. protected ?ObjectAction $objectAction = null;
  20. public function action(Approval $approval, int $status, string $comment = null, ?UploadedFile $uploadedFile = null): void
  21. {
  22. $this->approval = $approval;
  23. $this->actionExtraFields = [
  24. 'now' => $this->approval->node_level
  25. ];
  26. $fileInfo = $uploadedFile ? $this->chunkUploadFileByCompany($uploadedFile, FileObjectType::ACTION->value) : [];
  27. match($status) {
  28. 1 => $this->approved(),
  29. default => $this->rejected(),
  30. };
  31. $this->actionExtraFields['approval_mode'] = $this->approval->approval_mode;
  32. $action = $this->triggerAction($comment);
  33. $this->changeApprovalObjectStatus();
  34. $this->changeApproval();
  35. $this->fileToDatabase($fileInfo, $action->id);
  36. }
  37. protected function changeApproval(): void
  38. {
  39. $actionUsers = array_unique(array_filter([Auth::id(), ...explode(',', $this->approval->action_users)]));
  40. $this->approval->last_action_user_id = Auth::id();
  41. $this->approval->action_users = sprintf(",%s,", implode(",", $actionUsers));
  42. $this->approval->save();
  43. }
  44. protected function changeApprovalObjectStatus(): void
  45. {
  46. $approvalType = ApprovalObjectType::from($this->approval->object_type);
  47. $object = $approvalType
  48. ->modelBuilder()
  49. ->findOrFail($this->approval->object_id);
  50. if ($approvalType == ApprovalObjectType::CONTAINER_FILE) {
  51. File::query()->whereIn("id", $this->approval->sub_object_ids)->update([
  52. 'approval_status' => $this->approval->status
  53. ]);
  54. } else {
  55. $object->approval_status = $this->approval->status;
  56. $object->save();
  57. }
  58. }
  59. protected function triggerAction (string $comment = null)
  60. {
  61. return ActionRepository::createByApproval(
  62. $this->approval,
  63. $this->objectAction,
  64. $comment,
  65. extraFields: $this->actionExtraFields
  66. );
  67. }
  68. protected function approved(): void
  69. {
  70. $approvalFlowNodes = $this->approval->approvalFlow?->nodes;
  71. $nextNodeIndex = $this->approval->node_level + 1;
  72. $nextNode = $approvalFlowNodes[$nextNodeIndex] ?? [];
  73. $approvalObjectUsers = array_values(array_filter(explode(",", $this->approval->users), function($value) {
  74. return $value != Auth::id() && $value;
  75. }));
  76. switch (ApprovalMode::tryFrom($this->approval->approval_mode)) {
  77. case ApprovalMode::ALTERNATIVE_APPROVAL:
  78. if (! $nextNode) {
  79. $this->approvedHandle();
  80. } else {
  81. $this->approvedToNextNodeHandle($nextNodeIndex, $nextNode);
  82. }
  83. break;
  84. case ApprovalMode::COUNTERSIGNATURE:
  85. case ApprovalMode::SEQUENTIAL_APPROVAL:
  86. if (count($approvalObjectUsers) > 0 ) {
  87. $this->approvedWaitOthers($approvalObjectUsers);
  88. } elseif (! $nextNode) {
  89. $this->approvedHandle();
  90. } else {
  91. $this->approvedToNextNodeHandle($nextNodeIndex, $nextNode);
  92. }
  93. break;
  94. }
  95. }
  96. protected function approvedWaitOthers(array $approvalObjectUsers)
  97. {
  98. $this->approval->users = sprintf(",%s,", implode(',', $approvalObjectUsers));
  99. $this->objectAction = ObjectAction::APPROVED_WAIT_OTHERS;
  100. if ($this->approval->approval_mode == ApprovalMode::SEQUENTIAL_APPROVAL->value) {
  101. $this->actionExtraFields['next_sequential_user'] = $approvalObjectUsers[0];
  102. }
  103. }
  104. protected function cleanApprovalFields()
  105. {
  106. $this->approval->node_level = null;
  107. $this->approval->users = null;
  108. $this->approval->approval_mode = null;
  109. }
  110. protected function approvedHandle()
  111. {
  112. $this->approval->status = ObjectApprovalStatus::APPROVED->value;
  113. $this->cleanApprovalFields();
  114. $this->objectAction = ObjectAction::APPROVAL_APPROVED;
  115. }
  116. protected function approvedToNextNodeHandle(int $nextNodeIndex, array $nextNode)
  117. {
  118. $this->actionExtraFields['next'] = $nextNodeIndex;
  119. $this->approval->node_level = $nextNodeIndex;
  120. $this->approval->users = sprintf(",%s,", implode(',', $nextNode['approval_users']));
  121. $this->approval->approval_mode = $nextNode['approval_mode'];
  122. $this->objectAction = ObjectAction::APPROVED_TO_NEXT_NODE;
  123. if ($this->approval->approval_mode == ApprovalMode::SEQUENTIAL_APPROVAL->value) {
  124. $this->actionExtraFields['next_sequential_user'] = $nextNode['approval_users'][0];
  125. }
  126. }
  127. protected function rejected(): void
  128. {
  129. $this->approval->status = ObjectApprovalStatus::REJECTED->value;
  130. $this->cleanApprovalFields();
  131. $this->objectAction = ObjectAction::APPROVAL_REJECTED;
  132. }
  133. }