diff --git a/.vscode/settings.json b/.vscode/settings.json index 60392bf3..aff849d6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": true, + "source.organizeImports": false }, "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, diff --git a/CHANGELOG.md b/CHANGELOG.md index bd49fce6..f02d3cf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,160 +1,260 @@ -# [21.7.0](https://github.com/peerigon/clockodo/compare/v21.6.0...v21.7.0) (2023-08-09) +# [23.0.0](https://github.com/peerigon/clockodo/compare/v22.2.0...v23.0.0) (2023-11-21) + + +### Bug Fixes + +* Rename HolidaysQuota and HolidaysCarryover ([#145](https://github.com/peerigon/clockodo/issues/145)) ([16543bf](https://github.com/peerigon/clockodo/commit/16543bffc60339daf05f1ad1f46efd2a4ef30207)) + + +### BREAKING CHANGES + +* We've renamed `HolidayscarryRow` to `HolidaysCarryover` and `HolidaysquotaRow` to `HolidaysQuota` and adjusted all method names accordingly to make the naming more consistent. + +# [22.2.0](https://github.com/peerigon/clockodo/compare/v22.1.0...v22.2.0) (2023-11-06) ### Features -* expose nonbusiness group model ([eb4e568](https://github.com/peerigon/clockodo/commit/eb4e568dfa2aaec4401c8d8ef1a67f6bcfbe6ebb)) +* Use v3 API for services and lumpsum services ([#131](https://github.com/peerigon/clockodo/issues/131)) ([1a8ba9d](https://github.com/peerigon/clockodo/commit/1a8ba9d1fad6a6251a1116a39bfd1886a048bce1)) -# [21.6.0](https://github.com/peerigon/clockodo/compare/v21.5.1...v21.6.0) (2023-07-28) +# [22.1.0](https://github.com/peerigon/clockodo/compare/v22.0.0...v22.1.0) (2023-11-06) -### Bug Fixes +### Features -* make mocks more consistent ([1fd9177](https://github.com/peerigon/clockodo/commit/1fd91773ab079bcfaccb47361807bc9f169bcda0)) +* Add testData property to targethoursRow ([#140](https://github.com/peerigon/clockodo/issues/140)) ([9c2e511](https://github.com/peerigon/clockodo/commit/9c2e5119004eeb89c95b53e42815e95fbf5e071e)) +# [22.0.0](https://github.com/peerigon/clockodo/compare/v21.15.0...v22.0.0) (2023-10-24) ### Features -* add declined props ([1d80925](https://github.com/peerigon/clockodo/commit/1d80925c2c6de61c4fb4f8da65fb60f89068560a)) +- Replace deactivate... with delete... ([67e0b33](https://github.com/peerigon/clockodo/commit/67e0b336a342886c04df8a70636c020a58a02f28)) -## [21.5.1](https://github.com/peerigon/clockodo/compare/v21.5.0...v21.5.1) (2023-07-19) +### BREAKING CHANGES + +- There are no `deactivate...` methods anymore. In order to deactivate a customer, project, ..., you need to call `edit...` with `active: false`. + +# [21.15.0](https://github.com/peerigon/clockodo/compare/v21.14.0...v21.15.0) (2023-10-24) + +### Features + +- Add overtimecarry endpoint ([db9aca4](https://github.com/peerigon/clockodo/commit/db9aca46e6fec0366767e8c63d3d6509e11381d8)) +- added overtimecarry model and api request ([b062946](https://github.com/peerigon/clockodo/commit/b0629465e8213cd3e5ef8e6e29acf9fa6eb1bab2)) + +# [21.14.0](https://github.com/peerigon/clockodo/compare/v21.13.0...v21.14.0) (2023-10-24) + +### Features + +- Add holidaysquota and holidayscarry endpoints ([f342c2f](https://github.com/peerigon/clockodo/commit/f342c2fe9e6a2dbcb23ce0fb5181f3a5f9c26494)), closes [#31](https://github.com/peerigon/clockodo/issues/31) + +# [21.13.0](https://github.com/peerigon/clockodo/compare/v21.12.0...v21.13.0) (2023-10-16) + +### Features + +- expand workTimes model with new property ([828a6e7](https://github.com/peerigon/clockodo/commit/828a6e7ed0065c9195b8df260ccb97b07eb7509a)) + +# [21.12.0](https://github.com/peerigon/clockodo/compare/v21.11.0...v21.12.0) (2023-09-26) + +### Features + +- nonbusinessgroupsId is now optional for getNonbusinessDays ([fe6384a](https://github.com/peerigon/clockodo/commit/fe6384a93e528f3c8e18ff4acf529f1a109a8792)) +- nonbusinessgroupsId is now optional for the getNonbusinessDays API call ([cf98a8c](https://github.com/peerigon/clockodo/commit/cf98a8c4bf0ab099ac8840cb372aa24e01d79dd5)) + +# [21.11.0](https://github.com/peerigon/clockodo/compare/v21.10.4...v21.11.0) (2023-09-14) +### Features + +- Company expansion ([065fc38](https://github.com/peerigon/clockodo/commit/065fc3802bfcf2e46c7d2dccb15b1c1c54a41f87)) + +## [21.10.4](https://github.com/peerigon/clockodo/compare/v21.10.3...v21.10.4) (2023-09-13) ### Bug Fixes -* Incorrect absence and user types ([91a00b8](https://github.com/peerigon/clockodo/commit/91a00b89d6e18d6cbe3fbee8625a54e9c1223ae9)) +- Incorrect pagination types ([d5ddd74](https://github.com/peerigon/clockodo/commit/d5ddd745ecff9449e5415891931aa671b54c9d9c)) +- Incorrect pagination types ([412d610](https://github.com/peerigon/clockodo/commit/412d610e7c2dd3eab8d9a75ae2d92c0c2bc98314)) -# [21.5.0](https://github.com/peerigon/clockodo/compare/v21.4.0...v21.5.0) (2023-07-11) +## [21.10.3](https://github.com/peerigon/clockodo/compare/v21.10.2...v21.10.3) (2023-09-13) +### Bug Fixes + +- Incorrect AccessToCustomersProjects type ([a3c9574](https://github.com/peerigon/clockodo/commit/a3c957460e950be661a08a1987f4a75c07b7bebe)) +- make top-level props accept false ([3c31fa3](https://github.com/peerigon/clockodo/commit/3c31fa3b86b1aa11a372a9b51d8467872791325a)) + +## [21.10.2](https://github.com/peerigon/clockodo/compare/v21.10.1...v21.10.2) (2023-09-13) ### Bug Fixes -* Remove status from required properties of addWorkTimesChangeRequest() ([40bd5cd](https://github.com/peerigon/clockodo/commit/40bd5cd15913f2579cb8c23110dde8d8992c39ca)) -* Remove status from required properties of addWorkTimesChangeRequest() ([65dbd8e](https://github.com/peerigon/clockodo/commit/65dbd8eb6a7815100291421569cabffbeb575a74)) +- Incorrect type of company.worktimeForceBreaks ([2c699dd](https://github.com/peerigon/clockodo/commit/2c699dd32672a9d10887c8c266f437181767ebb2)) +- move comments ([f281997](https://github.com/peerigon/clockodo/commit/f28199714131d2b8ec187b94263d81b63e0c3f12)) +- use work time force breaks enum ([3a7b396](https://github.com/peerigon/clockodo/commit/3a7b3963aa149e977185eefd092dc8156df77e05)) +## [21.10.1](https://github.com/peerigon/clockodo/compare/v21.10.0...v21.10.1) (2023-09-12) + +### Bug Fixes + +- Add missing exports ([7ab415e](https://github.com/peerigon/clockodo/commit/7ab415e286f5371cdcb1007d542a4528af33b902)) +- Add missing exports ([2e1f654](https://github.com/peerigon/clockodo/commit/2e1f654be533116ed0350e5f2f1626dedb6f8f36)) + +# [21.10.0](https://github.com/peerigon/clockodo/compare/v21.9.0...v21.10.0) (2023-09-12) ### Features -* add optional param to type ([d4cb3c6](https://github.com/peerigon/clockodo/commit/d4cb3c604300406832d6192e52293a5ea88178c4)) -* Improve types of getTargethours() ([3ecfb8f](https://github.com/peerigon/clockodo/commit/3ecfb8ffd549dbf2fbb7faeb0006c9597854b492)) +- Add upcoming `allowEntryOverlaps` to company type ([5b76f64](https://github.com/peerigon/clockodo/commit/5b76f64db5ad6f197c9957c92a6e25f55d87ca8c)) +- Add upcoming allowEntryOverlaps to company type ([73ee73c](https://github.com/peerigon/clockodo/commit/73ee73c369213c1d2f59d0926aa821b75a769d40)) -# [21.4.0](https://github.com/peerigon/clockodo/compare/v21.3.0...v21.4.0) (2023-07-10) +# [21.9.0](https://github.com/peerigon/clockodo/compare/v21.8.0...v21.9.0) (2023-09-06) + +### Features + +- adjust absence, targethours and nonbusinessday APIs to handle multiple ids at once ([b571c21](https://github.com/peerigon/clockodo/commit/b571c214803df4c0c16ed4d601b039ec837310bc)) +- Support filtering by multiple ids ([567bb22](https://github.com/peerigon/clockodo/commit/567bb22a8ae4681e8c88028af24578f933360cba)) +# [21.8.0](https://github.com/peerigon/clockodo/compare/v21.7.0...v21.8.0) (2023-09-06) ### Features -* add boss prop to user model ([dcc7e15](https://github.com/peerigon/clockodo/commit/dcc7e15ccf4de2af52d1c896aa315803ffddea71)) -* Add boss reference to user model ([aa66df7](https://github.com/peerigon/clockodo/commit/aa66df7838f60d4e27736c22a629f9f98aca41e1)) +- edit test for omitted billable feature ([d8689ad](https://github.com/peerigon/clockodo/commit/d8689adab8ecbd0b28bb7f2c8a5632d2ca4a4410)) +- support default configured billable ([da085fa](https://github.com/peerigon/clockodo/commit/da085faebfa9159d553824552ee604b6094237c3)) +- Support omitting billable from startClock() ([6b73818](https://github.com/peerigon/clockodo/commit/6b73818fdd9138223ee7d6bef5c467534ca431dd)) -# [21.3.0](https://github.com/peerigon/clockodo/compare/v21.2.0...v21.3.0) (2023-07-10) +# [21.7.0](https://github.com/peerigon/clockodo/compare/v21.6.0...v21.7.0) (2023-08-09) +### Features + +- expose nonbusiness group model ([eb4e568](https://github.com/peerigon/clockodo/commit/eb4e568dfa2aaec4401c8d8ef1a67f6bcfbe6ebb)) + +# [21.6.0](https://github.com/peerigon/clockodo/compare/v21.5.1...v21.6.0) (2023-07-28) + +### Bug Fixes + +- make mocks more consistent ([1fd9177](https://github.com/peerigon/clockodo/commit/1fd91773ab079bcfaccb47361807bc9f169bcda0)) + +### Features + +- add declined props ([1d80925](https://github.com/peerigon/clockodo/commit/1d80925c2c6de61c4fb4f8da65fb60f89068560a)) + +## [21.5.1](https://github.com/peerigon/clockodo/compare/v21.5.0...v21.5.1) (2023-07-19) ### Bug Fixes -* Use v2 endpoint for entrygroups (and adjust types) ([1647db4](https://github.com/peerigon/clockodo/commit/1647db4fe0e3f844be2afb54d4139d6c1a1a5dbb)) +- Incorrect absence and user types ([91a00b8](https://github.com/peerigon/clockodo/commit/91a00b89d6e18d6cbe3fbee8625a54e9c1223ae9)) + +# [21.5.0](https://github.com/peerigon/clockodo/compare/v21.4.0...v21.5.0) (2023-07-11) + +### Bug Fixes +- Remove status from required properties of addWorkTimesChangeRequest() ([40bd5cd](https://github.com/peerigon/clockodo/commit/40bd5cd15913f2579cb8c23110dde8d8992c39ca)) +- Remove status from required properties of addWorkTimesChangeRequest() ([65dbd8e](https://github.com/peerigon/clockodo/commit/65dbd8eb6a7815100291421569cabffbeb575a74)) ### Features -* update entrygroups endpoints ([82ff3b4](https://github.com/peerigon/clockodo/commit/82ff3b41152ea476afb1cae57c24bb1a6d3ec527)) +- add optional param to type ([d4cb3c6](https://github.com/peerigon/clockodo/commit/d4cb3c604300406832d6192e52293a5ea88178c4)) +- Improve types of getTargethours() ([3ecfb8f](https://github.com/peerigon/clockodo/commit/3ecfb8ffd549dbf2fbb7faeb0006c9597854b492)) -# [21.2.0](https://github.com/peerigon/clockodo/compare/v21.1.0...v21.2.0) (2023-06-07) +# [21.4.0](https://github.com/peerigon/clockodo/compare/v21.3.0...v21.4.0) (2023-07-10) +### Features + +- add boss prop to user model ([dcc7e15](https://github.com/peerigon/clockodo/commit/dcc7e15ccf4de2af52d1c896aa315803ffddea71)) +- Add boss reference to user model ([aa66df7](https://github.com/peerigon/clockodo/commit/aa66df7838f60d4e27736c22a629f9f98aca41e1)) + +# [21.3.0](https://github.com/peerigon/clockodo/compare/v21.2.0...v21.3.0) (2023-07-10) ### Bug Fixes -* rename workTimeEditLock prop ([4d83f26](https://github.com/peerigon/clockodo/commit/4d83f26f0d2cc9a92b51340e785e2ce52bdcd2f5)) +- Use v2 endpoint for entrygroups (and adjust types) ([1647db4](https://github.com/peerigon/clockodo/commit/1647db4fe0e3f844be2afb54d4139d6c1a1a5dbb)) + +### Features +- update entrygroups endpoints ([82ff3b4](https://github.com/peerigon/clockodo/commit/82ff3b41152ea476afb1cae57c24bb1a6d3ec527)) + +# [21.2.0](https://github.com/peerigon/clockodo/compare/v21.1.0...v21.2.0) (2023-06-07) + +### Bug Fixes + +- rename workTimeEditLock prop ([4d83f26](https://github.com/peerigon/clockodo/commit/4d83f26f0d2cc9a92b51340e785e2ce52bdcd2f5)) ### Features -* add status prop to change request model ([315a4a0](https://github.com/peerigon/clockodo/commit/315a4a0db94c89de7665669db9846623d8a7a613)) +- add status prop to change request model ([315a4a0](https://github.com/peerigon/clockodo/commit/315a4a0db94c89de7665669db9846623d8a7a613)) # [21.1.0](https://github.com/peerigon/clockodo/compare/v21.0.1...v21.1.0) (2023-06-01) - ### Features -* add withdrawWorkTimeChangeRequest method ([#105](https://github.com/peerigon/clockodo/issues/105)) ([1b5eade](https://github.com/peerigon/clockodo/commit/1b5eade65f6a96e23f4add258bab56db64788446)) +- add withdrawWorkTimeChangeRequest method ([#105](https://github.com/peerigon/clockodo/issues/105)) ([1b5eade](https://github.com/peerigon/clockodo/commit/1b5eade65f6a96e23f4add258bab56db64788446)) ## [21.0.1](https://github.com/peerigon/clockodo/compare/v21.0.0...v21.0.1) (2023-04-11) - ### Bug Fixes -* Missing README on NPM ([fcdb878](https://github.com/peerigon/clockodo/commit/fcdb878e23cb1fae5c72460ebaca12cf0c884db5)) +- Missing README on NPM ([fcdb878](https://github.com/peerigon/clockodo/commit/fcdb878e23cb1fae5c72460ebaca12cf0c884db5)) # [21.0.0](https://github.com/peerigon/clockodo/compare/v20.0.0...v21.0.0) (2023-04-11) - ### Bug Fixes -* add approvedImmediately=false case ([2cb939b](https://github.com/peerigon/clockodo/commit/2cb939b0ab2d67f2525ddc9a856155f59885a7a1)) -* add comment ([781c6a1](https://github.com/peerigon/clockodo/commit/781c6a186b6603b983d7460960b34eb877f37a63)) -* add mock functions export ([53c38a4](https://github.com/peerigon/clockodo/commit/53c38a46b515ec16cc398483667174d0f880421d)) -* add mocks for workTimes ([6752007](https://github.com/peerigon/clockodo/commit/675200770834008596a362afbbdc8e66794f571d)) -* change error message to have type correctly ([2f2c88e](https://github.com/peerigon/clockodo/commit/2f2c88e6a912a05704ddda9ded4e2b48482de207)) -* correct return type of approve/decline ([671d4c0](https://github.com/peerigon/clockodo/commit/671d4c096c2395add676d7f85fe20952f8995ec1)) -* Improve AddWorkTimesChangeRequestReturnType type ([0620097](https://github.com/peerigon/clockodo/commit/06200974909f5b3ccdb9eae26def31f383bca5f5)) -* Incorrect param type of addWorkTimesChangeRequest() ([18fddb1](https://github.com/peerigon/clockodo/commit/18fddb1ba5aadfb5ddb91cd8304ce77d92d16a12)) -* make mock generation slimmer ([09016c9](https://github.com/peerigon/clockodo/commit/09016c91a6e128844f3b69390c83f8f0eb1ef141)) -* reflect concept changes ([8ba8355](https://github.com/peerigon/clockodo/commit/8ba83554efdfcb53f9019ab43a5fe00160a12ee1)) -* return single mock instead of array ([fee1ff2](https://github.com/peerigon/clockodo/commit/fee1ff2a582e86e60c228385be5316bada150c32)) -* update user mock ([1a4864e](https://github.com/peerigon/clockodo/commit/1a4864e3d1fc78d1adf2cffb1968fcab604f66df)) - +- add approvedImmediately=false case ([2cb939b](https://github.com/peerigon/clockodo/commit/2cb939b0ab2d67f2525ddc9a856155f59885a7a1)) +- add comment ([781c6a1](https://github.com/peerigon/clockodo/commit/781c6a186b6603b983d7460960b34eb877f37a63)) +- add mock functions export ([53c38a4](https://github.com/peerigon/clockodo/commit/53c38a46b515ec16cc398483667174d0f880421d)) +- add mocks for workTimes ([6752007](https://github.com/peerigon/clockodo/commit/675200770834008596a362afbbdc8e66794f571d)) +- change error message to have type correctly ([2f2c88e](https://github.com/peerigon/clockodo/commit/2f2c88e6a912a05704ddda9ded4e2b48482de207)) +- correct return type of approve/decline ([671d4c0](https://github.com/peerigon/clockodo/commit/671d4c096c2395add676d7f85fe20952f8995ec1)) +- Improve AddWorkTimesChangeRequestReturnType type ([0620097](https://github.com/peerigon/clockodo/commit/06200974909f5b3ccdb9eae26def31f383bca5f5)) +- Incorrect param type of addWorkTimesChangeRequest() ([18fddb1](https://github.com/peerigon/clockodo/commit/18fddb1ba5aadfb5ddb91cd8304ce77d92d16a12)) +- make mock generation slimmer ([09016c9](https://github.com/peerigon/clockodo/commit/09016c91a6e128844f3b69390c83f8f0eb1ef141)) +- reflect concept changes ([8ba8355](https://github.com/peerigon/clockodo/commit/8ba83554efdfcb53f9019ab43a5fe00160a12ee1)) +- return single mock instead of array ([fee1ff2](https://github.com/peerigon/clockodo/commit/fee1ff2a582e86e60c228385be5316bada150c32)) +- update user mock ([1a4864e](https://github.com/peerigon/clockodo/commit/1a4864e3d1fc78d1adf2cffb1968fcab604f66df)) ### Features -* add workTimeEditLock prop to User ([89c3c86](https://github.com/peerigon/clockodo/commit/89c3c86bfe61953e94436ffbd00ef319d74c29fb)) -* Add workTimes API methods ([#101](https://github.com/peerigon/clockodo/issues/101)) ([8bbca40](https://github.com/peerigon/clockodo/commit/8bbca40cd69a3ffc8ca6031e97fee9517c91b667)) -* add workTimes types ([4c8f6e4](https://github.com/peerigon/clockodo/commit/4c8f6e44649a8e3f26d3f723eade7d3c5e06eec5)) -* expand change request return type ([d337cc3](https://github.com/peerigon/clockodo/commit/d337cc30e512238ae9b2b0f75837fb13e29e7499)) -* Expose team types ([952f700](https://github.com/peerigon/clockodo/commit/952f70017ee7d037670ac6ee493e07eb7a59afe6)) -* Improve workTimes mocks ([3499590](https://github.com/peerigon/clockodo/commit/34995901a1a87054afd7592fd38eccfb772b6721)) -* Introduce special IsoDate and IsoUtcDateTime types ([6fe88e2](https://github.com/peerigon/clockodo/commit/6fe88e240c480466ae8a83748128d27dd8601609)) -* parametrize user mock's workTimeEditLock ([f976f7f](https://github.com/peerigon/clockodo/commit/f976f7f00f42e4c36c713cbb899640f56d1c59a8)) -* Update Node ([40f81b6](https://github.com/peerigon/clockodo/commit/40f81b66c53f9b8dd4afd2f2919a359615dceb13)) - +- add workTimeEditLock prop to User ([89c3c86](https://github.com/peerigon/clockodo/commit/89c3c86bfe61953e94436ffbd00ef319d74c29fb)) +- Add workTimes API methods ([#101](https://github.com/peerigon/clockodo/issues/101)) ([8bbca40](https://github.com/peerigon/clockodo/commit/8bbca40cd69a3ffc8ca6031e97fee9517c91b667)) +- add workTimes types ([4c8f6e4](https://github.com/peerigon/clockodo/commit/4c8f6e44649a8e3f26d3f723eade7d3c5e06eec5)) +- expand change request return type ([d337cc3](https://github.com/peerigon/clockodo/commit/d337cc30e512238ae9b2b0f75837fb13e29e7499)) +- Expose team types ([952f700](https://github.com/peerigon/clockodo/commit/952f70017ee7d037670ac6ee493e07eb7a59afe6)) +- Improve workTimes mocks ([3499590](https://github.com/peerigon/clockodo/commit/34995901a1a87054afd7592fd38eccfb772b6721)) +- Introduce special IsoDate and IsoUtcDateTime types ([6fe88e2](https://github.com/peerigon/clockodo/commit/6fe88e240c480466ae8a83748128d27dd8601609)) +- parametrize user mock's workTimeEditLock ([f976f7f](https://github.com/peerigon/clockodo/commit/f976f7f00f42e4c36c713cbb899640f56d1c59a8)) +- Update Node ([40f81b6](https://github.com/peerigon/clockodo/commit/40f81b66c53f9b8dd4afd2f2919a359615dceb13)) ### BREAKING CHANGES -* Removed official Node 14 support. We don't know of an actual breaking change for Node 14, but it might happen in future releases. +- Removed official Node 14 support. We don't know of an actual breaking change for Node 14, but it might happen in future releases. # [21.0.0-beta.1](https://github.com/peerigon/clockodo/compare/v20.0.0...v21.0.0-beta.1) (2023-04-11) - ### Bug Fixes -* add approvedImmediately=false case ([2cb939b](https://github.com/peerigon/clockodo/commit/2cb939b0ab2d67f2525ddc9a856155f59885a7a1)) -* add comment ([781c6a1](https://github.com/peerigon/clockodo/commit/781c6a186b6603b983d7460960b34eb877f37a63)) -* add mock functions export ([53c38a4](https://github.com/peerigon/clockodo/commit/53c38a46b515ec16cc398483667174d0f880421d)) -* add mocks for workTimes ([6752007](https://github.com/peerigon/clockodo/commit/675200770834008596a362afbbdc8e66794f571d)) -* change error message to have type correctly ([2f2c88e](https://github.com/peerigon/clockodo/commit/2f2c88e6a912a05704ddda9ded4e2b48482de207)) -* correct return type of approve/decline ([671d4c0](https://github.com/peerigon/clockodo/commit/671d4c096c2395add676d7f85fe20952f8995ec1)) -* Improve AddWorkTimesChangeRequestReturnType type ([0620097](https://github.com/peerigon/clockodo/commit/06200974909f5b3ccdb9eae26def31f383bca5f5)) -* Incorrect param type of addWorkTimesChangeRequest() ([18fddb1](https://github.com/peerigon/clockodo/commit/18fddb1ba5aadfb5ddb91cd8304ce77d92d16a12)) -* make mock generation slimmer ([09016c9](https://github.com/peerigon/clockodo/commit/09016c91a6e128844f3b69390c83f8f0eb1ef141)) -* reflect concept changes ([8ba8355](https://github.com/peerigon/clockodo/commit/8ba83554efdfcb53f9019ab43a5fe00160a12ee1)) -* return single mock instead of array ([fee1ff2](https://github.com/peerigon/clockodo/commit/fee1ff2a582e86e60c228385be5316bada150c32)) -* update user mock ([1a4864e](https://github.com/peerigon/clockodo/commit/1a4864e3d1fc78d1adf2cffb1968fcab604f66df)) - +- add approvedImmediately=false case ([2cb939b](https://github.com/peerigon/clockodo/commit/2cb939b0ab2d67f2525ddc9a856155f59885a7a1)) +- add comment ([781c6a1](https://github.com/peerigon/clockodo/commit/781c6a186b6603b983d7460960b34eb877f37a63)) +- add mock functions export ([53c38a4](https://github.com/peerigon/clockodo/commit/53c38a46b515ec16cc398483667174d0f880421d)) +- add mocks for workTimes ([6752007](https://github.com/peerigon/clockodo/commit/675200770834008596a362afbbdc8e66794f571d)) +- change error message to have type correctly ([2f2c88e](https://github.com/peerigon/clockodo/commit/2f2c88e6a912a05704ddda9ded4e2b48482de207)) +- correct return type of approve/decline ([671d4c0](https://github.com/peerigon/clockodo/commit/671d4c096c2395add676d7f85fe20952f8995ec1)) +- Improve AddWorkTimesChangeRequestReturnType type ([0620097](https://github.com/peerigon/clockodo/commit/06200974909f5b3ccdb9eae26def31f383bca5f5)) +- Incorrect param type of addWorkTimesChangeRequest() ([18fddb1](https://github.com/peerigon/clockodo/commit/18fddb1ba5aadfb5ddb91cd8304ce77d92d16a12)) +- make mock generation slimmer ([09016c9](https://github.com/peerigon/clockodo/commit/09016c91a6e128844f3b69390c83f8f0eb1ef141)) +- reflect concept changes ([8ba8355](https://github.com/peerigon/clockodo/commit/8ba83554efdfcb53f9019ab43a5fe00160a12ee1)) +- return single mock instead of array ([fee1ff2](https://github.com/peerigon/clockodo/commit/fee1ff2a582e86e60c228385be5316bada150c32)) +- update user mock ([1a4864e](https://github.com/peerigon/clockodo/commit/1a4864e3d1fc78d1adf2cffb1968fcab604f66df)) ### Features -* add workTimeEditLock prop to User ([89c3c86](https://github.com/peerigon/clockodo/commit/89c3c86bfe61953e94436ffbd00ef319d74c29fb)) -* Add workTimes API methods ([#101](https://github.com/peerigon/clockodo/issues/101)) ([8bbca40](https://github.com/peerigon/clockodo/commit/8bbca40cd69a3ffc8ca6031e97fee9517c91b667)) -* add workTimes types ([4c8f6e4](https://github.com/peerigon/clockodo/commit/4c8f6e44649a8e3f26d3f723eade7d3c5e06eec5)) -* expand change request return type ([d337cc3](https://github.com/peerigon/clockodo/commit/d337cc30e512238ae9b2b0f75837fb13e29e7499)) -* Expose team types ([952f700](https://github.com/peerigon/clockodo/commit/952f70017ee7d037670ac6ee493e07eb7a59afe6)) -* Improve workTimes mocks ([3499590](https://github.com/peerigon/clockodo/commit/34995901a1a87054afd7592fd38eccfb772b6721)) -* Introduce special IsoDate and IsoUtcDateTime types ([6fe88e2](https://github.com/peerigon/clockodo/commit/6fe88e240c480466ae8a83748128d27dd8601609)) -* parametrize user mock's workTimeEditLock ([f976f7f](https://github.com/peerigon/clockodo/commit/f976f7f00f42e4c36c713cbb899640f56d1c59a8)) -* Update Node ([40f81b6](https://github.com/peerigon/clockodo/commit/40f81b66c53f9b8dd4afd2f2919a359615dceb13)) - +- add workTimeEditLock prop to User ([89c3c86](https://github.com/peerigon/clockodo/commit/89c3c86bfe61953e94436ffbd00ef319d74c29fb)) +- Add workTimes API methods ([#101](https://github.com/peerigon/clockodo/issues/101)) ([8bbca40](https://github.com/peerigon/clockodo/commit/8bbca40cd69a3ffc8ca6031e97fee9517c91b667)) +- add workTimes types ([4c8f6e4](https://github.com/peerigon/clockodo/commit/4c8f6e44649a8e3f26d3f723eade7d3c5e06eec5)) +- expand change request return type ([d337cc3](https://github.com/peerigon/clockodo/commit/d337cc30e512238ae9b2b0f75837fb13e29e7499)) +- Expose team types ([952f700](https://github.com/peerigon/clockodo/commit/952f70017ee7d037670ac6ee493e07eb7a59afe6)) +- Improve workTimes mocks ([3499590](https://github.com/peerigon/clockodo/commit/34995901a1a87054afd7592fd38eccfb772b6721)) +- Introduce special IsoDate and IsoUtcDateTime types ([6fe88e2](https://github.com/peerigon/clockodo/commit/6fe88e240c480466ae8a83748128d27dd8601609)) +- parametrize user mock's workTimeEditLock ([f976f7f](https://github.com/peerigon/clockodo/commit/f976f7f00f42e4c36c713cbb899640f56d1c59a8)) +- Update Node ([40f81b6](https://github.com/peerigon/clockodo/commit/40f81b66c53f9b8dd4afd2f2919a359615dceb13)) ### BREAKING CHANGES -* Removed official Node 14 support. We don't know of an actual breaking change for Node 14, but it might happen in future releases. +- Removed official Node 14 support. We don't know of an actual breaking change for Node 14, but it might happen in future releases. # [20.0.0](https://github.com/peerigon/clockodo/compare/v19.1.2...v20.0.0) (2023-04-06) diff --git a/README.md b/README.md index 33f72493..dc020153 100644 --- a/README.md +++ b/README.md @@ -754,50 +754,50 @@ await clockodo.editUser({ id: 33, name: "Moalo Loco" }); ## Delete methods -### deactivateCustomer() +### deleteCustomer() -Deactivates (not deletes) customer. +Deletes the customer. #### Example: ```js -await clockodo.deactivateCustomer({ id: 343 }); +await clockodo.deleteCustomer({ id: 343 }); ``` --- -### deactivateProject() +### deleteProject() -Deactivates (not deletes) project. +Deletes the project. #### Example: ```js -await clockodo.deactivateProject({ id: 8 }); +await clockodo.deleteProject({ id: 8 }); ``` --- -### deactivateService() +### deleteService() -Deactivates (not deletes) service. +Deletes the service. #### Example: ```js -await clockodo.deactivateService({ id: 94 }); +await clockodo.deleteService({ id: 94 }); ``` --- -### deactivateUser() +### deleteUser() -Deactivates (not deletes) user. +Deletes user. #### Example: ```js -await clockodo.deactivateUser({ id: 7 }); +await clockodo.deleteUser({ id: 7 }); ``` --- diff --git a/src/clockodo.test.ts b/src/clockodo.test.ts index b45cdb63..d0a3e035 100644 --- a/src/clockodo.test.ts +++ b/src/clockodo.test.ts @@ -194,6 +194,46 @@ describe("Clockodo (instance)", () => { }); }); + describe("getLumpSumService()", () => { + it("correctly builds getLumpSumService() request", async () => { + const nockScope = nock(CLOCKODO_API) + .get("/v3/lumpsumservices/777") + .reply(200, {}); + + await clockodo.getLumpSumService({ id: 777 }); + + nockScope.done(); + }); + }); + + describe("getLumpSumServicesPage()", () => { + it("correctly builds getLumpSumServicesPage() request", async () => { + const nockScope = nock(CLOCKODO_API) + .get("/v3/lumpsumservices") + .reply(200, {}); + + await clockodo.getLumpSumServicesPage(); + + nockScope.done(); + }); + }); + + describe("getLumpSumServices()", () => { + it("requests all lumpSumService pages", async () => { + const nockScope = setupPaginatedApiMock({ + baseUrl: "/v3/lumpsumservices?", + countPages: 3, + createPageResponse: (page) => ({ lumpSumServices: [page] }), + }); + + const { lumpSumServices } = await clockodo.getLumpSumServices(); + + expect(lumpSumServices).toMatchObject([1, 2, 3]); + + nockScope.done(); + }); + }); + describe("getEntry()", () => { it("correctly builds getEntry() request", async () => { const nockScope = nock(CLOCKODO_API) @@ -405,7 +445,9 @@ describe("Clockodo (instance)", () => { describe("getService()", () => { it("correctly builds getService() request", async () => { - const nockScope = nock(CLOCKODO_API).get("/services/10").reply(200, {}); + const nockScope = nock(CLOCKODO_API) + .get("/v3/services/10") + .reply(200, {}); await clockodo.getService({ id: 10 }); @@ -413,11 +455,27 @@ describe("Clockodo (instance)", () => { }); }); + describe("getServicesPage()", () => { + it("correctly builds getServicesPage() request", async () => { + const nockScope = nock(CLOCKODO_API).get("/v3/services").reply(200, {}); + + await clockodo.getServicesPage(); + + nockScope.done(); + }); + }); + describe("getServices()", () => { - it("correctly builds getServices() request", async () => { - const nockScope = nock(CLOCKODO_API).get("/services").reply(200, {}); + it("requests all getServices pages", async () => { + const nockScope = setupPaginatedApiMock({ + baseUrl: "/v3/services?", + countPages: 3, + createPageResponse: (page) => ({ services: [page] }), + }); + + const { services } = await clockodo.getServices(); - await clockodo.getServices(); + expect(services).toMatchObject([1, 2, 3]); nockScope.done(); }); @@ -447,7 +505,9 @@ describe("Clockodo (instance)", () => { describe("getUser()", () => { it("correctly builds getUser() request", async () => { - const nockScope = nock(CLOCKODO_API).get("/users/1263").reply(200, {}); + const nockScope = nock(CLOCKODO_API) + .get("/v2/users/1263") + .reply(200, {}); await clockodo.getUser({ id: 1263 }); @@ -457,7 +517,7 @@ describe("Clockodo (instance)", () => { describe("getUsers()", () => { it("correctly builds getUsers() request", async () => { - const nockScope = nock(CLOCKODO_API).get("/users").reply(200, {}); + const nockScope = nock(CLOCKODO_API).get("/v2/users").reply(200, {}); await clockodo.getUsers(); @@ -516,12 +576,15 @@ describe("Clockodo (instance)", () => { const nockScope = nock(CLOCKODO_API) .get( "/nonbusinessdays?" + - qs.stringify({ nonbusinessgroups_id: 123, year: 2021 }) + qs.stringify( + { nonbusinessgroups_id: [123], year: 2021 }, + { arrayFormat: "brackets" } + ) ) .reply(200, {}); await clockodo.getNonbusinessDays({ - nonbusinessgroupsId: 123, + nonbusinessgroupsId: [123], year: 2021, }); @@ -589,6 +652,42 @@ describe("Clockodo (instance)", () => { nockScope.done(); }); }); + + describe("getOvertimecarry()", () => { + it("correctly builds getOvertimecarry() request", async () => { + const nockScope = nock(CLOCKODO_API) + .get("/overtimecarry?users_id=17&year=2028") + .reply(200, {}); + + await clockodo.getOvertimecarry({ usersId: 17, year: 2028 }); + + nockScope.done(); + }); + }); + + describe("getHolidaysQuotas()", () => { + it("correctly builds getHolidaysQuotas() request", async () => { + const nockScope = nock(CLOCKODO_API) + .get("/holidaysquota?users_id=17") + .reply(200, {}); + + await clockodo.getHolidaysQuotas({ usersId: 17 }); + + nockScope.done(); + }); + }); + + describe("getHolidaysCarryovers()", () => { + it("correctly builds getHolidaysCarryovers() request", async () => { + const nockScope = nock(CLOCKODO_API) + .get("/holidayscarry?users_id=17&year=2028") + .reply(200, {}); + + await clockodo.getHolidaysCarryovers({ usersId: 17, year: 2028 }); + + nockScope.done(); + }); + }); }); describe("POST", () => { @@ -621,9 +720,8 @@ describe("Clockodo (instance)", () => { // @ts-expect-error Intentional error just for the test clockodo.startClock({ customersId: 24, - servicesId: 7, }) - ).rejects.toThrowError('Missing required parameter "billable"'); + ).rejects.toThrowError('Missing required parameter "servicesId"'); }); }); @@ -647,6 +745,26 @@ describe("Clockodo (instance)", () => { }); }); + describe("addLumpsumService()", () => { + it("correctly builds addLumpsumService() request", async () => { + const expectedParameters = { + name: "Weyland-Yutani", + price: 1, + }; + + const nockScope = nock(CLOCKODO_API) + .post("/v3/lumpsumservices", expectedParameters) + .reply(200, {}); + + await clockodo.addLumpsumService({ + name: "Weyland-Yutani", + price: 1, + }); + + nockScope.done(); + }); + }); + describe("addProject()", () => { it("correctly builds addProject() request", async () => { const expectedParameters = { @@ -677,7 +795,7 @@ describe("Clockodo (instance)", () => { }; const nockScope = nock(CLOCKODO_API) - .post("/services", expectedParameters) + .post("/v3/services", expectedParameters) .reply(200, {}); await clockodo.addService({ name: "Thinking", active: true }); @@ -696,7 +814,7 @@ describe("Clockodo (instance)", () => { }; const nockScope = nock(CLOCKODO_API) - .post("/users", expectedParameters) + .post("/v2/users", expectedParameters) .reply(200, {}); await clockodo.addUser({ @@ -766,8 +884,8 @@ describe("Clockodo (instance)", () => { describe("addAbsence()", () => { it("correctly builds addAbsence() request", async () => { const expectedParameters = { - date_since: "2017-08-18 00:00:00", - date_until: "2018-02-09 00:00:00", + date_since: "2017-08-18", + date_until: "2018-02-09", type: AbsenceType.SpecialLeave, note: "elternzeit", }; @@ -777,8 +895,8 @@ describe("Clockodo (instance)", () => { .reply(200, {}); await clockodo.addAbsence({ - dateSince: "2017-08-18 00:00:00", - dateUntil: "2018-02-09 00:00:00", + dateSince: "2017-08-18", + dateUntil: "2018-02-09", type: AbsenceType.SpecialLeave, note: "elternzeit", }); @@ -791,8 +909,8 @@ describe("Clockodo (instance)", () => { return expect( // @ts-expect-error Intentional error just for the test clockodo.addAbsence({ - dateSince: "2017-08-18 00:00:00", - dateUntil: "2018-02-09 00:00:00", + dateSince: "2017-08-18", + dateUntil: "2018-02-09", }) ).rejects.toThrowError('Missing required parameter "type"'); }); @@ -921,6 +1039,23 @@ describe("Clockodo (instance)", () => { }); }); + describe("editLumpsumService()", () => { + it("correctly builds editLumpsumService() request", async () => { + const lumpsumService = { + id: 15, + name: "Mystery Gang", + }; + + const nockScope = nock(CLOCKODO_API) + .put("/v3/lumpsumservices/15", mapRequestBody(lumpsumService)) + .reply(200, {}); + + await clockodo.editLumpsumService(lumpsumService); + + nockScope.done(); + }); + }); + describe("editProject()", () => { it("correctly builds editProject() request", async () => { const project = { @@ -947,7 +1082,7 @@ describe("Clockodo (instance)", () => { }; const nockScope = nock(CLOCKODO_API) - .put("/services/23", mapRequestBody(service)) + .put("/v3/services/23", mapRequestBody(service)) .reply(200, {}); await clockodo.editService(service); @@ -964,7 +1099,7 @@ describe("Clockodo (instance)", () => { }; const nockScope = nock(CLOCKODO_API) - .put("/users/33", mapRequestBody(user)) + .put("/v2/users/33", mapRequestBody(user)) .reply(200, {}); await clockodo.editUser(user); @@ -1050,47 +1185,61 @@ describe("Clockodo (instance)", () => { }); }); - describe("deactivateCustomer()", () => { - it("correctly builds deactivateCustomer() request", async () => { + describe("deleteCustomer()", () => { + it("correctly builds deleteCustomer() request", async () => { const nockScope = nock(CLOCKODO_API) .delete("/v2/customers/343") .reply(200, {}); - await clockodo.deactivateCustomer({ id: 343 }); + await clockodo.deleteCustomer({ id: 343 }); nockScope.done(); }); }); - describe("deactivateProject()", () => { - it("correctly builds deactivateProject() request", async () => { + describe("deleteProject()", () => { + it("correctly builds deleteProject() request", async () => { const nockScope = nock(CLOCKODO_API) .delete("/v2/projects/8") .reply(200, {}); - await clockodo.deactivateProject({ id: 8 }); + await clockodo.deleteProject({ id: 8 }); + + nockScope.done(); + }); + }); + + describe("deleteService()", () => { + it("correctly builds deleteService() request", async () => { + const nockScope = nock(CLOCKODO_API) + .delete("/v3/services/94") + .reply(200, {}); + + await clockodo.deleteService({ id: 94 }); nockScope.done(); }); }); - describe("deactivateService()", () => { - it("correctly builds deactivateService() request", async () => { + describe("deleteLumpsumService()", () => { + it("correctly builds deleteLumpsumService() request", async () => { const nockScope = nock(CLOCKODO_API) - .delete("/services/94") + .delete("/v3/lumpsumservices/94") .reply(200, {}); - await clockodo.deactivateService({ id: 94 }); + await clockodo.deleteLumpsumService({ id: 94 }); nockScope.done(); }); }); - describe("deactivateUser()", () => { - it("correctly builds deactivateUser() request", async () => { - const nockScope = nock(CLOCKODO_API).delete("/users/7").reply(200, {}); + describe("deleteUser()", () => { + it("correctly builds deleteUser() request", async () => { + const nockScope = nock(CLOCKODO_API) + .delete("/v2/users/7") + .reply(200, {}); - await clockodo.deactivateUser({ id: 7 }); + await clockodo.deleteUser({ id: 7 }); nockScope.done(); }); diff --git a/src/clockodo.ts b/src/clockodo.ts index 21dce9f8..bcf5928b 100644 --- a/src/clockodo.ts +++ b/src/clockodo.ts @@ -41,6 +41,9 @@ import { WorkTimeChangeRequestStatus, WorkTimeDay, } from "./models/workTimes.js"; +import { OvertimecarryRow } from "./models/overtimecarry.js"; +import { HolidaysQuota } from "./models/holidaysQuota.js"; +import { HolidaysCarryover } from "./models/holidaysCarryover.js"; export class Clockodo { api: Api; @@ -67,7 +70,7 @@ export class Clockodo { } async getAbsences( - params: Params<{ year: number }> + params: Params<{ year: number; usersId?: User["id"] | Array }> ): Promise { REQUIRED.checkRequired(params, REQUIRED.GET_ABSENCES); @@ -115,7 +118,7 @@ export class Clockodo { } async getCustomersPage( - params?: Params + params?: Params ): Promise { return this.api.get("/v2/customers", params); } @@ -147,7 +150,7 @@ export class Clockodo { } async getProjectsPage( - params?: Params + params?: Params ): Promise { return this.api.get("/v2/projects", params); } @@ -207,7 +210,7 @@ export class Clockodo { } async getEntriesPage( - params: Params + params: Params ): Promise { REQUIRED.checkRequired(params, REQUIRED.GET_ENTRIES); @@ -235,7 +238,7 @@ export class Clockodo { } async getEntriesTextsPage( - params: Params + params: Params ): Promise { REQUIRED.checkRequired(params, REQUIRED.GET_ENTRIES_TEXTS); @@ -264,11 +267,29 @@ export class Clockodo { const { id, ...remainingParams } = params; - return this.api.get("/services/" + id, remainingParams); + return this.api.get("/v3/services/" + id, remainingParams); + } + + async getServices( + params?: Params + ): Promise> { + const pages = await this.api.getAllPages( + "/v3/services", + params + ); + const [{ paging, ...remainingResponse }] = pages; + const services = pages.flatMap(({ services }) => services); + + return { + ...remainingResponse, + services, + }; } - async getServices(params?: Params): Promise { - return this.api.get("/services", params); + async getServicesPage( + params?: Params + ): Promise { + return this.api.get("/v3/services", params); } async getTeam(params: Params<{ id: Team["id"] }>): Promise { @@ -291,14 +312,33 @@ export class Clockodo { const { id, ...remainingParams } = params; - return this.api.get("/lumpsumservices/" + id, remainingParams); + return this.api.get("/v3/lumpsumservices/" + id, remainingParams); } // This endpoint still uses the old lumpSum casing async getLumpSumServices( - params?: Params + params?: Params + ): Promise> { + const pages = await this.api.getAllPages( + "/v3/lumpsumservices", + params + ); + const [{ paging, ...remainingResponse }] = pages; + const lumpSumServices = pages.flatMap( + ({ lumpSumServices }) => lumpSumServices + ); + + return { + ...remainingResponse, + lumpSumServices, + }; + } + + // This endpoint still uses the old lumpSum casing + async getLumpSumServicesPage( + params?: Params ): Promise { - return this.api.get("/lumpsumservices", params); + return this.api.get("/v3/lumpsumservices", params); } async getTargethoursRow( @@ -312,7 +352,7 @@ export class Clockodo { } async getTargethours( - params?: Params<{ usersId?: number }> + params?: Params<{ usersId?: User["id"] | Array }> ): Promise { return this.api.get("/targethours", params); } @@ -322,11 +362,11 @@ export class Clockodo { const { id, ...remainingParams } = params; - return this.api.get("/users/" + id, remainingParams); + return this.api.get("/v2/users/" + id, remainingParams); } async getUsers(params?: Params): Promise { - return this.api.get("/users", params); + return this.api.get("/v2/users", params); } async getUserReport< @@ -362,7 +402,12 @@ export class Clockodo { } async getNonbusinessDays( - params: Params<{ nonbusinessgroupsId: number; year: number }> + params: Params<{ + nonbusinessgroupsId?: + | NonbusinessGroup["id"] + | Array; + year: number; + }> ): Promise { REQUIRED.checkRequired(params, REQUIRED.GET_NONBUSINESS_DAYS); @@ -391,6 +436,16 @@ export class Clockodo { return this.api.post("/v2/customers", params); } + async addLumpsumService( + params: Params< + Pick + > + ): Promise { + REQUIRED.checkRequired(params, REQUIRED.ADD_LUMPSUM_SERVICE); + + return this.api.post("/v3/lumpsumservices", params); + } + async addEntry( params: Params< | Pick @@ -425,7 +480,7 @@ export class Clockodo { ): Promise { REQUIRED.checkRequired(params, REQUIRED.ADD_SERVICE); - return this.api.post("/services", params); + return this.api.post("/v3/services", params); } async addTeam( @@ -441,13 +496,17 @@ export class Clockodo { ): Promise { REQUIRED.checkRequired(params, REQUIRED.ADD_USER); - return this.api.post("/users", params); + return this.api.post("/v2/users", params); } async startClock( params: Params< Pick & { - billable: ClockingTimeEntryBillability; + /** + * Billability of the time entry that is about to be created. + * Omit it if you want to use the project's default. + */ + billable?: ClockingTimeEntryBillability; } > ): Promise { @@ -490,6 +549,18 @@ export class Clockodo { return this.api.put("/v2/customers/" + id, params); } + async editLumpsumService( + params: Params< + Pick + > + ) { + REQUIRED.checkRequired(params, REQUIRED.EDIT_LUMPSUM_SERVICE); + + const { id } = params; + + return this.api.put("/v3/lumpsumservices/" + id, params); + } + async editEntry( params: Params> ): Promise { @@ -525,7 +596,7 @@ export class Clockodo { const { id } = params; - return this.api.put("/services/" + id, params); + return this.api.put("/v3/services/" + id, params); } async editTeam( @@ -545,47 +616,47 @@ export class Clockodo { const { id } = params; - return this.api.put("/users/" + id, params); + return this.api.put("/v2/users/" + id, params); } - async deactivateCustomer( - params: Params> + async deleteCustomer( + params: Params> ): Promise { - REQUIRED.checkRequired(params, REQUIRED.DEACTIVATE_CUSTOMER); + REQUIRED.checkRequired(params, REQUIRED.DELETE_CUSTOMER); const { id } = params; return this.api.delete("/v2/customers/" + id, params); } - async deactivateProject( - params: Params> + async deleteProject( + params: Params> ): Promise { - REQUIRED.checkRequired(params, REQUIRED.DEACTIVATE_PROJECT); + REQUIRED.checkRequired(params, REQUIRED.DELETE_PROJECT); const { id } = params; return this.api.delete("/v2/projects/" + id, params); } - async deactivateService( - params: Params> + async deleteService( + params: Params> ): Promise { - REQUIRED.checkRequired(params, REQUIRED.DEACTIVATE_SERVICE); + REQUIRED.checkRequired(params, REQUIRED.DELETE_SERVICE); const { id } = params; - return this.api.delete("/services/" + id, params); + return this.api.delete("/v3/services/" + id, params); } - async deactivateUser( - params: Params> + async deleteUser( + params: Params> ): Promise { - REQUIRED.checkRequired(params, REQUIRED.DEACTIVATE_USER); + REQUIRED.checkRequired(params, REQUIRED.DELETE_USER); const { id } = params; - return this.api.delete("/users/" + id, params); + return this.api.delete("/v2/users/" + id, params); } async deleteAbsence( @@ -608,6 +679,18 @@ export class Clockodo { return this.api.delete("/v2/entries/" + id, params); } + async deleteLumpsumService( + params: Params< + Pick + > + ): Promise { + REQUIRED.checkRequired(params, REQUIRED.DELETE_LUMPSUM_SERVICE); + + const { id } = params; + + return this.api.delete("/v3/lumpsumservices/" + id, params); + } + async deleteEntryGroup( params: Params<{ timeSince: string; timeUntil: string }> ): Promise { @@ -645,7 +728,7 @@ export class Clockodo { } async getWorkTimesPage( - params?: Params + params?: Params ): Promise { return this.api.get("/v2/workTimes", params); } @@ -667,7 +750,7 @@ export class Clockodo { } async getWorkTimesChangeRequestsPage( - params: Params + params: Params ): Promise { return this.api.get("/v2/workTimes/changeRequests", params); } @@ -756,6 +839,24 @@ export class Clockodo { remainingParams ); } + + async getOvertimecarry( + params?: Params + ): Promise { + return this.api.get("/overtimecarry", params); + } + + async getHolidaysQuotas( + params?: Params + ): Promise { + return this.api.get("/holidaysquota", params); + } + + async getHolidaysCarryovers( + params?: Params + ): Promise { + return this.api.get("/holidayscarry", params); + } } export type AbsenceReturnType = { absence: Absence }; @@ -787,18 +888,35 @@ export type ProjectsReturnType = ResponseWithPaging & projects: Array; }; export type ProjectReturnType = { project: Project }; + +export type ServiceParams = { + /** Filter service by search term */ + filterFulltext?: string; + /** Filter service by active flag */ + filterActive?: boolean; +}; export type ServiceReturnType = { service: Service }; -export type ServicesReturnType = { services: Array }; +export type ServicesReturnType = ResponseWithPaging & + ResponseWithFilter<"active" | "fulltext"> & { services: Array }; + export type TeamReturnType = { team: Team }; export type TeamsReturnType = { teams: Array }; + +export type LumpsumServiceParams = { + /** Filter lumpsum service by search term */ + filterFulltext?: string; + /** Filter lumpsum service by active flag */ + filterActive?: boolean; +}; export type LumpsumServiceReturnType = { // This endpoint still uses the old lumpSum casing lumpSumService: LumpsumService; }; -export type LumpsumServicesReturnType = { - // This endpoint still uses the old lumpSum casing - lumpSumServices: Array; -}; +export type LumpsumServicesReturnType = ResponseWithPaging & + ResponseWithFilter<"active" | "fulltext"> & { + // This endpoint still uses the old lumpSum casing + lumpSumServices: Array; + }; export type UserReturnType = { user: User }; export type UsersReturnType = { users: Array }; export type EntryReturnType = { entry: Entry }; @@ -991,7 +1109,7 @@ export type AddUserReturnType = { user: User; }; -export type WorkTimesParams = ParamsWithPage & { +export type WorkTimesParams = { /** The user ID by which the work times should be filtered */ usersId?: number; dateSince: string; @@ -1001,7 +1119,7 @@ export type WorkTimesReturnType = ResponseWithPaging & { workTimeDays: Array; }; -export type WorkTimesChangeRequestsParams = ParamsWithPage & { +export type WorkTimesChangeRequestsParams = { /** The user ID by which the work time change requests should be filtered */ usersId?: number; dateSince?: string; @@ -1044,3 +1162,31 @@ export type AddWorkTimesChangeRequestReturnType = **/ replacedChangeRequest: null; }; + +export type OvertimecarryRowReturnType = { + overtimecarry: Array; +}; +export type OvertimecarryRowParams = { + /** The user ID by which the overtime carry rows should be filtered */ + usersId?: number; + /** The year to which the data should be restricted to */ + year?: number; +}; + +export type HolidaysQuotasReturnType = { + holidaysquota: Array; +}; +export type HolidaysQuotasParams = { + /** The user ID by which the holidays quota rows should be filtered */ + usersId?: number; +}; + +export type HolidaysCarryoversReturnType = { + holidayscarry: Array; +}; +export type HolidaysCarryoversParams = { + /** The user ID by which the holidays carry rows should be filtered */ + usersId?: number; + /** The year to which the data should be restricted to */ + year?: number; +}; diff --git a/src/index.ts b/src/index.ts index 34ff3590..2a260cb4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,17 @@ export * from "./models/absence.js"; export * from "./models/access.js"; +export * from "./models/company.js"; export * from "./models/customer.js"; export * from "./models/dateTime.js"; +export * from "./models/entriesText.js"; export * from "./models/entry.js"; export * from "./models/entryGroup.js"; -export * from "./models/holidayscarry.js"; -export * from "./models/holidaysquota.js"; +export * from "./models/holidaysCarryover.js"; +export * from "./models/holidaysQuota.js"; export * from "./models/lumpsumService.js"; export * from "./models/nonbusinessDay.js"; export * from "./models/nonbusinessGroup.js"; +export * from "./models/overtimecarry.js"; export * from "./models/project.js"; export * from "./models/service.js"; export * from "./models/targethours.js"; diff --git a/src/lib/api.ts b/src/lib/api.ts index 0ceb1439..22fec2db 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -13,13 +13,7 @@ const paramsSerializer = (params: Record) => { const urlParams = []; for (const [key, value] of Object.entries(params)) { - if (key === "grouping") { - urlParams.push( - qs.stringify({ [key]: value }, { arrayFormat: "brackets" }) - ); - } else { - urlParams.push(qs.stringify({ [key]: value }, { arrayFormat: "repeat" })); - } + urlParams.push(qs.stringify({ [key]: value }, { arrayFormat: "brackets" })); } return urlParams.join("&"); @@ -35,6 +29,7 @@ export type Params< export type ParamsWithPage = { page?: number; + itemsPerPage?: number; }; export type Paging = { @@ -59,6 +54,7 @@ export type Filter = { timeSince: string; timeUntil: string; active: BooleanAsNumber; + fulltext: string; }; export type ResponseWithPaging = { diff --git a/src/lib/mappings.ts b/src/lib/mappings.ts index c7a93c90..dfa37374 100644 --- a/src/lib/mappings.ts +++ b/src/lib/mappings.ts @@ -20,6 +20,7 @@ export const queryParamMapping: Record = { filterTimeSince: "filter[time_since]", filterTimeUntil: "filter[time_until]", filterActive: "filter[active]", + filterFulltext: "filter[fulltext]", // excludeIds needs to stay in camelCase. // This seems to be an inconsistency in the API. excludeIds: "excludeIds", diff --git a/src/lib/requiredParams.ts b/src/lib/requiredParams.ts index 1c93ef73..45bd191f 100644 --- a/src/lib/requiredParams.ts +++ b/src/lib/requiredParams.ts @@ -1,5 +1,6 @@ export const ADD_ABSENCE = ["dateSince", "dateUntil", "type"] as const; export const ADD_CUSTOMER = ["name"] as const; +export const ADD_LUMPSUM_SERVICE = ["name", "price"] as const; export const ADD_TIME_ENTRY = [ "customersId", "servicesId", @@ -30,15 +31,17 @@ export const CHANGE_CLOCK_DURATION = [ "durationBefore", "duration", ] as const; -export const DEACTIVATE_CUSTOMER = ["id"] as const; -export const DEACTIVATE_PROJECT = ["id"] as const; -export const DEACTIVATE_SERVICE = ["id"] as const; -export const DEACTIVATE_USER = ["id"] as const; +export const DELETE_CUSTOMER = ["id"] as const; +export const DELETE_PROJECT = ["id"] as const; +export const DELETE_USER = ["id"] as const; export const DELETE_ENTRY = ["id"] as const; +export const DELETE_SERVICE = ["id"] as const; +export const DELETE_LUMPSUM_SERVICE = ["id"] as const; export const DELETE_ENTRY_GROUP = ["timeSince", "timeUntil"] as const; export const DELETE_ABSENCE = ["id"] as const; export const DELETE_TEAM = ["id"] as const; export const EDIT_CUSTOMER = ["id"] as const; +export const EDIT_LUMPSUM_SERVICE = ["id"] as const; export const EDIT_PROJECT = ["id"] as const; export const EDIT_SERVICE = ["id"] as const; export const EDIT_TEAM = ["id"] as const; @@ -64,9 +67,9 @@ export const GET_TEAM = ["id"] as const; export const GET_USER = ["id"] as const; export const GET_USER_REPORT = ["usersId", "year"] as const; export const GET_USER_REPORTS = ["year"] as const; -export const GET_NONBUSINESS_DAYS = ["nonbusinessgroupsId", "year"] as const; +export const GET_NONBUSINESS_DAYS = ["year"] as const; export const REGISTER = ["companiesName", "name", "email"] as const; -export const START_CLOCK = ["customersId", "servicesId", "billable"] as const; +export const START_CLOCK = ["customersId", "servicesId"] as const; export const STOP_CLOCK = ["entriesId"] as const; export const ADD_WORK_TIMES_CHANGE_REQUEST = [ diff --git a/src/mocks.ts b/src/mocks.ts index c9b9646e..53369e53 100644 --- a/src/mocks.ts +++ b/src/mocks.ts @@ -4,13 +4,16 @@ export * from "./models/absence.mocks.js"; export * from "./models/customer.mocks.js"; export * from "./models/entry.mocks.js"; // export * from "./models/entryGroup.mocks.js"; -// export * from "./models/holidayscarry.mocks.js"; -// export * from "./models/holidaysquota.mocks.js"; +export * from "./models/holidaysCarryover.mocks.js"; +export * from "./models/holidaysQuota.mocks.js"; export * from "./models/lumpsumService.mocks.js"; +export * from "./models/service.mocks.js"; export * from "./models/nonbusinessDay.mocks.js"; +export * from "./models/overtimecarry.mocks.js"; export * from "./models/project.mocks.js"; // export * from "./models/service.mocks.js"; export * from "./models/targethours.mocks.js"; +export * from "./models/team.mocks.js"; export * from "./models/user.mocks.js"; // export * from "./models/userReport.mocks.js"; export * from "./models/worktimeRegulation.mocks.js"; diff --git a/src/models/__snapshots__/nonbusinessDay.mocks.test.ts.snap b/src/models/__snapshots__/nonbusinessDay.mocks.test.ts.snap index e5efac09..09dd0729 100644 --- a/src/models/__snapshots__/nonbusinessDay.mocks.test.ts.snap +++ b/src/models/__snapshots__/nonbusinessDay.mocks.test.ts.snap @@ -7,120 +7,140 @@ Array [ "halfDay": false, "id": 0, "name": "similique libero ad", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-03-24", "halfDay": false, "id": 1, "name": "velit ipsa quidem", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-04-14", "halfDay": false, "id": 2, "name": "perspiciatis cum similique", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-05-05", "halfDay": false, "id": 3, "name": "reprehenderit dolores veritatis", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-05-23", "halfDay": false, "id": 4, "name": "expedita voluptatum vel", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-05-26", "halfDay": false, "id": 5, "name": "magnam illum dignissimos", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-05-30", "halfDay": false, "id": 6, "name": "cum iste corporis", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-06-03", "halfDay": false, "id": 7, "name": "commodi ad animi", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-06-05", "halfDay": false, "id": 8, "name": "voluptas amet consectetur", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-06-25", "halfDay": false, "id": 9, "name": "doloribus similique cumque", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-06-28", "halfDay": false, "id": 10, "name": "quo eum voluptatem", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-07-20", "halfDay": false, "id": 11, "name": "dolores dignissimos quia", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-07-31", "halfDay": false, "id": 12, "name": "inventore quaerat officiis", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-09-07", "halfDay": true, "id": 13, "name": "nobis debitis quidem", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-09-09", "halfDay": false, "id": 14, "name": "laudantium blanditiis quam", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-09-11", "halfDay": false, "id": 15, "name": "excepturi dicta aliquam", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-09-17", "halfDay": true, "id": 16, "name": "ducimus commodi fuga", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-09-20", "halfDay": false, "id": 17, "name": "voluptates non beatae", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-10-12", "halfDay": false, "id": 18, "name": "ducimus doloribus consectetur", + "nonbusinessgroupsId": 0, }, Object { "date": "2020-12-24", "halfDay": false, "id": 19, "name": "iure iste nobis", + "nonbusinessgroupsId": 0, }, ] `; diff --git a/src/models/__snapshots__/targethours.mocks.test.ts.snap b/src/models/__snapshots__/targethours.mocks.test.ts.snap index f12eebce..77a134b4 100644 --- a/src/models/__snapshots__/targethours.mocks.test.ts.snap +++ b/src/models/__snapshots__/targethours.mocks.test.ts.snap @@ -8,6 +8,7 @@ Array [ "dateUntil": "2019-04-30", "id": 0, "monthlyTarget": 48093, + "testData": false, "type": "monthly", "usersId": 0, "workdayFriday": true, @@ -24,6 +25,7 @@ Array [ "dateUntil": "2019-07-31", "id": 1, "monthlyTarget": 44025, + "testData": false, "type": "monthly", "usersId": 0, "workdayFriday": true, @@ -40,6 +42,7 @@ Array [ "dateUntil": "2019-09-30", "id": 2, "monthlyTarget": 65472, + "testData": false, "type": "monthly", "usersId": 0, "workdayFriday": false, @@ -61,6 +64,7 @@ Array [ "monday": 0, "saturday": 4, "sunday": 0, + "testData": false, "thursday": 4.16, "tuesday": 24, "type": "weekly", @@ -78,6 +82,7 @@ Array [ "monday": 24, "saturday": 0, "sunday": 24, + "testData": false, "thursday": 2.74, "tuesday": 3, "type": "weekly", @@ -95,6 +100,7 @@ Array [ "monday": 5.36, "saturday": 0, "sunday": 5.36, + "testData": false, "thursday": 6, "tuesday": 0, "type": "weekly", @@ -112,6 +118,7 @@ Array [ "monday": 6.11, "saturday": 24, "sunday": 6.11, + "testData": false, "thursday": 0, "tuesday": 1, "type": "weekly", @@ -129,6 +136,7 @@ Array [ "monday": 0, "saturday": 24, "sunday": 0, + "testData": false, "thursday": 5.02, "tuesday": 4, "type": "weekly", @@ -146,6 +154,7 @@ Array [ "monday": 1, "saturday": 1.22, "sunday": 1, + "testData": false, "thursday": 0, "tuesday": 0, "type": "weekly", @@ -163,6 +172,7 @@ Array [ "monday": 5, "saturday": 24, "sunday": 5, + "testData": false, "thursday": 2, "tuesday": 0, "type": "weekly", @@ -180,6 +190,7 @@ Array [ "monday": 24, "saturday": 6, "sunday": 24, + "testData": false, "thursday": 0, "tuesday": 2, "type": "weekly", @@ -197,6 +208,7 @@ Array [ "monday": 1.21, "saturday": 0, "sunday": 1.21, + "testData": false, "thursday": 8, "tuesday": 3, "type": "weekly", @@ -214,6 +226,7 @@ Array [ "monday": 24, "saturday": 0, "sunday": 24, + "testData": false, "thursday": 6, "tuesday": 3, "type": "weekly", @@ -231,6 +244,7 @@ Array [ "monday": 24, "saturday": 8, "sunday": 24, + "testData": false, "thursday": 3, "tuesday": 6.84, "type": "weekly", @@ -248,6 +262,7 @@ Array [ "monday": 0, "saturday": 4, "sunday": 0, + "testData": false, "thursday": 2.71, "tuesday": 4, "type": "weekly", @@ -265,6 +280,7 @@ Array [ "monday": 7.25, "saturday": 4, "sunday": 7.25, + "testData": false, "thursday": 24, "tuesday": 7, "type": "weekly", @@ -282,6 +298,7 @@ Array [ "monday": 0, "saturday": 2.06, "sunday": 0, + "testData": false, "thursday": 24, "tuesday": 0, "type": "weekly", @@ -299,6 +316,7 @@ Array [ "monday": 0, "saturday": 24, "sunday": 0, + "testData": false, "thursday": 0, "tuesday": 4, "type": "weekly", @@ -316,6 +334,7 @@ Array [ "monday": 0, "saturday": 24, "sunday": 0, + "testData": false, "thursday": 0, "tuesday": 3.6, "type": "weekly", @@ -333,6 +352,7 @@ Array [ "monday": 24, "saturday": 0, "sunday": 24, + "testData": false, "thursday": 0, "tuesday": 3.66, "type": "weekly", diff --git a/src/models/__snapshots__/workTimes.mocks.test.ts.snap b/src/models/__snapshots__/workTimes.mocks.test.ts.snap index e01bd897..bc55906d 100644 --- a/src/models/__snapshots__/workTimes.mocks.test.ts.snap +++ b/src/models/__snapshots__/workTimes.mocks.test.ts.snap @@ -20,6 +20,7 @@ Array [ "type": 1, }, ], + "createdAt": "2020-03-24T04:00:00Z", "date": "2020-03-24", "id": 0, "status": 1, @@ -43,6 +44,7 @@ Array [ "type": 2, }, ], + "createdAt": "2020-04-14T04:00:00Z", "date": "2020-04-14", "id": 1, "status": 1, @@ -56,6 +58,7 @@ Array [ "type": 2, }, ], + "createdAt": "2020-06-05T04:00:00Z", "date": "2020-06-05", "id": 2, "status": 1, @@ -79,6 +82,7 @@ Array [ "type": 1, }, ], + "createdAt": "2020-09-11T04:00:00Z", "date": "2020-09-11", "id": 3, "status": 1, @@ -97,6 +101,7 @@ Array [ "type": 1, }, ], + "createdAt": "2020-09-17T04:00:00Z", "date": "2020-09-17", "id": 4, "status": 1, diff --git a/src/models/absence.ts b/src/models/absence.ts index 30989d52..18ed7a51 100644 --- a/src/models/absence.ts +++ b/src/models/absence.ts @@ -1,15 +1,17 @@ +import { IsoDate } from "./dateTime.js"; + type CommonAbsence = { /** ID of the absence */ id: number; /** ID of the corresponding co-worker */ usersId: number; /** Start date in YYYY-MM-DD format */ - dateSince: string; + dateSince: IsoDate; /** * End date in YYYY-MM-DD format * Is the same date as dateSince in case the absence is only one day long **/ - dateUntil: string; // | null (as stated in the docs) doesn't seem to be correct + dateUntil: IsoDate; // | null (as stated in the docs) doesn't seem to be correct /** * Status of the absence. */ @@ -27,12 +29,12 @@ type CommonAbsence = { * Date at which the absence request has been enquired in YYYY-MM-DD format. * Only with access rights for absence administration or in case of own absences */ - dateEnquired?: string | null; + dateEnquired?: IsoDate | null; /** * Date at which the absence request has been approved, declined or cancelled in format YYYY-MM-DD. * Only with access rights for absence administration or in case of own absences */ - dateApproved?: string | null; + dateApproved?: IsoDate | null; /** * The ID of the co-worker who has approved, declined or cancelled the request. * Only with access rights for absence administration or in case of own absences diff --git a/src/models/access.ts b/src/models/access.ts index c7f4ac30..0bb4aa45 100644 --- a/src/models/access.ts +++ b/src/models/access.ts @@ -1,5 +1,5 @@ export type AccessToCustomersProjects = - | true + | boolean | Record }>; export type AccessToServices = boolean | Record; diff --git a/src/models/company.ts b/src/models/company.ts index 2088eca1..bd960afb 100644 --- a/src/models/company.ts +++ b/src/models/company.ts @@ -11,6 +11,8 @@ export type Company = { allowEntriesTextMultiline: boolean; /** Can time and lump sum entries be directly assigned to customers (or only to projects)? */ allowEntriesForCustomers: boolean; + /** Are entries of a single user allowed to overlap with each other? */ + allowEntryOverlaps: boolean; /** Does the duration of a time entry have to be equal to the difference between start and end? */ forceLinkedEntryTimes: boolean; /** ID of the default customer */ @@ -21,6 +23,14 @@ export type Company = { moduleAbsence: boolean; /** Is the work-time module active for the company? */ moduleWorkTime: boolean; + /** Is the entries-texts module active for the company? */ + moduleEntriesTexts: boolean; + /** Is the project-times module active for the company? */ + moduleProjectTimes: boolean; + /** Is the target-hours module active for the company? */ + moduleTargetHours: boolean; + /** Is the user-reports module active for the company? */ + moduleUserReports: boolean; /** ID of the default nonbusiness group */ nonbusinessGroupDefault: number | null; /** ID of the default worktime regulation */ @@ -29,8 +39,8 @@ export type Company = { * Date from which worktime regulations are evaluated for the company in YYYY-MM-DD format */ worktimeEvaluateRegulationsSince: string | null; - /** Is missing break time subtracted from the tracked work time? */ - worktimeForceBreaks: boolean; + /** Subtraction of missing break time */ + worktimeForceBreaks: WorktimeForceBreaks; /** Number of days in the default holiday quota of the company */ holidaysCountDefault: number; /** @@ -61,3 +71,18 @@ export type Company = { /** Has the registration process been completed? */ onboardingComplete: boolean; }; + +export enum WorktimeForceBreaks { + /** + * 0: no subtraction + */ + Off = 0, + /** + * 1: full subtraction + */ + Full = 1, + /** + * 2: full subtraction / floating subtraction as of 2022 + */ + Floating = 2, +} diff --git a/src/models/holidaysCarryover.mocks.ts b/src/models/holidaysCarryover.mocks.ts new file mode 100644 index 00000000..e3ca59dc --- /dev/null +++ b/src/models/holidaysCarryover.mocks.ts @@ -0,0 +1,21 @@ +import { faker } from "@faker-js/faker"; +import { HolidaysCarryover } from "./holidaysCarryover.js"; + +type Options = { + count?: number; + yearMinMax?: [number, number]; +}; + +export const createHolidaysCarryoverMocks = ({ + count = 1, + yearMinMax = [1900, 2024], +}: Options = {}) => { + return Array.from({ length: count }, (): HolidaysCarryover => { + return { + usersId: 0, + year: faker.datatype.number({ min: yearMinMax[0], max: yearMinMax[1] }), + note: faker.datatype.boolean() ? faker.lorem.sentences(2) : null, + count: faker.datatype.number({ min: 0, max: 100 }), + }; + }); +}; diff --git a/src/models/holidaysCarryover.ts b/src/models/holidaysCarryover.ts new file mode 100644 index 00000000..8d920571 --- /dev/null +++ b/src/models/holidaysCarryover.ts @@ -0,0 +1,11 @@ +export type HolidaysCarryover = { + /** The related employee's ID */ + usersId: number; + /** + * Year for which the holiday carryover applies + */ + year: number; + /** Day count */ + count: number; + note: string | null; +}; diff --git a/src/models/holidaysQuota.mocks.ts b/src/models/holidaysQuota.mocks.ts new file mode 100644 index 00000000..48ca39a7 --- /dev/null +++ b/src/models/holidaysQuota.mocks.ts @@ -0,0 +1,35 @@ +import { faker } from "@faker-js/faker"; +import { HolidaysQuota } from "./holidaysQuota.js"; + +type Options = { + count?: number; + yearSinceMinMax?: [number, number]; + yearUntilMinMax?: [number, number]; +}; + +export const createHolidaysQuotaMocks = ({ + count = 1, + yearSinceMinMax = [2020, 2021], + yearUntilMinMax = [2021, 2022], +}: Options = {}) => { + return Array.from({ length: count }, (_, index): HolidaysQuota => { + const id = index; + + return { + id, + usersId: 0, + yearSince: faker.datatype.number({ + min: yearSinceMinMax[0], + max: yearSinceMinMax[1], + }), + yearUntil: faker.datatype.boolean() + ? faker.datatype.number({ + min: yearUntilMinMax[0], + max: yearUntilMinMax[1], + }) + : null, + note: faker.datatype.boolean() ? faker.lorem.sentences(2) : null, + count: faker.datatype.number({ min: 0, max: 100 }), + }; + }); +}; diff --git a/src/models/holidaysQuota.ts b/src/models/holidaysQuota.ts new file mode 100644 index 00000000..9c248eb6 --- /dev/null +++ b/src/models/holidaysQuota.ts @@ -0,0 +1,17 @@ +export type HolidaysQuota = { + /** The ID of the holiday quota settings */ + id: number; + /** The related employee's ID */ + usersId: number; + /** + * Year from which on the holiday quota setting apply + */ + yearSince: number; + /** + * Year until which the holiday quota setting apply + */ + yearUntil: number | null; + /** Count of holidays */ + count: number; + note: string | null; +}; diff --git a/src/models/holidayscarry.ts b/src/models/holidayscarry.ts deleted file mode 100644 index 0f8de25c..00000000 --- a/src/models/holidayscarry.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type HolidayscarryRow = { - usersId: number; - year: number; - count: number; - note: string; -}; diff --git a/src/models/holidaysquota.ts b/src/models/holidaysquota.ts deleted file mode 100644 index b52e2c57..00000000 --- a/src/models/holidaysquota.ts +++ /dev/null @@ -1,12 +0,0 @@ -export type HolidaysquotaRow = { - id: number; - usersId: number; - yearSince: number; - yearUntil: number | null; - count: number; -}; - -/** - * @deprecated Please use HolidaysquotaRow type - */ -export type HolidayquotaRow = HolidaysquotaRow; diff --git a/src/models/nonbusinessDay.mocks.ts b/src/models/nonbusinessDay.mocks.ts index 7263f842..d3ecc8ab 100644 --- a/src/models/nonbusinessDay.mocks.ts +++ b/src/models/nonbusinessDay.mocks.ts @@ -9,7 +9,10 @@ const DEFAULT_TO = new Date(2021, 0); export const createNonbusinessDayMocks = ({ count = 1, dateBetween: [from, to] = [DEFAULT_FROM, DEFAULT_TO], -}: { count?: number; dateBetween?: readonly [Date, Date] } = {}) => { +}: { + count?: number; + dateBetween?: readonly [Date, Date]; +}) => { const nextIdPerYear = new Map(); const getNextIdForYear = (year: number) => { @@ -32,6 +35,7 @@ export const createNonbusinessDayMocks = ({ return { date: isoDateFromDateTime(dateTime), id, + nonbusinessgroupsId: 0, name, halfDay: isHalfDay, }; diff --git a/src/models/nonbusinessDay.ts b/src/models/nonbusinessDay.ts index 652106fb..4f844081 100644 --- a/src/models/nonbusinessDay.ts +++ b/src/models/nonbusinessDay.ts @@ -1,8 +1,10 @@ export type NonbusinessDay = { /** The date of the nonbusiness day */ date: string; - /** The ID of the nonbusiness day */ + /** The ID of the nonbusiness day */ id: number; + /** The ID of the corresponding nonbusiness group */ + nonbusinessgroupsId: number; /** The name of the nonbusiness day */ name: string; /** It is half a nonbusiness day */ diff --git a/src/models/overtimecarry.mocks.ts b/src/models/overtimecarry.mocks.ts new file mode 100644 index 00000000..9a749844 --- /dev/null +++ b/src/models/overtimecarry.mocks.ts @@ -0,0 +1,26 @@ +import { faker } from "@faker-js/faker"; +import { OvertimecarryRow } from "./overtimecarry.js"; + +type Options = { + count?: number; + hoursMinMax?: [number, number]; + yearMinMax?: [number, number]; +}; + +export const createOvertimecarryMocks = ({ + count = 1, + hoursMinMax = [0, 100], + yearMinMax = [1900, 2024], +}: Options = {}) => { + return Array.from({ length: count }, (): OvertimecarryRow => { + return { + usersId: 0, + year: faker.datatype.number({ min: yearMinMax[0], max: yearMinMax[1] }), + note: faker.datatype.boolean() ? faker.lorem.sentences(2) : null, + hours: faker.datatype.number({ + min: hoursMinMax[0], + max: hoursMinMax[1], + }), + }; + }); +}; diff --git a/src/models/overtimecarry.ts b/src/models/overtimecarry.ts new file mode 100644 index 00000000..7053c693 --- /dev/null +++ b/src/models/overtimecarry.ts @@ -0,0 +1,12 @@ +export type OvertimecarryRow = { + /** The related employee's ID */ + usersId: number; + /** + * Year for which the overtime carryover applies + * Format YYYY + */ + year: number; + /** Number of hours */ + hours: number; + note: string | null; +}; diff --git a/src/models/service.mocks.ts b/src/models/service.mocks.ts new file mode 100644 index 00000000..0a2528d2 --- /dev/null +++ b/src/models/service.mocks.ts @@ -0,0 +1,16 @@ +import { faker } from "@faker-js/faker"; +import { Service } from "./service.js"; + +export const createServiceMocks = ({ count = 1 }: { count?: number } = {}) => + Array.from({ length: count }, (_, index): Service => { + return { + id: index, + name: faker.commerce.productName(), + number: faker.datatype.hexadecimal(), + active: faker.datatype.boolean(), + note: + index % 2 === 0 + ? null + : faker.lorem.sentences(faker.datatype.number({ min: 1, max: 3 })), + }; + }); diff --git a/src/models/targethours.mocks.ts b/src/models/targethours.mocks.ts index 3b64d2ac..d7ceda99 100644 --- a/src/models/targethours.mocks.ts +++ b/src/models/targethours.mocks.ts @@ -32,6 +32,7 @@ const createCommonTargethoursRowMock = (dateSince: Date) => { dateUntil: null, compensationMonthly: faker.datatype.number({ min: 0, max: 8 }), usersId: 0, + testData: false, }; }; diff --git a/src/models/targethours.ts b/src/models/targethours.ts index dd2dc048..b5b58ff7 100644 --- a/src/models/targethours.ts +++ b/src/models/targethours.ts @@ -22,6 +22,8 @@ type CommonTargethoursRow = { compensationMonthly: number; /** The related employee's ID */ usersId: number; + /** Defines if the Targethoursrow was generated as test data */ + testData: boolean; }; export type TargethoursRowWeekly = CommonTargethoursRow & { diff --git a/src/models/team.mocks.ts b/src/models/team.mocks.ts new file mode 100644 index 00000000..d1a73ed6 --- /dev/null +++ b/src/models/team.mocks.ts @@ -0,0 +1,10 @@ +import { faker } from "@faker-js/faker"; +import { Team } from "./team.js"; + +export const createTeamMocks = ({ count = 1 }: { count?: number }) => + Array.from({ length: count }, (_, index): Team => { + return { + id: index, + name: faker.name.jobArea() + " Team", + }; + }); diff --git a/src/models/workTimes.mocks.ts b/src/models/workTimes.mocks.ts index e9b32320..f0999017 100644 --- a/src/models/workTimes.mocks.ts +++ b/src/models/workTimes.mocks.ts @@ -1,6 +1,7 @@ import { faker } from "@faker-js/faker"; import { isoDateFromDateTime, + isoUtcDateTimeFromDateTime, isoUtcDateTimeFromTimestamp, } from "../lib/dateTime.js"; import { @@ -105,22 +106,26 @@ const createChangeRequest = ({ date, id, status = WorkTimeChangeRequestStatus.Requested, + createdAt, }: { date: Date; id: number; status?: WorkTimeChangeRequestStatus; + createdAt?: Date; }): WorkTimeChangeRequest => { const changes = generateChangeRequestChanges({ count: faker.datatype.number({ min: 1, max: 4 }), date, }); const isoDate = isoDateFromDateTime(date); + const isoCreatedAt = isoUtcDateTimeFromDateTime(createdAt ?? new Date()); return { id, date: isoDate, usersId: 0, changes, + createdAt: isoCreatedAt, ...(status === WorkTimeChangeRequestStatus.Declined ? { status: WorkTimeChangeRequestStatus.Declined, @@ -152,6 +157,7 @@ export const createWorkTimeChangeRequestMocks = ({ return createChangeRequest({ date, id, + createdAt: date, }); }); }; diff --git a/src/models/workTimes.ts b/src/models/workTimes.ts index 549bb07b..d25cffc1 100644 --- a/src/models/workTimes.ts +++ b/src/models/workTimes.ts @@ -21,6 +21,7 @@ export type WorkTimeChangeRequest = { id: number; date: IsoDate; usersId: number; + createdAt: IsoUtcDateTime; changes: Array; } & ( | {