1<?php
2/**
3 * OrangeHRM is a comprehensive Human Resource Management (HRM) System that captures
4 * all the essential functionalities required for any enterprise.
5 * Copyright (C) 2006 OrangeHRM Inc., http://www.orangehrm.com
6 *
7 * OrangeHRM is free software; you can redistribute it and/or modify it under the terms of
8 * the GNU General Public License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * OrangeHRM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along with this program;
16 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA  02110-1301, USA
18 */
19
20namespace Orangehrm\Rest\Api\User\Leave;
21
22use AuthorizeService;
23use BasicUserRoleManager;
24use EmployeeService;
25use HolidayService;
26use LeavePeriodService;
27use LeaveRequestService;
28use LeaveTypeService;
29use Orangehrm\Rest\Api\EndPoint;
30use Orangehrm\Rest\Api\Exception\BadRequestException;
31use Orangehrm\Rest\Api\Exception\InvalidParamException;
32use Orangehrm\Rest\Api\Exception\RecordNotFoundException;
33use Orangehrm\Rest\Api\User\Leave\Model\LeaveTypeModel;
34use Orangehrm\Rest\Http\Response;
35use sfContext;
36use UserRoleManagerFactory;
37use WorkScheduleService;
38use WorkWeek;
39use WorkWeekService;
40
41class LeaveConfigAPI extends EndPoint
42{
43    const PARAMETER_FROM_DATE = 'fromDate';
44    const PARAMETER_TO_DATE = 'toDate';
45    const PARAMETER_EMP_NUMBER = 'empNumber';
46    const PARAMETER_LEAVE_TYPES_ALL = 'all';
47
48    protected $workWeekService = null;
49    protected $leavePeriodService = null;
50    protected $holidayService = null;
51    protected $workScheduleService = null;
52    protected $leaveRequestService = null;
53    protected $leaveTypeService = null;
54    protected $employeeService = null;
55
56    /**
57     * @return WorkWeekService
58     */
59    public function getWorkWeekService(): WorkWeekService
60    {
61        if (is_null($this->workWeekService)) {
62            $this->workWeekService = new WorkWeekService();
63        }
64        return $this->workWeekService;
65    }
66
67    /**
68     * @param WorkWeekService $service
69     */
70    public function setWorkWeekService(WorkWeekService $service)
71    {
72        $this->workWeekService = $service;
73    }
74
75    /**
76     * @return LeavePeriodService
77     */
78    public function getLeavePeriodService(): LeavePeriodService
79    {
80        if (is_null($this->leavePeriodService)) {
81            $this->leavePeriodService = new LeavePeriodService();
82        }
83        return $this->leavePeriodService;
84    }
85
86    /**
87     * @param LeavePeriodService $leavePeriodService
88     */
89    public function setLeavePeriodService(LeavePeriodService $leavePeriodService)
90    {
91        $this->leavePeriodService = $leavePeriodService;
92    }
93
94    /**
95     * @return HolidayService
96     */
97    public function getHolidayService(): HolidayService
98    {
99        if (is_null($this->holidayService)) {
100            $this->holidayService = new HolidayService();
101        }
102        return $this->holidayService;
103    }
104
105    /**
106     * @param HolidayService $holidayService
107     */
108    public function setHolidayService(HolidayService $holidayService)
109    {
110        $this->holidayService = $holidayService;
111    }
112
113    /**
114     * @return WorkScheduleService
115     */
116    public function getWorkScheduleService(): WorkScheduleService
117    {
118        if (is_null($this->workScheduleService)) {
119            $this->workScheduleService = new WorkScheduleService();
120        }
121        return $this->workScheduleService;
122    }
123
124    /**
125     *
126     * @param WorkScheduleService $service
127     */
128    public function setWorkScheduleService(WorkScheduleService $service)
129    {
130        $this->workScheduleService = $service;
131    }
132
133    /**
134     * @return LeaveRequestService|null
135     */
136    public function getLeaveRequestService(): LeaveRequestService
137    {
138        if (is_null($this->leaveRequestService)) {
139            $this->leaveRequestService = new LeaveRequestService();
140        }
141        return $this->leaveRequestService;
142    }
143
144    /**
145     * @param LeaveRequestService $leaveRequestService
146     */
147    public function setLeaveRequestService(LeaveRequestService $leaveRequestService)
148    {
149        $this->leaveRequestService = $leaveRequestService;
150    }
151
152    /**
153     * @return LeaveTypeService
154     */
155    protected function getLeaveTypeService(): LeaveTypeService
156    {
157        if (is_null($this->leaveTypeService)) {
158            $this->leaveTypeService = new LeaveTypeService();
159        }
160        return $this->leaveTypeService;
161    }
162
163    /**
164     * @param LeaveTypeService $leaveTypeService
165     */
166    protected function setLeaveTypeService(LeaveTypeService $leaveTypeService)
167    {
168        $this->leaveTypeService = $leaveTypeService;
169    }
170
171    /**
172     * @return EmployeeService
173     */
174    public function getEmployeeService(): EmployeeService
175    {
176        if (is_null($this->employeeService)) {
177            $this->employeeService = new EmployeeService();
178        }
179        return $this->employeeService;
180    }
181
182    /**
183     * @param EmployeeService $employeeService
184     */
185    public function setEmployeeService(EmployeeService $employeeService)
186    {
187        $this->employeeService = $employeeService;
188    }
189
190    protected function getUserAttribute(string $name)
191    {
192        return sfContext::getInstance()->getUser()->getAttribute($name);
193    }
194
195    public function getEmployeeWorkShift(): Response
196    {
197        $params = $this->filterEmployeeWorkShift();
198        $workSchedule = $this->getWorkScheduleService()->getWorkSchedule($params[self::PARAMETER_EMP_NUMBER]);
199        $workShiftLength = $workSchedule->getWorkShiftLength();
200        $startEndTime = $workSchedule->getWorkShiftStartEndTime();
201        $result = [
202            'workShift' => is_string($workShiftLength) ? $workShiftLength : number_format(
203                (float)$workShiftLength,
204                2,
205                '.',
206                ''
207            ),
208            'startTime' => date('H:i', strtotime($startEndTime['start_time'])),
209            'endTime' => date('H:i', strtotime($startEndTime['end_time']))
210        ];
211        return new Response($result);
212    }
213
214    public function getEmployeeWorkWeek(): Response
215    {
216        $workWeek = $this->getWorkWeekService()->getWorkWeekOfOperationalCountry(null);
217        if ($workWeek instanceof WorkWeek) {
218            return new Response($workWeek->toArray());
219        }
220        throw new RecordNotFoundException('No Records Found');
221    }
222
223    public function getHolidays(): Response
224    {
225        $params = $this->filterHolidaysParameters();
226        $holidayList = $this->getHolidayService()->searchHolidays(
227            $params[self::PARAMETER_FROM_DATE],
228            $params[self::PARAMETER_TO_DATE]
229        );
230        $holidays = array_map(
231            function ($holiday) {
232                return $holiday->toArray();
233            },
234            $holidayList
235        );
236        return new Response($holidays);
237    }
238
239    public function getLeavePeriods(): Response
240    {
241        $leavePeriodList = $this->getLeavePeriodService()->getGeneratedLeavePeriodList();
242        $leavePeriods = [];
243        foreach ($leavePeriodList as $leavePeriod) {
244            $leavePeriods[] = [
245                'startDate' => $leavePeriod[0],
246                'endDate' => $leavePeriod[1],
247            ];
248        }
249        return new Response($leavePeriods);
250    }
251
252    public function getLeaveTypes(): Response
253    {
254        $params = $this->filterLeaveTypes();
255        $leaveTypeList = $this->getLeaveTypeService()->getLeaveTypeList();
256        if (count($leaveTypeList) === 0) {
257            throw new BadRequestException('No Leave Types Defined.');
258        }
259        if (!$params[self::PARAMETER_LEAVE_TYPES_ALL]) {
260            $empNumber = $this->getUserAttribute("auth.empNumber");
261            $employee = $this->getEmployeeService()->getEmployee($empNumber);
262            $leaveTypeList = $this->getLeaveRequestService()->getEmployeeAllowedToApplyLeaveTypes($employee);
263        }
264
265        $leaveTypes = [];
266        foreach ($leaveTypeList as $leaveType) {
267            $leaveTypeModel = new LeaveTypeModel($leaveType);
268            $leaveTypes[] = $leaveTypeModel->toArray();
269        }
270        return new Response($leaveTypes);
271    }
272
273    public function filterHolidaysParameters(): array
274    {
275        $params = [];
276        $fromDate = $this->getRequestParams()->getQueryParam(self::PARAMETER_FROM_DATE);
277        $toDate = $this->getRequestParams()->getQueryParam(self::PARAMETER_TO_DATE);
278
279        if (empty($fromDate) || empty($toDate)) {
280            $currentLeavePeriod = $this->getLeavePeriodService()->getCurrentLeavePeriodByDate(date('Y-m-d'));
281            if (empty($fromDate)) {
282                $fromDate = $currentLeavePeriod[0];
283            }
284            if (empty($toDate)) {
285                $toDate = $currentLeavePeriod[1];
286            }
287        }
288        if (strtotime($toDate) - strtotime($fromDate) < 0) {
289            throw new InvalidParamException('From date should be before to date');
290        }
291        $params[self::PARAMETER_FROM_DATE] = $fromDate;
292        $params[self::PARAMETER_TO_DATE] = $toDate;
293        return $params;
294    }
295
296    public function filterEmployeeWorkShift(): array
297    {
298        $params = [];
299        $empNumber = $this->getRequestParams()->getQueryParam(self::PARAMETER_EMP_NUMBER);
300        if (empty($empNumber)) {
301            $empNumber = $this->getUserAttribute("auth.empNumber");
302        } elseif (!(in_array(
303                $empNumber,
304                $this->getAccessibleEmpNumbers('assign_leave')
305            ) || $empNumber == $this->getUserAttribute("auth.empNumber"))) {
306            throw new BadRequestException('Access Denied');
307        }
308
309        $params[self::PARAMETER_EMP_NUMBER] = $empNumber;
310        return $params;
311    }
312
313    public function filterLeaveTypes(): array
314    {
315        $params = [];
316        $all = $this->getRequestParams()->getQueryParam(self::PARAMETER_LEAVE_TYPES_ALL, 'false');
317        if (!($all == 'true' || $all == 'false')) {
318            throw new InvalidParamException(sprintf("Invalid `%s` Value", self::PARAMETER_LEAVE_TYPES_ALL));
319        }
320        $all = $all == 'true';
321        if ($all) {
322            $isSupervisor = $this->getUserAttribute('auth.isSupervisor');
323            $isAdmin = $this->getUserAttribute('auth.isAdmin') == AuthorizeService::YES;
324            if (!($isSupervisor || $isAdmin)) {
325                throw new BadRequestException('Access Denied');
326            }
327        }
328        $params[self::PARAMETER_LEAVE_TYPES_ALL] = $all;
329        return $params;
330    }
331
332    public function getHolidaysValidationRules(): array
333    {
334        return [
335            self::PARAMETER_TO_DATE => ['Date' => ['Y-m-d']],
336            self::PARAMETER_FROM_DATE => ['Date' => ['Y-m-d']],
337        ];
338    }
339
340    protected function getAccessibleEmpNumbers(string $action): array
341    {
342        $properties = ["empNumber"];
343        $requiredPermissions = [BasicUserRoleManager::PERMISSION_TYPE_ACTION => [$action]];
344        $employeeList = UserRoleManagerFactory::getUserRoleManager()->getAccessibleEntityProperties(
345            'Employee',
346            $properties,
347            null,
348            null,
349            [],
350            [],
351            $requiredPermissions
352        );
353
354        return array_keys($employeeList);
355    }
356}
357