Skip to content

Commit 3b5b24e

Browse files
OHRM5X-2144: Develop leave - employee leave balance API (orangehrm#1666)
* OHRM5X-2142: Fix installer - failure when logging migration info * OHRM5X-2131: Fix leave - showing entitlements for deleted leave types also * OHRM5X-2128: Fix getting all leave entitlements when empNumber is an empty string * OHRM5X-2128: Fix int casting issue when passing an empty string
1 parent 7b486ef commit 3b5b24e

22 files changed

+401
-37
lines changed

installer/Migration/V5_4_0/Migration.php

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
2323
use Doctrine\DBAL\Schema\Index;
24+
use Doctrine\DBAL\Types\Type;
2425
use Doctrine\DBAL\Types\Types;
2526
use OrangeHRM\Installer\Util\V1\AbstractMigration;
2627

@@ -93,6 +94,11 @@ public function up(): void
9394
$this->modifyDefaultPasswordEnforcement();
9495

9596
$this->createOAuth2Tables();
97+
98+
// https://github.com/orangehrm/orangehrm/issues/1622
99+
$this->getSchemaHelper()->addOrChangeColumns('ohrm_migration_log', [
100+
'php_version' => ['Type' => Type::getType(Types::STRING), 'Length' => 255],
101+
]);
96102
}
97103

98104
/**

installer/Migration/V5_4_0/permission/api.yaml

+13
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,16 @@ apiv2_pim_my_info:
1414
permissions:
1515
- { role: Admin, permission: { read: true, create: false, update: false, delete: false } }
1616
- { role: ESS, permission: { read: true, create: false, update: false, delete: false } }
17+
18+
apiv2_leave_employee_leave_balances:
19+
description: "Leave - Employee Leave Balances"
20+
api: OrangeHRM\Leave\Api\EmployeeLeaveBalanceAPI
21+
module: leave
22+
allowed:
23+
read: true
24+
create: false
25+
update: false
26+
delete: false
27+
permissions:
28+
- { role: Admin, permission: { read: true, create: false, update: false, delete: false } }
29+
- { role: ESS, permission: { read: true, create: false, update: false, delete: false } }

installer/Util/MigrationHelper.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function logMigrationStarted(string $version): int
6969
->addColumn('id', Types::INTEGER, ['Autoincrement' => true])
7070
->addColumn('version', Types::STRING, ['Length' => 10])
7171
->addColumn('db_version', Types::STRING, ['Length' => 255])
72-
->addColumn('php_version', Types::STRING, ['Length' => 10])
72+
->addColumn('php_version', Types::STRING, ['Length' => 255])
7373
->addColumn('started_at', Types::DATETIME_MUTABLE)
7474
->addColumn('finished_at', Types::DATETIME_MUTABLE, ['Notnull' => false, 'Default' => null])
7575
->setPrimaryKey(['id'])
@@ -86,7 +86,7 @@ public function logMigrationStarted(string $version): int
8686
->setValue('started_at', ':startedAt')
8787
->setParameter('migrationVersion', $version)
8888
->setParameter('databaseVersion', substr($systemCheck->getMysqlServerVersion(), 0, 255))
89-
->setParameter('phpVersion', $systemCheck->getPhpVersion())
89+
->setParameter('phpVersion', substr($systemCheck->getPhpVersion(), 0, 255))
9090
->setParameter(
9191
'startedAt',
9292
(new DateTime())->setTimezone(new DateTimeZone(DateTimeHelperService::TIMEZONE_UTC)),

src/plugins/orangehrmCorePlugin/Api/V2/RequestParams.php

+10-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121

2222
use DateTime;
2323
use DateTimeZone;
24+
use InvalidArgumentException;
2425
use OpenApi\Annotations as OA;
26+
use OrangeHRM\Core\Api\V2\Exception\InvalidParamException;
2527
use OrangeHRM\Core\Dto\Base64Attachment;
2628

2729
class RequestParams
@@ -94,7 +96,13 @@ public function getStringOrNull(
9496
*/
9597
public function getInt(string $type, string $key, int $default = 0): int
9698
{
97-
return $this->$type->getInt($key, $default);
99+
$param = $this->$type->get($key, $default);
100+
if ($this->isEmptyString($param)) {
101+
throw new InvalidParamException([
102+
$key => new InvalidArgumentException("Parameter `$key` should not be an empty string")
103+
]);
104+
}
105+
return (int) $param;
98106
}
99107

100108
/**
@@ -306,6 +314,6 @@ public function has(string $type, string $key): bool
306314
*/
307315
private function isEmptyString($param): bool
308316
{
309-
return is_string($param) && empty($param);
317+
return is_string($param) && trim($param) === '';
310318
}
311319
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
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+
20+
namespace OrangeHRM\Leave\Api;
21+
22+
use OrangeHRM\Core\Api\CommonParams;
23+
use OrangeHRM\Core\Api\V2\CollectionEndpoint;
24+
use OrangeHRM\Core\Api\V2\Endpoint;
25+
use OrangeHRM\Core\Api\V2\EndpointCollectionResult;
26+
use OrangeHRM\Core\Api\V2\EndpointResult;
27+
use OrangeHRM\Core\Api\V2\Model\ArrayModel;
28+
use OrangeHRM\Core\Api\V2\ParameterBag;
29+
use OrangeHRM\Core\Api\V2\RequestParams;
30+
use OrangeHRM\Core\Api\V2\Validator\ParamRule;
31+
use OrangeHRM\Core\Api\V2\Validator\ParamRuleCollection;
32+
use OrangeHRM\Core\Api\V2\Validator\Rule;
33+
use OrangeHRM\Core\Api\V2\Validator\Rules;
34+
use OrangeHRM\Core\Traits\Auth\AuthUserTrait;
35+
use OrangeHRM\Leave\Dto\LeaveTypeSearchFilterParams;
36+
use OrangeHRM\Leave\Entitlement\LeaveBalance;
37+
use OrangeHRM\Leave\Traits\Service\LeaveEntitlementServiceTrait;
38+
use OrangeHRM\Leave\Traits\Service\LeavePeriodServiceTrait;
39+
use OrangeHRM\Leave\Traits\Service\LeaveRequestServiceTrait;
40+
use OrangeHRM\Leave\Traits\Service\LeaveTypeServiceTrait;
41+
42+
class EmployeeLeaveBalanceAPI extends Endpoint implements CollectionEndpoint
43+
{
44+
use LeaveEntitlementServiceTrait;
45+
use LeaveRequestServiceTrait;
46+
use LeavePeriodServiceTrait;
47+
use LeaveTypeServiceTrait;
48+
use AuthUserTrait;
49+
50+
/**
51+
* @inheritDoc
52+
*/
53+
public function getAll(): EndpointResult
54+
{
55+
$empNumber = $this->getRequestParams()->getInt(
56+
RequestParams::PARAM_TYPE_QUERY,
57+
CommonParams::PARAMETER_EMP_NUMBER,
58+
$this->getAuthUser()->getEmpNumber()
59+
);
60+
61+
if (!$this->getRequestParams()->has(RequestParams::PARAM_TYPE_QUERY, LeaveCommonParams::PARAMETER_FROM_DATE) ||
62+
!$this->getRequestParams()->has(RequestParams::PARAM_TYPE_QUERY, LeaveCommonParams::PARAMETER_TO_DATE)) {
63+
$currentLeavePeriod = $this->getLeavePeriodService()->getCurrentLeavePeriod();
64+
$fromDate = $this->getRequestParams()->getDateTime(
65+
RequestParams::PARAM_TYPE_QUERY,
66+
LeaveCommonParams::PARAMETER_FROM_DATE,
67+
null,
68+
$currentLeavePeriod->getStartDate()
69+
);
70+
$toDate = $this->getRequestParams()->getDateTime(
71+
RequestParams::PARAM_TYPE_QUERY,
72+
LeaveCommonParams::PARAMETER_TO_DATE,
73+
null,
74+
$currentLeavePeriod->getEndDate()
75+
);
76+
} else {
77+
$fromDate = $this->getRequestParams()->getDateTime(
78+
RequestParams::PARAM_TYPE_QUERY,
79+
LeaveCommonParams::PARAMETER_FROM_DATE,
80+
);
81+
$toDate = $this->getRequestParams()->getDateTime(
82+
RequestParams::PARAM_TYPE_QUERY,
83+
LeaveCommonParams::PARAMETER_TO_DATE,
84+
);
85+
}
86+
87+
$leaveTypeSearchFilterParams = new LeaveTypeSearchFilterParams();
88+
$this->setSortingAndPaginationParams($leaveTypeSearchFilterParams);
89+
90+
$leaveTypes = $this->getLeaveTypeService()
91+
->getLeaveTypeDao()
92+
->searchLeaveType($leaveTypeSearchFilterParams);
93+
$leaveTypeCount = $this->getLeaveTypeService()->getLeaveTypeDao()
94+
->getSearchLeaveTypesCount($leaveTypeSearchFilterParams);
95+
96+
$leaveTypeIds = array_unique(
97+
array_merge(
98+
$this->getLeaveRequestService()
99+
->getLeaveRequestDao()
100+
->getUsedLeaveTypeIdsByEmployee($empNumber),
101+
$this->getLeaveEntitlementService()
102+
->getLeaveEntitlementDao()
103+
->getLeaveTypeIdsForEntitlementsByEmployee($empNumber)
104+
)
105+
);
106+
107+
$leaveTypesResult = [];
108+
foreach ($leaveTypes as $leaveType) {
109+
$balanceArray = null;
110+
$balance = null;
111+
if (in_array($leaveType->getId(), $leaveTypeIds)) {
112+
$balance = $this->getLeaveEntitlementService()
113+
->getLeaveBalance($empNumber, $leaveType->getId(), $fromDate, $toDate);
114+
$balanceArray = [
115+
'entitled' => $balance->getEntitled(),
116+
'used' => $balance->getUsed(),
117+
'scheduled' => $balance->getScheduled(),
118+
'pending' => $balance->getPending(),
119+
'taken' => $balance->getTaken(),
120+
'balance' => $balance->getBalance(),
121+
];
122+
}
123+
124+
$leaveTypeResult = [
125+
'leaveType' => [
126+
'id' => $leaveType->getId(),
127+
'name' => $leaveType->getName(),
128+
'deleted' => $leaveType->isDeleted(),
129+
],
130+
'usageBreakdown' => $balanceArray,
131+
'fromDate' => $balance instanceof LeaveBalance ? $balance->getYmdAsAtDate() : null,
132+
'toDate' => $balance instanceof LeaveBalance ? $balance->getYmdEndDate() : null,
133+
];
134+
$leaveTypesResult[] = $leaveTypeResult;
135+
}
136+
return new EndpointCollectionResult(
137+
ArrayModel::class,
138+
$leaveTypesResult,
139+
new ParameterBag([CommonParams::PARAMETER_TOTAL => $leaveTypeCount])
140+
);
141+
}
142+
143+
/**
144+
* @inheritDoc
145+
*/
146+
public function getValidationRuleForGetAll(): ParamRuleCollection
147+
{
148+
return new ParamRuleCollection(
149+
$this->getValidationDecorator()->notRequiredParamRule(
150+
new ParamRule(
151+
CommonParams::PARAMETER_EMP_NUMBER,
152+
new Rule(Rules::POSITIVE),
153+
new Rule(Rules::IN_ACCESSIBLE_EMP_NUMBERS)
154+
)
155+
),
156+
...$this->getSortingAndPaginationParamsRules(LeaveTypeSearchFilterParams::ALLOWED_SORT_FIELDS),
157+
);
158+
}
159+
160+
/**
161+
* @inheritDoc
162+
*/
163+
public function create(): EndpointResult
164+
{
165+
throw $this->getNotImplementedException();
166+
}
167+
168+
/**
169+
* @inheritDoc
170+
*/
171+
public function getValidationRuleForCreate(): ParamRuleCollection
172+
{
173+
throw $this->getNotImplementedException();
174+
}
175+
176+
/**
177+
* @inheritDoc
178+
*/
179+
public function delete(): EndpointResult
180+
{
181+
throw $this->getNotImplementedException();
182+
}
183+
184+
/**
185+
* @inheritDoc
186+
*/
187+
public function getValidationRuleForDelete(): ParamRuleCollection
188+
{
189+
throw $this->getNotImplementedException();
190+
}
191+
}

src/plugins/orangehrmLeavePlugin/Api/LeaveEntitlementAPI.php

+14
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class LeaveEntitlementAPI extends Endpoint implements CrudEndpoint
5959
public const PARAMETER_LOCATION_ID = 'locationId';
6060
public const PARAMETER_SUBUNIT_ID = 'subunitId';
6161
public const FILTER_MODEL = 'model';
62+
public const FILTER_LEAVE_TYPE_DELETED = 'leaveTypeDeleted';
6263

6364
public const META_PARAMETER_SUM = 'sum';
6465
public const META_PARAMETER_COUNT = 'count';
@@ -181,6 +182,12 @@ private function getIdParamRule(): ParamRule
181182
* @OA\Schema(type="string")
182183
* ),
183184
* @OA\Parameter(
185+
* name="leaveTypeDeleted",
186+
* in="query",
187+
* required=false,
188+
* @OA\Schema(type="boolean")
189+
* ),
190+
* @OA\Parameter(
184191
* name="sortField",
185192
* in="query",
186193
* required=false,
@@ -256,6 +263,12 @@ public function getAll(): EndpointResult
256263
$entitlementSearchFilterParams->setLeaveTypeId($leaveTypeId);
257264
$entitlementSearchFilterParams->setFromDate($fromDate);
258265
$entitlementSearchFilterParams->setToDate($toDate);
266+
$entitlementSearchFilterParams->setLeaveTypeDeleted(
267+
$this->getRequestParams()->getBooleanOrNull(
268+
RequestParams::PARAM_TYPE_QUERY,
269+
self::FILTER_LEAVE_TYPE_DELETED
270+
)
271+
);
259272
$this->setSortingAndPaginationParams($entitlementSearchFilterParams);
260273

261274
$entitlements = $this->getLeaveEntitlementService()
@@ -323,6 +336,7 @@ public function getValidationRuleForGetAll(): ParamRuleCollection
323336
$this->getValidationDecorator()->notRequiredParamRule($fromDateRule),
324337
$this->getValidationDecorator()->notRequiredParamRule($toDateRule),
325338
$this->getModelClassParamRule(),
339+
new ParamRule(self::FILTER_LEAVE_TYPE_DELETED, new Rule(Rules::BOOL_VAL)),
326340
...$this->getSortingAndPaginationParamsRules(LeaveEntitlementSearchFilterParams::ALLOWED_SORT_FIELDS)
327341
);
328342
}

src/plugins/orangehrmLeavePlugin/Api/Model/LeaveCommentModel.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public function __construct(LeaveComment $leaveComment)
4242
['getCreatedByEmployee','getMiddleName'],
4343
['getCreatedByEmployee','getEmployeeId'],
4444
['getCreatedByEmployee','getEmployeeTerminationRecord', 'getId'],
45+
['getCreatedByEmployee','getEmployeeTerminationRecord', 'getId'],
4546
'comment',
4647
]
4748
);
@@ -56,7 +57,8 @@ public function __construct(LeaveComment $leaveComment)
5657
['createdByEmployee','firstName'],
5758
['createdByEmployee','middleName'],
5859
['createdByEmployee','employeeId'],
59-
['createdByEmployee','employeeTerminationRecord','terminationId'],
60+
['createdByEmployee','employeeTerminationRecord','terminationId'], // TODO:: remove
61+
['createdByEmployee','terminationId'],
6062
'comment',
6163
]
6264
);

src/plugins/orangehrmLeavePlugin/Api/Model/LeaveEntitlementSummaryModel.php

+8-8
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@
2929
* schema="Leave-LeaveEntitlementSummaryModel",
3030
* type="object",
3131
* @OA\Property(property="id", type="integer"),
32-
* @OA\Property(property="entitlement", type="number"),
33-
* @OA\Property(property="daysUsed", type="number"),
3432
* @OA\Property(
3533
* property="usageBreakdown",
3634
* type="object",
35+
* @OA\Property(property="entitlement", type="number"),
36+
* @OA\Property(property="used", type="number"),
3737
* @OA\Property(property="scheduled", type="number"),
3838
* @OA\Property(property="pending", type="number"),
3939
* @OA\Property(property="taken", type="number"),
@@ -46,8 +46,8 @@
4646
* @OA\Property(property="name", type="string"),
4747
* @OA\Property(property="deleted", type="boolean")
4848
* ),
49-
* @OA\Property(property="fromDate", type="number"),
50-
* @OA\Property(property="toDate", type="number"),
49+
* @OA\Property(property="fromDate", type="string"),
50+
* @OA\Property(property="toDate", type="string"),
5151
* )
5252
*/
5353
class LeaveEntitlementSummaryModel implements Normalizable
@@ -76,9 +76,9 @@ public function toArray(): array
7676

7777
return [
7878
'id' => $entity->getId(),
79-
'entitlement' => $entity->getNoOfDays(),
80-
'daysUsed' => $entity->getDaysUsed(),
8179
'usageBreakdown' => [
80+
'entitlement' => $balance->getEntitled(),
81+
'used' => $balance->getUsed(),
8282
'scheduled' => $balance->getScheduled(),
8383
'pending' => $balance->getPending(),
8484
'taken' => $balance->getTaken(),
@@ -89,8 +89,8 @@ public function toArray(): array
8989
'name' => $entity->getLeaveType()->getName(),
9090
'deleted' => $entity->getLeaveType()->isDeleted(),
9191
],
92-
'fromDate' => $entity->getDecorator()->getFromDate(),
93-
'toDate' => $entity->getDecorator()->getToDate(),
92+
'fromDate' => $balance->getYmdAsAtDate(),
93+
'toDate' => $balance->getYmdEndDate(),
9494
];
9595
}
9696
}

0 commit comments

Comments
 (0)