ActionService.php 4.5 KB

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