dfprocessajaxhandler.class.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. <?php
  2. dol_include_once('/documentfollower/class/documentfollowerprocess.class.php');
  3. dol_include_once('/documentfollower/class/dfprocessuserhandler.class.php');
  4. dol_include_once('/documentfollower/class/documentfollowerprocessstate.class.php');
  5. dol_include_once('/documentfollower/class/dfprocesslevelemailsender.class.php');
  6. dol_include_once('/documentfollower/class/dfprocesscloseemail.class.php');
  7. dol_include_once('/documentfollower/class/dfprocessloghandler.class.php');
  8. /**
  9. *
  10. */
  11. class DfProcessAjaxHandler
  12. {
  13. const OPERATION_ASSIGN = 1;
  14. const OPERATION_SIGN = 2;
  15. const OPERATION_RESTORE = 3;
  16. public $db;
  17. public $errors;
  18. public $user;
  19. public $process;
  20. public $operation;
  21. public $userLevel;
  22. public $level;
  23. public $description;
  24. /**
  25. *
  26. */
  27. public function __construct(DocumentFollowerProcess $process, int $operation, int $level= null, string $description = null)
  28. {
  29. global $db, $user;
  30. $this->db = $db;
  31. $this->user = $user;
  32. $this->process = $process;
  33. $this->operation = $operation;
  34. $this->level = $level;
  35. $this->description = $description;
  36. }
  37. /**
  38. *
  39. */
  40. public function process(): bool
  41. {
  42. $processed = false;
  43. $this->validateProcess();
  44. $this->validateUser();
  45. $this->validateOperation();
  46. if ($this->operation === self::OPERATION_ASSIGN) {
  47. // not send email
  48. $this->look();
  49. $processed = true;
  50. } else if ($this->operation === self::OPERATION_SIGN) {
  51. $this->sign();
  52. $processed = true;
  53. } else if ($this->operation === self::OPERATION_RESTORE) {
  54. // send email to user(s)
  55. $this->returnTo();
  56. $processed = true;
  57. }
  58. return $processed;
  59. }
  60. /**
  61. *
  62. */
  63. public function saveState(): int
  64. {
  65. $state = new DocumentFollowerProcessState($this->db);
  66. $state->ref = bin2hex(random_bytes(5));
  67. $state->status = $this->operation;
  68. $state->is_active = 1; //($this->level) ? 0 : 1;
  69. $state->fk_process = $this->process->id;
  70. $state->return_level = $this->level;
  71. $state->description = $this->description;
  72. $id = $state->create($this->user);
  73. if ($id < 1) {
  74. throw new \Exception('Save failure');
  75. }
  76. return $id;
  77. }
  78. /**
  79. *
  80. */
  81. public function getProcessLastLevel(): int
  82. {
  83. return (new DfProcessUserHandler($this->process->id))->getLastLevel();
  84. }
  85. /**
  86. *
  87. */
  88. public function checkEverybodySignedOnTheCurrentLevel(): bool
  89. {
  90. return (new DfProcessHandler)->checkEverybodySignedTheLevel($this->process, $this->userLevel);
  91. }
  92. /**
  93. *
  94. */
  95. private function validateUser(): void
  96. {
  97. $userHandler = new DfProcessUserHandler($this->process->id);
  98. $isAssigned = $userHandler->isUserAssignedToProcess($this->user->id);
  99. if ($isAssigned) {
  100. $this->userLevel = $userHandler->level;
  101. // check
  102. $userIds = $userHandler->getLevelMembers($this->process->id, $this->userLevel);
  103. if (in_array($this->user->id, $userIds)) {
  104. // ...
  105. } else {
  106. throw new \Exception('User not assigned to process on this level');
  107. }
  108. } else {
  109. throw new \Exception('User not assigned to process');
  110. }
  111. }
  112. /**
  113. *
  114. */
  115. private function validateOperation(): void
  116. {
  117. $constants = (new ReflectionClass(__CLASS__))->getConstants();
  118. if (!in_array($this->operation, $constants)) {
  119. throw new \Exception('Invalid operation!');
  120. }
  121. }
  122. /**
  123. *
  124. */
  125. private function validateProcess(): void
  126. {
  127. if (intval($this->process->status) !== DocumentFollowerProcess::STATUS_VALIDATED
  128. || $this->process->process_status !== 1) {
  129. throw new \Exception('Not active process!');
  130. }
  131. }
  132. /**
  133. *
  134. */
  135. public function look(): bool
  136. {
  137. $this->saveState();
  138. return true;
  139. }
  140. /**
  141. *
  142. */
  143. public function sign(): bool
  144. {
  145. // save signed state
  146. $this->saveState();
  147. // send email to next step(s), if everybody sign on this level
  148. if ($this->checkEverybodySignedOnTheCurrentLevel()) {
  149. // is it the last level
  150. if ($this->userLevel == $this->getProcessLastLevel()) {
  151. // close the process
  152. $this->closeProcess();
  153. // send email to process creator
  154. (new DfProcessCloseEmail)->send($this->process);
  155. } else {
  156. // send email to next level user(s)
  157. $nextLevel = $this->userLevel + 1;
  158. (new DfProcessLevelEmailSender($this->process, $nextLevel))->sendEmailToLevelMembers();
  159. }
  160. }
  161. return true;
  162. }
  163. /**
  164. *
  165. */
  166. public function returnTo(): bool
  167. {
  168. $this->saveState();
  169. $levels = (new DocumentFollowerProcessUser($this->db))->fetchAll('ASC', 'level', 0, 0, [
  170. 'fk_process' => $this->process->id,
  171. 'customsql' => 'level >= '.$this->level
  172. ]);
  173. if (is_array($levels)) {
  174. foreach ($levels as $level) {
  175. if ($level->fk_user) {
  176. $this->inactivateUserState($level->fk_user);
  177. } elseif ($level->fk_usergroup) {
  178. $this->inactivateGroupState($level->fk_usergroup);
  179. }
  180. }
  181. }
  182. (new DfProcessLevelEmailSender($this->process, $this->level))->sendEmailToLevelMembers();
  183. return true;
  184. }
  185. /**
  186. *
  187. */
  188. private function inactivateUserState(int $userId): void
  189. {
  190. $states = (new DocumentFollowerProcessState($this->db))->fetchAll('', '', 0, 0, [
  191. 'fk_process' => $this->process->id,
  192. 'is_active' => 1,
  193. 'fk_user_creat' => $userId,
  194. 'customsql' => 'status != 3'
  195. ]);
  196. if (is_array($states)) {
  197. $state = reset($states);
  198. $state->is_active = 0;
  199. $state->status = 3;
  200. $state->update($this->user);
  201. }
  202. }
  203. /**
  204. *
  205. */
  206. private function inactivateGroupState(int $userGroupId): void
  207. {
  208. $group = (new UserGroup($this->db));
  209. $group->fetch($userGroupId, '', false);
  210. $userIds = array_keys($group->listUsersForGroup());
  211. $states = (new DocumentFollowerProcessState($this->db))->fetchAll('', '', 0, 0, [
  212. 'fk_process' => $this->process->id,
  213. 'is_active' => 1,
  214. 'customsql' => 'fk_user IN ('.implode(',', $userIds).') AND status != 3'
  215. ]);
  216. if (is_array($states)) {
  217. foreach ($states as $state) {
  218. $state->is_active = 0;
  219. $state->status = '3';
  220. $state->update($this->user);
  221. }
  222. }
  223. }
  224. /**
  225. *
  226. */
  227. private function closeProcess(): void
  228. {
  229. $this->process->process_status = 3;
  230. if ($this->process->update($this->user) < 0) {
  231. throw new \Exception("The process cannot be closed (ID: {$this->process->id})");
  232. }
  233. }
  234. }