@acorex-platform/module-timesheet-management-client 0.0.32 → 0.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/fesm2022/acorex-platform-module-timesheet-management-client-admin-adjust-timesheet-period.command-8lA7h4rI.mjs.map +1 -1
  2. package/fesm2022/acorex-platform-module-timesheet-management-client-approval-inbox.query-Wyz_jjxb.mjs.map +1 -1
  3. package/fesm2022/acorex-platform-module-timesheet-management-client-approve-timesheet-period.command-DlAeGANo.mjs.map +1 -1
  4. package/fesm2022/acorex-platform-module-timesheet-management-client-compare-attendance-vs-timesheet.query-ZZym5nSx.mjs.map +1 -1
  5. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-time-entry.mjs +369 -0
  6. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-time-entry.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-timesheet-correction.mjs +252 -0
  8. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-timesheet-correction.mjs.map +1 -0
  9. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-timesheet-period.mjs +347 -0
  10. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-timesheet-period.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-timesheet-policy.mjs +281 -0
  12. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-timesheet-policy.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-work-item.mjs +305 -0
  14. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entities-work-item.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-acorex-platform-module-timesheet-management-client-contracts-entity-catalog-BbB3MCCl.mjs +97 -0
  16. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-acorex-platform-module-timesheet-management-client-contracts-entity-catalog-BbB3MCCl.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-time-entry.entity-CAs7zUnV.mjs +295 -0
  18. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-time-entry.entity-CAs7zUnV.mjs.map +1 -0
  19. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-timesheet-correction.entity--wZeCM5Q.mjs +178 -0
  20. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-timesheet-correction.entity--wZeCM5Q.mjs.map +1 -0
  21. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-timesheet-period.entity-BOyfB4YA.mjs +273 -0
  22. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-timesheet-period.entity-BOyfB4YA.mjs.map +1 -0
  23. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-timesheet-policy.entity-CqqN7Xty.mjs +207 -0
  24. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-timesheet-policy.entity-CqqN7Xty.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-work-item.entity-DilF7u50.mjs +231 -0
  26. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog-work-item.entity-DilF7u50.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog.mjs +2 -0
  28. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts-entity-catalog.mjs.map +1 -0
  29. package/fesm2022/acorex-platform-module-timesheet-management-client-contracts.mjs.map +1 -1
  30. package/fesm2022/acorex-platform-module-timesheet-management-client-create-time-entry.command-DS2EVLym.mjs.map +1 -1
  31. package/fesm2022/acorex-platform-module-timesheet-management-client-delete-time-entry.command-5_ItHpnx.mjs.map +1 -1
  32. package/fesm2022/acorex-platform-module-timesheet-management-client-local-entities.mjs +33 -0
  33. package/fesm2022/acorex-platform-module-timesheet-management-client-local-entities.mjs.map +1 -0
  34. package/fesm2022/acorex-platform-module-timesheet-management-client-lock-timesheet-period.command-D7V7SWUK.mjs.map +1 -1
  35. package/fesm2022/acorex-platform-module-timesheet-management-client-my-timesheet-grid.query-DlDY3tdF.mjs.map +1 -1
  36. package/fesm2022/acorex-platform-module-timesheet-management-client-reject-timesheet-period.command-CONxKPNm.mjs.map +1 -1
  37. package/fesm2022/acorex-platform-module-timesheet-management-client-reopen-timesheet-period.command-DRr_c67L.mjs.map +1 -1
  38. package/fesm2022/acorex-platform-module-timesheet-management-client-report-billable-summary.query-BeLk4Of7.mjs.map +1 -1
  39. package/fesm2022/acorex-platform-module-timesheet-management-client-report-hours-by-project.query-Sp8cLnTC.mjs.map +1 -1
  40. package/fesm2022/acorex-platform-module-timesheet-management-client-report-hours-by-work-item.query-C8RU9Uc0.mjs.map +1 -1
  41. package/fesm2022/acorex-platform-module-timesheet-management-client-submit-timesheet-period.command-C2qlQVIC.mjs.map +1 -1
  42. package/fesm2022/acorex-platform-module-timesheet-management-client-team-timesheets.query-B0QpkVEI.mjs.map +1 -1
  43. package/fesm2022/acorex-platform-module-timesheet-management-client-timesheet-validation.service-DMrJn3HU.mjs.map +1 -1
  44. package/fesm2022/acorex-platform-module-timesheet-management-client-update-time-entry.command-Do6s9OrI.mjs.map +1 -1
  45. package/fesm2022/acorex-platform-module-timesheet-management-client-work-item-search.query-BA2kvF-S.mjs.map +1 -1
  46. package/fesm2022/acorex-platform-module-timesheet-management-client-workforce-exception-report.query-0q-AITic.mjs.map +1 -1
  47. package/fesm2022/acorex-platform-module-timesheet-management-client.mjs +1 -1
  48. package/fesm2022/acorex-platform-module-timesheet-management-client.mjs.map +1 -1
  49. package/package.json +29 -1
  50. package/types/acorex-platform-module-timesheet-management-client-contracts-entities-time-entry.d.ts +8 -0
  51. package/types/acorex-platform-module-timesheet-management-client-contracts-entities-timesheet-correction.d.ts +8 -0
  52. package/types/acorex-platform-module-timesheet-management-client-contracts-entities-timesheet-period.d.ts +8 -0
  53. package/types/acorex-platform-module-timesheet-management-client-contracts-entities-timesheet-policy.d.ts +8 -0
  54. package/types/acorex-platform-module-timesheet-management-client-contracts-entities-work-item.d.ts +8 -0
  55. package/types/acorex-platform-module-timesheet-management-client-contracts-entity-catalog.d.ts +10 -0
  56. package/types/acorex-platform-module-timesheet-management-client-local-entities.d.ts +12 -0
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-timesheet-management-client-report-billable-summary.query-BeLk4Of7.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/report-billable-summary.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessObject,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { sumBy } from 'lodash';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMReportBillableSummaryQueryInput {\n employeeId?: string;\n startDate: string;\n endDate: string;\n}\n\nexport interface AXMReportBillableSummaryQueryResult {\n billableSeconds: number;\n nonBillableSeconds: number;\n totalSeconds: number;\n}\n\n//#endregion\n\n/**\n * Summarizes billable vs non-billable hours for a date range.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMReportBillableSummaryQuery\n implements AXPQuery<AXMReportBillableSummaryQueryInput, AXMReportBillableSummaryQueryResult>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input: AXMReportBillableSummaryQueryInput,\n ): AXPQueryFetchResultPromise<AXMReportBillableSummaryQueryResult> {\n try {\n const entryAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timeEntry.name)\n .data<string, AXMTimesheetManagementTimeEntryEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [\n { field: 'entryDate', operator: { type: 'gte' }, value: input.startDate },\n { field: 'entryDate', operator: { type: 'lte' }, value: input.endDate },\n ];\n\n if (input.employeeId) {\n filters.unshift({ field: 'employeeId', operator: { type: 'equal' }, value: input.employeeId });\n }\n\n const result = await entryAccessor.query({\n skip: 0,\n take: 5000,\n filter: { logic: 'and', filters },\n });\n\n const billableSeconds = sumBy(\n result.items.filter((row) => row.isBillable),\n (row) => row.durationSeconds ?? 0,\n );\n const totalSeconds = sumBy(result.items, (row) => row.durationSeconds ?? 0);\n\n return runtimeQuerySuccessObject({\n billableSeconds,\n nonBillableSeconds: totalSeconds - billableSeconds,\n totalSeconds,\n });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to load billable summary report.',\n );\n }\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;;AA4BA;AAEA;;AAEG;MAEU,6BAA6B,CAAA;AAD1C,IAAA,WAAA,GAAA;;AAMmB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAgD1D,IAAA;;;IA1CC,MAAM,KAAK,CACT,KAAyC,EAAA;AAEzC,QAAA,IAAI;AACF,YAAA,MAAM,aAAa,GAAG,IAAI,CAAC;AACxB,iBAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI;AACrE,iBAAA,IAAI,EAAsD;AAE7D,YAAA,MAAM,OAAO,GAA+B;AAC1C,gBAAA,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE;AACzE,gBAAA,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE;aACxE;AAED,YAAA,IAAI,KAAK,CAAC,UAAU,EAAE;gBACpB,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;YAChG;AAEA,YAAA,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC;AACvC,gBAAA,IAAI,EAAE,CAAC;AACP,gBAAA,IAAI,EAAE,IAAI;AACV,gBAAA,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;AAClC,aAAA,CAAC;AAEF,YAAA,MAAM,eAAe,GAAG,KAAK,CAC3B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,UAAU,CAAC,EAC5C,CAAC,GAAG,KAAK,GAAG,CAAC,eAAe,IAAI,CAAC,CAClC;AACD,YAAA,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC;AAE3E,YAAA,OAAO,yBAAyB,CAAC;gBAC/B,eAAe;gBACf,kBAAkB,EAAE,YAAY,GAAG,eAAe;gBAClD,YAAY;AACb,aAAA,CAAC;QACJ;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,mBAAmB,CACxB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,yCAAyC,CACnF;QACH;IACF;8GAlDW,6BAA6B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAA7B,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,6BAA6B,cADhB,MAAM,EAAA,CAAA,CAAA;;2FACnB,6BAA6B,EAAA,UAAA,EAAA,CAAA;kBADzC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;;;"}
1
+ {"version":3,"file":"acorex-platform-module-timesheet-management-client-report-billable-summary.query-BeLk4Of7.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/report-billable-summary.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessObject,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { sumBy } from 'lodash';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMReportBillableSummaryQueryInput {\n employeeId?: string;\n startDate: string;\n endDate: string;\n}\n\nexport interface AXMReportBillableSummaryQueryResult {\n billableSeconds: number;\n nonBillableSeconds: number;\n totalSeconds: number;\n}\n\n//#endregion\n\n/**\n * Summarizes billable vs non-billable hours for a date range.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMReportBillableSummaryQuery\n implements AXPQuery<AXMReportBillableSummaryQueryInput, AXMReportBillableSummaryQueryResult>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input: AXMReportBillableSummaryQueryInput,\n ): AXPQueryFetchResultPromise<AXMReportBillableSummaryQueryResult> {\n try {\n const entryAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timeEntry.name)\n .data<string, AXMTimesheetManagementTimeEntryEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [\n { field: 'entryDate', operator: { type: 'gte' }, value: input.startDate },\n { field: 'entryDate', operator: { type: 'lte' }, value: input.endDate },\n ];\n\n if (input.employeeId) {\n filters.unshift({ field: 'employeeId', operator: { type: 'equal' }, value: input.employeeId });\n }\n\n const result = await entryAccessor.query({\n skip: 0,\n take: 5000,\n filter: { logic: 'and', filters },\n });\n\n const billableSeconds = sumBy(\n result.items.filter((row) => row.isBillable),\n (row) => row.durationSeconds ?? 0,\n );\n const totalSeconds = sumBy(result.items, (row) => row.durationSeconds ?? 0);\n\n return runtimeQuerySuccessObject({\n billableSeconds,\n nonBillableSeconds: totalSeconds - billableSeconds,\n totalSeconds,\n });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to load billable summary report.',\n );\n }\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;;AA4BA;AAEA;;AAEG;MAEU,6BAA6B,CAAA;AAD1C,IAAA,WAAA,GAAA;;AAMmB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAgD1D,IAAA;;;IA1CC,MAAM,KAAK,CACT,KAAyC,EAAA;AAEzC,QAAA,IAAI;AACF,YAAA,MAAM,aAAa,GAAG,IAAI,CAAC;AACxB,iBAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI;AACrE,iBAAA,IAAI,EAAsD;AAE7D,YAAA,MAAM,OAAO,GAA+B;AAC1C,gBAAA,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE;AACzE,gBAAA,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE;aACxE;AAED,YAAA,IAAI,KAAK,CAAC,UAAU,EAAE;gBACpB,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;YAChG;AAEA,YAAA,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC;AACvC,gBAAA,IAAI,EAAE,CAAC;AACP,gBAAA,IAAI,EAAE,IAAI;AACV,gBAAA,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;AAClC,aAAA,CAAC;AAEF,YAAA,MAAM,eAAe,GAAG,KAAK,CAC3B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,UAAU,CAAC,EAC5C,CAAC,GAAG,KAAK,GAAG,CAAC,eAAe,IAAI,CAAC,CAClC;AACD,YAAA,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC;AAE3E,YAAA,OAAO,yBAAyB,CAAC;gBAC/B,eAAe;gBACf,kBAAkB,EAAE,YAAY,GAAG,eAAe;gBAClD,YAAY;AACb,aAAA,CAAC;QACJ;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,mBAAmB,CACxB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,yCAAyC,CACnF;QACH;IACF;8GAlDW,6BAA6B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAA7B,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,6BAA6B,cADhB,MAAM,EAAA,CAAA,CAAA;;2FACnB,6BAA6B,EAAA,UAAA,EAAA,CAAA;kBADzC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-timesheet-management-client-report-hours-by-project.query-Sp8cLnTC.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/report-hours-by-project.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessObject,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { groupBy, sumBy } from 'lodash';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMReportHoursByProjectQueryInput {\n employeeId?: string;\n startDate: string;\n endDate: string;\n}\n\nexport interface AXMReportHoursByProjectRow {\n projectId?: string;\n projectName?: string;\n totalSeconds: number;\n}\n\nexport interface AXMReportHoursByProjectQueryResult {\n rows: AXMReportHoursByProjectRow[];\n totalSeconds: number;\n}\n\n//#endregion\n\n/**\n * Aggregates logged hours by project for a date range.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMReportHoursByProjectQuery\n implements AXPQuery<AXMReportHoursByProjectQueryInput, AXMReportHoursByProjectQueryResult>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input: AXMReportHoursByProjectQueryInput,\n ): AXPQueryFetchResultPromise<AXMReportHoursByProjectQueryResult> {\n try {\n const entries = await this.loadEntries(input);\n const grouped = groupBy(entries, (row) => row.projectId ?? '__none__');\n\n const rows = Object.entries(grouped).map(([key, items]) => {\n const first = items[0];\n return {\n projectId: key === '__none__' ? undefined : key,\n projectName: first?.project?.title,\n totalSeconds: sumBy(items, (row) => row.durationSeconds ?? 0),\n };\n });\n\n return runtimeQuerySuccessObject({\n rows,\n totalSeconds: sumBy(entries, (row) => row.durationSeconds ?? 0),\n });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to load hours by project report.',\n );\n }\n }\n\n //#endregion\n\n //#region ---- Private helpers ----\n\n private async loadEntries(input: AXMReportHoursByProjectQueryInput): Promise<AXMTimesheetManagementTimeEntryEntityModel[]> {\n const entryAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timeEntry.name)\n .data<string, AXMTimesheetManagementTimeEntryEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [\n { field: 'entryDate', operator: { type: 'gte' }, value: input.startDate },\n { field: 'entryDate', operator: { type: 'lte' }, value: input.endDate },\n ];\n\n if (input.employeeId) {\n filters.unshift({ field: 'employeeId', operator: { type: 'equal' }, value: input.employeeId });\n }\n\n const result = await entryAccessor.query({\n skip: 0,\n take: 5000,\n filter: { logic: 'and', filters },\n });\n\n return result.items;\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;;AAiCA;AAEA;;AAEG;MAEU,4BAA4B,CAAA;AADzC,IAAA,WAAA,GAAA;;AAMmB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AA6D1D,IAAA;;;IAvDC,MAAM,KAAK,CACT,KAAwC,EAAA;AAExC,QAAA,IAAI;YACF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAC7C,YAAA,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,SAAS,IAAI,UAAU,CAAC;AAEtE,YAAA,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,KAAI;AACxD,gBAAA,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;gBACtB,OAAO;oBACL,SAAS,EAAE,GAAG,KAAK,UAAU,GAAG,SAAS,GAAG,GAAG;AAC/C,oBAAA,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK;AAClC,oBAAA,YAAY,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC;iBAC9D;AACH,YAAA,CAAC,CAAC;AAEF,YAAA,OAAO,yBAAyB,CAAC;gBAC/B,IAAI;AACJ,gBAAA,YAAY,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC;AAChE,aAAA,CAAC;QACJ;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,mBAAmB,CACxB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,yCAAyC,CACnF;QACH;IACF;;;IAMQ,MAAM,WAAW,CAAC,KAAwC,EAAA;AAChE,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC;AACxB,aAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI;AACrE,aAAA,IAAI,EAAsD;AAE7D,QAAA,MAAM,OAAO,GAA+B;AAC1C,YAAA,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE;AACzE,YAAA,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE;SACxE;AAED,QAAA,IAAI,KAAK,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;QAChG;AAEA,QAAA,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC;AACvC,YAAA,IAAI,EAAE,CAAC;AACP,YAAA,IAAI,EAAE,IAAI;AACV,YAAA,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;AAClC,SAAA,CAAC;QAEF,OAAO,MAAM,CAAC,KAAK;IACrB;8GA/DW,4BAA4B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAA5B,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,4BAA4B,cADf,MAAM,EAAA,CAAA,CAAA;;2FACnB,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBADxC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;;;"}
1
+ {"version":3,"file":"acorex-platform-module-timesheet-management-client-report-hours-by-project.query-Sp8cLnTC.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/report-hours-by-project.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessObject,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { groupBy, sumBy } from 'lodash';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMReportHoursByProjectQueryInput {\n employeeId?: string;\n startDate: string;\n endDate: string;\n}\n\nexport interface AXMReportHoursByProjectRow {\n projectId?: string;\n projectName?: string;\n totalSeconds: number;\n}\n\nexport interface AXMReportHoursByProjectQueryResult {\n rows: AXMReportHoursByProjectRow[];\n totalSeconds: number;\n}\n\n//#endregion\n\n/**\n * Aggregates logged hours by project for a date range.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMReportHoursByProjectQuery\n implements AXPQuery<AXMReportHoursByProjectQueryInput, AXMReportHoursByProjectQueryResult>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input: AXMReportHoursByProjectQueryInput,\n ): AXPQueryFetchResultPromise<AXMReportHoursByProjectQueryResult> {\n try {\n const entries = await this.loadEntries(input);\n const grouped = groupBy(entries, (row) => row.projectId ?? '__none__');\n\n const rows = Object.entries(grouped).map(([key, items]) => {\n const first = items[0];\n return {\n projectId: key === '__none__' ? undefined : key,\n projectName: first?.project?.title,\n totalSeconds: sumBy(items, (row) => row.durationSeconds ?? 0),\n };\n });\n\n return runtimeQuerySuccessObject({\n rows,\n totalSeconds: sumBy(entries, (row) => row.durationSeconds ?? 0),\n });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to load hours by project report.',\n );\n }\n }\n\n //#endregion\n\n //#region ---- Private helpers ----\n\n private async loadEntries(input: AXMReportHoursByProjectQueryInput): Promise<AXMTimesheetManagementTimeEntryEntityModel[]> {\n const entryAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timeEntry.name)\n .data<string, AXMTimesheetManagementTimeEntryEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [\n { field: 'entryDate', operator: { type: 'gte' }, value: input.startDate },\n { field: 'entryDate', operator: { type: 'lte' }, value: input.endDate },\n ];\n\n if (input.employeeId) {\n filters.unshift({ field: 'employeeId', operator: { type: 'equal' }, value: input.employeeId });\n }\n\n const result = await entryAccessor.query({\n skip: 0,\n take: 5000,\n filter: { logic: 'and', filters },\n });\n\n return result.items;\n }\n\n //#endregion\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-timesheet-management-client-report-hours-by-work-item.query-C8RU9Uc0.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/report-hours-by-work-item.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessObject,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { groupBy, sumBy } from 'lodash';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMReportHoursByWorkItemQueryInput {\n employeeId?: string;\n startDate: string;\n endDate: string;\n}\n\nexport interface AXMReportHoursByWorkItemRow {\n workItemId: string;\n workItemCode?: string;\n workItemTitle?: string;\n totalSeconds: number;\n}\n\nexport interface AXMReportHoursByWorkItemQueryResult {\n rows: AXMReportHoursByWorkItemRow[];\n totalSeconds: number;\n}\n\n//#endregion\n\n/**\n * Aggregates logged hours by work item for a date range.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMReportHoursByWorkItemQuery\n implements AXPQuery<AXMReportHoursByWorkItemQueryInput, AXMReportHoursByWorkItemQueryResult>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input: AXMReportHoursByWorkItemQueryInput,\n ): AXPQueryFetchResultPromise<AXMReportHoursByWorkItemQueryResult> {\n try {\n const entries = await this.loadEntries(input);\n const grouped = groupBy(entries, (row) => row.workItemId);\n\n const rows = Object.entries(grouped).map(([workItemId, items]) => {\n const first = items[0];\n return {\n workItemId,\n workItemCode: first?.workItem?.code ?? first?.workItemSnapshot?.title,\n workItemTitle: first?.workItemSnapshot?.title ?? first?.workItem?.title,\n totalSeconds: sumBy(items, (row) => row.durationSeconds ?? 0),\n };\n });\n\n return runtimeQuerySuccessObject({\n rows,\n totalSeconds: sumBy(entries, (row) => row.durationSeconds ?? 0),\n });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to load hours by work item report.',\n );\n }\n }\n\n //#endregion\n\n //#region ---- Private helpers ----\n\n private async loadEntries(input: AXMReportHoursByWorkItemQueryInput): Promise<AXMTimesheetManagementTimeEntryEntityModel[]> {\n const entryAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timeEntry.name)\n .data<string, AXMTimesheetManagementTimeEntryEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [\n { field: 'entryDate', operator: { type: 'gte' }, value: input.startDate },\n { field: 'entryDate', operator: { type: 'lte' }, value: input.endDate },\n ];\n\n if (input.employeeId) {\n filters.unshift({ field: 'employeeId', operator: { type: 'equal' }, value: input.employeeId });\n }\n\n const result = await entryAccessor.query({\n skip: 0,\n take: 5000,\n filter: { logic: 'and', filters },\n });\n\n return result.items;\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;;AAkCA;AAEA;;AAEG;MAEU,6BAA6B,CAAA;AAD1C,IAAA,WAAA,GAAA;;AAMmB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AA8D1D,IAAA;;;IAxDC,MAAM,KAAK,CACT,KAAyC,EAAA;AAEzC,QAAA,IAAI;YACF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAC7C,YAAA,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,UAAU,CAAC;AAEzD,YAAA,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,KAAI;AAC/D,gBAAA,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;gBACtB,OAAO;oBACL,UAAU;oBACV,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,IAAI,KAAK,EAAE,gBAAgB,EAAE,KAAK;oBACrE,aAAa,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,IAAI,KAAK,EAAE,QAAQ,EAAE,KAAK;AACvE,oBAAA,YAAY,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC;iBAC9D;AACH,YAAA,CAAC,CAAC;AAEF,YAAA,OAAO,yBAAyB,CAAC;gBAC/B,IAAI;AACJ,gBAAA,YAAY,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC;AAChE,aAAA,CAAC;QACJ;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,mBAAmB,CACxB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,2CAA2C,CACrF;QACH;IACF;;;IAMQ,MAAM,WAAW,CAAC,KAAyC,EAAA;AACjE,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC;AACxB,aAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI;AACrE,aAAA,IAAI,EAAsD;AAE7D,QAAA,MAAM,OAAO,GAA+B;AAC1C,YAAA,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE;AACzE,YAAA,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE;SACxE;AAED,QAAA,IAAI,KAAK,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;QAChG;AAEA,QAAA,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC;AACvC,YAAA,IAAI,EAAE,CAAC;AACP,YAAA,IAAI,EAAE,IAAI;AACV,YAAA,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;AAClC,SAAA,CAAC;QAEF,OAAO,MAAM,CAAC,KAAK;IACrB;8GAhEW,6BAA6B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAA7B,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,6BAA6B,cADhB,MAAM,EAAA,CAAA,CAAA;;2FACnB,6BAA6B,EAAA,UAAA,EAAA,CAAA;kBADzC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;;;"}
1
+ {"version":3,"file":"acorex-platform-module-timesheet-management-client-report-hours-by-work-item.query-C8RU9Uc0.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/report-hours-by-work-item.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessObject,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { groupBy, sumBy } from 'lodash';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMReportHoursByWorkItemQueryInput {\n employeeId?: string;\n startDate: string;\n endDate: string;\n}\n\nexport interface AXMReportHoursByWorkItemRow {\n workItemId: string;\n workItemCode?: string;\n workItemTitle?: string;\n totalSeconds: number;\n}\n\nexport interface AXMReportHoursByWorkItemQueryResult {\n rows: AXMReportHoursByWorkItemRow[];\n totalSeconds: number;\n}\n\n//#endregion\n\n/**\n * Aggregates logged hours by work item for a date range.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMReportHoursByWorkItemQuery\n implements AXPQuery<AXMReportHoursByWorkItemQueryInput, AXMReportHoursByWorkItemQueryResult>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input: AXMReportHoursByWorkItemQueryInput,\n ): AXPQueryFetchResultPromise<AXMReportHoursByWorkItemQueryResult> {\n try {\n const entries = await this.loadEntries(input);\n const grouped = groupBy(entries, (row) => row.workItemId);\n\n const rows = Object.entries(grouped).map(([workItemId, items]) => {\n const first = items[0];\n return {\n workItemId,\n workItemCode: first?.workItem?.code ?? first?.workItemSnapshot?.title,\n workItemTitle: first?.workItemSnapshot?.title ?? first?.workItem?.title,\n totalSeconds: sumBy(items, (row) => row.durationSeconds ?? 0),\n };\n });\n\n return runtimeQuerySuccessObject({\n rows,\n totalSeconds: sumBy(entries, (row) => row.durationSeconds ?? 0),\n });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to load hours by work item report.',\n );\n }\n }\n\n //#endregion\n\n //#region ---- Private helpers ----\n\n private async loadEntries(input: AXMReportHoursByWorkItemQueryInput): Promise<AXMTimesheetManagementTimeEntryEntityModel[]> {\n const entryAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timeEntry.name)\n .data<string, AXMTimesheetManagementTimeEntryEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [\n { field: 'entryDate', operator: { type: 'gte' }, value: input.startDate },\n { field: 'entryDate', operator: { type: 'lte' }, value: input.endDate },\n ];\n\n if (input.employeeId) {\n filters.unshift({ field: 'employeeId', operator: { type: 'equal' }, value: input.employeeId });\n }\n\n const result = await entryAccessor.query({\n skip: 0,\n take: 5000,\n filter: { logic: 'and', filters },\n });\n\n return result.items;\n }\n\n //#endregion\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-timesheet-management-client-submit-timesheet-period.command-C2qlQVIC.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/timesheet-period/commands/submit-timesheet-period.command.ts"],"sourcesContent":["\n\nimport { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport { AXPRuntimeCommandResult, AXPSystemStatusType } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimesheetPeriodEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport { AXMTimesheetValidationService } from '../timesheet-validation.service';\n\n//#region ---- Types ----\n\nexport interface SubmitTimesheetPeriodInput {\n id: string;\n}\n\n//#endregion\n\n/**\n * Submits a draft timesheet period for approval.\n */\n@Injectable({ providedIn: 'root' })\nexport class SubmitTimesheetPeriodCommand implements AXPCommand<SubmitTimesheetPeriodInput, void> {\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n private readonly validationService = inject(AXMTimesheetValidationService);\n\n //#endregion\n\n //#region ---- Command Implementation ----\n\n async execute(input: SubmitTimesheetPeriodInput): AXPCommandExecuteResultPromise<void> {\n try {\n const dataAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timesheetPeriod.name)\n .data<string, AXMTimesheetManagementTimesheetPeriodEntityModel>();\n\n const period = await dataAccessor.byKey(input.id);\n if (!period) {\n return { success: false, message: { text: 'Timesheet period not found.' } };\n }\n\n this.validationService.assertCanSubmit(period);\n\n await dataAccessor.update(input.id, {\n statusId: AXPSystemStatusType.WaitingApproval,\n submittedAt: new Date().toISOString(),\n });\n\n return { success: true, kind: 'object', data: undefined };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Failed to submit timesheet period.';\n console.error('[SubmitTimesheetPeriodCommand] Error:', error);\n return { success: false, message: { text: message } };\n }\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;;AAiBA;AAEA;;AAEG;MAEU,4BAA4B,CAAA;AADzC,IAAA,WAAA,GAAA;;AAImB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACxC,QAAA,IAAA,CAAA,iBAAiB,GAAG,MAAM,CAAC,6BAA6B,CAAC;AAiC3E,IAAA;;;IA3BC,MAAM,OAAO,CAAC,KAAiC,EAAA;AAC7C,QAAA,IAAI;AACF,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC;AACvB,iBAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI;AAC3E,iBAAA,IAAI,EAA4D;YAEnE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC,MAAM,EAAE;AACX,gBAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,6BAA6B,EAAE,EAAE;YAC7E;AAEA,YAAA,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,MAAM,CAAC;AAE9C,YAAA,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE;gBAClC,QAAQ,EAAE,mBAAmB,CAAC,eAAe;AAC7C,gBAAA,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AACtC,aAAA,CAAC;AAEF,YAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE;QAC3D;QAAE,OAAO,KAAc,EAAE;AACvB,YAAA,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,oCAAoC;AAC7F,YAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC;AAC7D,YAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QACvD;IACF;8GAlCW,4BAA4B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAA5B,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,4BAA4B,cADf,MAAM,EAAA,CAAA,CAAA;;2FACnB,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBADxC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;;;"}
1
+ {"version":3,"file":"acorex-platform-module-timesheet-management-client-submit-timesheet-period.command-C2qlQVIC.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/timesheet-period/commands/submit-timesheet-period.command.ts"],"sourcesContent":["\n\nimport { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport { AXPRuntimeCommandResult, AXPSystemStatusType } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimesheetPeriodEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport { AXMTimesheetValidationService } from '../timesheet-validation.service';\n\n//#region ---- Types ----\n\nexport interface SubmitTimesheetPeriodInput {\n id: string;\n}\n\n//#endregion\n\n/**\n * Submits a draft timesheet period for approval.\n */\n@Injectable({ providedIn: 'root' })\nexport class SubmitTimesheetPeriodCommand implements AXPCommand<SubmitTimesheetPeriodInput, void> {\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n private readonly validationService = inject(AXMTimesheetValidationService);\n\n //#endregion\n\n //#region ---- Command Implementation ----\n\n async execute(input: SubmitTimesheetPeriodInput): AXPCommandExecuteResultPromise<void> {\n try {\n const dataAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timesheetPeriod.name)\n .data<string, AXMTimesheetManagementTimesheetPeriodEntityModel>();\n\n const period = await dataAccessor.byKey(input.id);\n if (!period) {\n return { success: false, message: { text: 'Timesheet period not found.' } };\n }\n\n this.validationService.assertCanSubmit(period);\n\n await dataAccessor.update(input.id, {\n statusId: AXPSystemStatusType.WaitingApproval,\n submittedAt: new Date().toISOString(),\n });\n\n return { success: true, kind: 'object', data: undefined };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Failed to submit timesheet period.';\n console.error('[SubmitTimesheetPeriodCommand] Error:', error);\n return { success: false, message: { text: message } };\n }\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;;AAiBA;AAEA;;AAEG;MAEU,4BAA4B,CAAA;AADzC,IAAA,WAAA,GAAA;;AAImB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACxC,QAAA,IAAA,CAAA,iBAAiB,GAAG,MAAM,CAAC,6BAA6B,CAAC;AAiC3E,IAAA;;;IA3BC,MAAM,OAAO,CAAC,KAAiC,EAAA;AAC7C,QAAA,IAAI;AACF,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC;AACvB,iBAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI;AAC3E,iBAAA,IAAI,EAA4D;YAEnE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC,MAAM,EAAE;AACX,gBAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,6BAA6B,EAAE,EAAE;YAC7E;AAEA,YAAA,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,MAAM,CAAC;AAE9C,YAAA,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE;gBAClC,QAAQ,EAAE,mBAAmB,CAAC,eAAe;AAC7C,gBAAA,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AACtC,aAAA,CAAC;AAEF,YAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE;QAC3D;QAAE,OAAO,KAAc,EAAE;AACvB,YAAA,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,oCAAoC;AAC7F,YAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC;AAC7D,YAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QACvD;IACF;8GAlCW,4BAA4B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAA5B,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,4BAA4B,cADf,MAAM,EAAA,CAAA,CAAA;;2FACnB,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBADxC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-timesheet-management-client-team-timesheets.query-B0QpkVEI.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/team-timesheets.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessCollection,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimesheetPeriodEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMTeamTimesheetsQueryInput {\n managerEmployeeId?: string;\n statusId?: string;\n skip?: number;\n take?: number;\n}\n\n//#endregion\n\n/**\n * Lists timesheet periods for direct reports or team members.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMTeamTimesheetsQuery\n implements AXPQuery<AXMTeamTimesheetsQueryInput, AXMTimesheetManagementTimesheetPeriodEntityModel>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input?: AXMTeamTimesheetsQueryInput | null,\n ): AXPQueryFetchResultPromise<AXMTimesheetManagementTimesheetPeriodEntityModel> {\n try {\n const opts = input ?? {};\n const periodAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timesheetPeriod.name)\n .data<string, AXMTimesheetManagementTimesheetPeriodEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [];\n if (opts.statusId) {\n filters.push({ field: 'statusId', operator: { type: 'equal' }, value: opts.statusId });\n }\n\n const result = await periodAccessor.query({\n skip: opts.skip ?? 0,\n take: opts.take ?? 50,\n sort: [{ field: 'startDate', dir: 'desc' }],\n ...(filters.length\n ? { filter: { logic: 'and', filters } }\n : {}),\n });\n\n return runtimeQuerySuccessCollection({ items: result.items, total: result.total });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to load team timesheets.',\n );\n }\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;AAsBA;AAEA;;AAEG;MAEU,sBAAsB,CAAA;AADnC,IAAA,WAAA,GAAA;;AAMmB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAsC1D,IAAA;;;IAhCC,MAAM,KAAK,CACT,KAA0C,EAAA;AAE1C,QAAA,IAAI;AACF,YAAA,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;AACxB,YAAA,MAAM,cAAc,GAAG,IAAI,CAAC;AACzB,iBAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI;AAC3E,iBAAA,IAAI,EAA4D;YAEnE,MAAM,OAAO,GAA+B,EAAE;AAC9C,YAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACjB,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxF;AAEA,YAAA,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC;AACxC,gBAAA,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;AACpB,gBAAA,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;gBACrB,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;gBAC3C,IAAI,OAAO,CAAC;sBACR,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;sBACnC,EAAE,CAAC;AACR,aAAA,CAAC;AAEF,YAAA,OAAO,6BAA6B,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QACpF;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,mBAAmB,CACxB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,iCAAiC,CAC3E;QACH;IACF;8GAxCW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAtB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,sBAAsB,cADT,MAAM,EAAA,CAAA,CAAA;;2FACnB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;;;"}
1
+ {"version":3,"file":"acorex-platform-module-timesheet-management-client-team-timesheets.query-B0QpkVEI.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/team-timesheets.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessCollection,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimesheetPeriodEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMTeamTimesheetsQueryInput {\n managerEmployeeId?: string;\n statusId?: string;\n skip?: number;\n take?: number;\n}\n\n//#endregion\n\n/**\n * Lists timesheet periods for direct reports or team members.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMTeamTimesheetsQuery\n implements AXPQuery<AXMTeamTimesheetsQueryInput, AXMTimesheetManagementTimesheetPeriodEntityModel>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input?: AXMTeamTimesheetsQueryInput | null,\n ): AXPQueryFetchResultPromise<AXMTimesheetManagementTimesheetPeriodEntityModel> {\n try {\n const opts = input ?? {};\n const periodAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timesheetPeriod.name)\n .data<string, AXMTimesheetManagementTimesheetPeriodEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [];\n if (opts.statusId) {\n filters.push({ field: 'statusId', operator: { type: 'equal' }, value: opts.statusId });\n }\n\n const result = await periodAccessor.query({\n skip: opts.skip ?? 0,\n take: opts.take ?? 50,\n sort: [{ field: 'startDate', dir: 'desc' }],\n ...(filters.length\n ? { filter: { logic: 'and', filters } }\n : {}),\n });\n\n return runtimeQuerySuccessCollection({ items: result.items, total: result.total });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to load team timesheets.',\n );\n }\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;AAsBA;AAEA;;AAEG;MAEU,sBAAsB,CAAA;AADnC,IAAA,WAAA,GAAA;;AAMmB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAsC1D,IAAA;;;IAhCC,MAAM,KAAK,CACT,KAA0C,EAAA;AAE1C,QAAA,IAAI;AACF,YAAA,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;AACxB,YAAA,MAAM,cAAc,GAAG,IAAI,CAAC;AACzB,iBAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI;AAC3E,iBAAA,IAAI,EAA4D;YAEnE,MAAM,OAAO,GAA+B,EAAE;AAC9C,YAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACjB,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxF;AAEA,YAAA,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC;AACxC,gBAAA,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;AACpB,gBAAA,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;gBACrB,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;gBAC3C,IAAI,OAAO,CAAC;sBACR,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;sBACnC,EAAE,CAAC;AACR,aAAA,CAAC;AAEF,YAAA,OAAO,6BAA6B,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QACpF;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,mBAAmB,CACxB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,iCAAiC,CAC3E;QACH;IACF;8GAxCW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAtB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,sBAAsB,cADT,MAAM,EAAA,CAAA,CAAA;;2FACnB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-timesheet-management-client-timesheet-validation.service-DMrJn3HU.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/timesheet-period/timesheet-validation.service.ts"],"sourcesContent":["//#region ---- Imports ----\n\nimport { AXPSystemStatusType } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\nimport { inject, Injectable } from '@angular/core';\nimport { defaultTo, get, isEmpty, isNil } from 'lodash';\nimport {\n AXMTimesheetPeriodLockedStatusIds,\n AXMTimesheetPeriodOpenStatusIds,\n RootConfig,\n} from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type {\n AXMTimesheetManagementTimesheetPeriodEntityModel,\n AXMTimesheetPeriodType,\n} from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimesheetPolicyEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#endregion\n\n//#region ---- Types ----\n\nexport interface AXMTimesheetValidationIssue {\n code: string;\n message: string;\n field?: string;\n}\n\nexport interface AXMTimesheetValidationResult {\n valid: boolean;\n issues: AXMTimesheetValidationIssue[];\n}\n\nexport interface AXMTimesheetGetOrCreateDraftPeriodInput {\n employeeId: string;\n periodType: AXMTimesheetPeriodType;\n startDate: string;\n endDate: string;\n timezone: string;\n}\n\n//#endregion\n\n//#region ---- Timesheet Validation Service ----\n\n/**\n * Domain validation service for timesheet period and time entry business rules.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMTimesheetValidationService {\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Entry Validation ----\n\n /**\n * Validates that a time entry date falls within policy and period constraints.\n */\n validateEntryDates(\n entry: Pick<AXMTimesheetManagementTimeEntryEntityModel, 'entryDate' | 'startedAt' | 'endedAt'>,\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'startDate' | 'endDate'>,\n policy?: Pick<AXMTimesheetManagementTimesheetPolicyEntityModel, 'allowFutureDates'>,\n ): AXMTimesheetValidationResult {\n const issues: AXMTimesheetValidationIssue[] = [];\n const entryDate = entry.entryDate?.slice(0, 10);\n const periodStart = period.startDate?.slice(0, 10);\n const periodEnd = period.endDate?.slice(0, 10);\n\n if (entryDate && periodStart && entryDate < periodStart) {\n issues.push({\n code: 'entry-before-period',\n field: 'entryDate',\n message: 'Entry date is before the period start date.',\n });\n }\n\n if (entryDate && periodEnd && entryDate > periodEnd) {\n issues.push({\n code: 'entry-after-period',\n field: 'entryDate',\n message: 'Entry date is after the period end date.',\n });\n }\n\n if (!defaultTo(policy?.allowFutureDates, false)) {\n const today = new Date().toISOString().slice(0, 10);\n if (entryDate && entryDate > today) {\n issues.push({\n code: 'future-entry-date',\n field: 'entryDate',\n message: 'Future entry dates are not allowed by the active policy.',\n });\n }\n }\n\n if (entry.startedAt && entry.endedAt) {\n const started = Date.parse(entry.startedAt);\n const ended = Date.parse(entry.endedAt);\n if (!Number.isNaN(started) && !Number.isNaN(ended) && ended < started) {\n issues.push({\n code: 'ended-before-started',\n field: 'endedAt',\n message: 'End time must be after start time.',\n });\n }\n }\n\n return { valid: isEmpty(issues), issues };\n }\n\n /**\n * Validates that a time entry does not overlap existing entries for the same employee.\n */\n validateNoOverlap(\n entry: Pick<AXMTimesheetManagementTimeEntryEntityModel, 'id' | 'employeeId' | 'startedAt' | 'endedAt'>,\n existingEntries: Array<Pick<AXMTimesheetManagementTimeEntryEntityModel, 'id' | 'employeeId' | 'startedAt' | 'endedAt'>>,\n policy?: Pick<AXMTimesheetManagementTimesheetPolicyEntityModel, 'overlapPolicy'>,\n ): AXMTimesheetValidationResult {\n const issues: AXMTimesheetValidationIssue[] = [];\n const overlapPolicy = defaultTo(policy?.overlapPolicy, 'reject');\n\n if (!entry.startedAt || !entry.endedAt) {\n return { valid: true, issues };\n }\n\n const start = Date.parse(entry.startedAt);\n const end = Date.parse(entry.endedAt);\n if (Number.isNaN(start) || Number.isNaN(end)) {\n return { valid: true, issues };\n }\n\n const overlapping = existingEntries.filter((candidate) => {\n if (candidate.id === entry.id || candidate.employeeId !== entry.employeeId) {\n return false;\n }\n if (!candidate.startedAt || !candidate.endedAt) {\n return false;\n }\n const candidateStart = Date.parse(candidate.startedAt);\n const candidateEnd = Date.parse(candidate.endedAt);\n if (Number.isNaN(candidateStart) || Number.isNaN(candidateEnd)) {\n return false;\n }\n return start < candidateEnd && end > candidateStart;\n });\n\n if (!isEmpty(overlapping)) {\n issues.push({\n code: overlapPolicy === 'warn' ? 'entry-overlap-warning' : 'entry-overlap',\n field: 'startedAt',\n message:\n overlapPolicy === 'warn'\n ? 'This entry overlaps another entry for the same employee.'\n : 'Overlapping time entries are not allowed.',\n });\n }\n\n return {\n valid: overlapPolicy === 'warn' ? true : isEmpty(issues),\n issues,\n };\n }\n\n //#endregion\n\n //#region ---- Period Validation ----\n\n /**\n * Validates that a timesheet period can still be edited.\n */\n validatePeriodEditable(\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>,\n ): AXMTimesheetValidationResult {\n const statusId = period.statusId;\n const isLocked = (AXMTimesheetPeriodLockedStatusIds as readonly string[]).includes(statusId);\n\n if (isLocked) {\n return {\n valid: false,\n issues: [\n {\n code: 'period-locked',\n field: 'statusId',\n message: 'This timesheet period is locked and cannot be edited.',\n },\n ],\n };\n }\n\n return { valid: true, issues: [] };\n }\n\n /**\n * Validates that a period is complete enough for submission.\n */\n validateSubmissionCompleteness(\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId' | 'totalSeconds'>,\n entries: Array<Pick<AXMTimesheetManagementTimeEntryEntityModel, 'description'>>,\n policy?: Pick<AXMTimesheetManagementTimesheetPolicyEntityModel, 'requireDescription'>,\n ): AXMTimesheetValidationResult {\n const issues: AXMTimesheetValidationIssue[] = [];\n\n if (period.statusId !== AXPSystemStatusType.Draft) {\n issues.push({\n code: 'period-not-draft',\n field: 'statusId',\n message: 'Only draft periods can be submitted.',\n });\n }\n\n if (isEmpty(entries)) {\n issues.push({\n code: 'no-entries',\n message: 'At least one time entry is required before submission.',\n });\n }\n\n if (defaultTo(policy?.requireDescription, false)) {\n const missingDescription = entries.some((entry) => isEmpty(get(entry, 'description')));\n if (missingDescription) {\n issues.push({\n code: 'missing-description',\n field: 'description',\n message: 'All time entries must include a description before submission.',\n });\n }\n }\n\n const totalSeconds = defaultTo(period.totalSeconds, 0);\n if (totalSeconds <= 0 && !isEmpty(entries)) {\n issues.push({\n code: 'zero-total',\n field: 'totalSeconds',\n message: 'Submitted periods must have a positive total duration.',\n });\n }\n\n return { valid: isEmpty(issues), issues };\n }\n\n //#endregion\n\n //#region ---- Assertion Helpers ----\n\n assertPeriodAllowsTimeEntryEdits(\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>,\n ): void {\n const result = this.validatePeriodEditable(period);\n if (!result.valid) {\n throw new Error(result.issues[0]?.message ?? 'This timesheet period cannot be edited.');\n }\n }\n\n assertCanSubmit(\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId' | 'totalSeconds'>,\n entries: Array<Pick<AXMTimesheetManagementTimeEntryEntityModel, 'description'>> = [],\n policy?: Pick<AXMTimesheetManagementTimesheetPolicyEntityModel, 'requireDescription'>,\n ): void {\n const result = this.validateSubmissionCompleteness(period, entries, policy);\n if (!result.valid) {\n throw new Error(result.issues[0]?.message ?? 'Timesheet period cannot be submitted.');\n }\n }\n\n assertCanApprove(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n if (period.statusId !== AXPSystemStatusType.WaitingApproval) {\n throw new Error('Only submitted periods can be approved.');\n }\n }\n\n assertCanReject(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n if (period.statusId !== AXPSystemStatusType.WaitingApproval) {\n throw new Error('Only submitted periods can be rejected.');\n }\n }\n\n assertCanReopen(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n if (period.statusId !== AXPSystemStatusType.Rejected) {\n throw new Error('Only rejected periods can be reopened.');\n }\n }\n\n assertCanLock(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n if (period.statusId !== AXPSystemStatusType.Approved) {\n throw new Error('Only approved periods can be locked.');\n }\n }\n\n assertCanAdminAdjust(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n const isLocked = (AXMTimesheetPeriodLockedStatusIds as readonly string[]).includes(period.statusId);\n if (!isLocked && period.statusId !== AXPSystemStatusType.Approved) {\n throw new Error('Only approved or locked periods can be adjusted by an administrator.');\n }\n }\n\n //#endregion\n\n //#region ---- Period Resolution ----\n\n /**\n * Finds an existing open draft period or creates a new draft period for the employee.\n */\n async getOrCreateDraftPeriod(\n input: AXMTimesheetGetOrCreateDraftPeriodInput,\n ): Promise<AXMTimesheetManagementTimesheetPeriodEntityModel> {\n const periodAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timesheetPeriod.name)\n .data<string, AXMTimesheetManagementTimesheetPeriodEntityModel>();\n\n const existing = await periodAccessor.query({\n skip: 0,\n take: 1,\n filter: {\n logic: 'and',\n filters: [\n { field: 'employeeId', operator: { type: 'equal' }, value: input.employeeId },\n { field: 'periodType', operator: { type: 'equal' }, value: input.periodType },\n { field: 'startDate', operator: { type: 'equal' }, value: input.startDate },\n { field: 'endDate', operator: { type: 'equal' }, value: input.endDate },\n {\n field: 'statusId',\n operator: { type: 'in' },\n value: [...AXMTimesheetPeriodOpenStatusIds],\n },\n ],\n },\n });\n\n const match = get(existing, 'items[0]') as AXMTimesheetManagementTimesheetPeriodEntityModel | undefined;\n if (!isNil(match)) {\n return match;\n }\n\n const createdId = await periodAccessor.create({\n employeeId: input.employeeId,\n periodType: input.periodType,\n startDate: input.startDate,\n endDate: input.endDate,\n timezone: input.timezone,\n statusId: AXPSystemStatusType.Draft,\n totalSeconds: 0,\n });\n\n const created = await periodAccessor.byKey(createdId);\n if (isNil(created)) {\n throw new Error('Failed to load the newly created draft timesheet period.');\n }\n\n return created;\n }\n\n //#endregion\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"acorex-platform-module-timesheet-management-client-timesheet-validation.service-DMrJn3HU.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/timesheet-period/timesheet-validation.service.ts"],"sourcesContent":["//#region ---- Imports ----\n\nimport { AXPSystemStatusType } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\nimport { inject, Injectable } from '@angular/core';\nimport { defaultTo, get, isEmpty, isNil } from 'lodash';\nimport {\n AXMTimesheetPeriodLockedStatusIds,\n AXMTimesheetPeriodOpenStatusIds,\n RootConfig,\n} from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type {\n AXMTimesheetManagementTimesheetPeriodEntityModel,\n AXMTimesheetPeriodType,\n} from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimesheetPolicyEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#endregion\n\n//#region ---- Types ----\n\nexport interface AXMTimesheetValidationIssue {\n code: string;\n message: string;\n field?: string;\n}\n\nexport interface AXMTimesheetValidationResult {\n valid: boolean;\n issues: AXMTimesheetValidationIssue[];\n}\n\nexport interface AXMTimesheetGetOrCreateDraftPeriodInput {\n employeeId: string;\n periodType: AXMTimesheetPeriodType;\n startDate: string;\n endDate: string;\n timezone: string;\n}\n\n//#endregion\n\n//#region ---- Timesheet Validation Service ----\n\n/**\n * Domain validation service for timesheet period and time entry business rules.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMTimesheetValidationService {\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Entry Validation ----\n\n /**\n * Validates that a time entry date falls within policy and period constraints.\n */\n validateEntryDates(\n entry: Pick<AXMTimesheetManagementTimeEntryEntityModel, 'entryDate' | 'startedAt' | 'endedAt'>,\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'startDate' | 'endDate'>,\n policy?: Pick<AXMTimesheetManagementTimesheetPolicyEntityModel, 'allowFutureDates'>,\n ): AXMTimesheetValidationResult {\n const issues: AXMTimesheetValidationIssue[] = [];\n const entryDate = entry.entryDate?.slice(0, 10);\n const periodStart = period.startDate?.slice(0, 10);\n const periodEnd = period.endDate?.slice(0, 10);\n\n if (entryDate && periodStart && entryDate < periodStart) {\n issues.push({\n code: 'entry-before-period',\n field: 'entryDate',\n message: 'Entry date is before the period start date.',\n });\n }\n\n if (entryDate && periodEnd && entryDate > periodEnd) {\n issues.push({\n code: 'entry-after-period',\n field: 'entryDate',\n message: 'Entry date is after the period end date.',\n });\n }\n\n if (!defaultTo(policy?.allowFutureDates, false)) {\n const today = new Date().toISOString().slice(0, 10);\n if (entryDate && entryDate > today) {\n issues.push({\n code: 'future-entry-date',\n field: 'entryDate',\n message: 'Future entry dates are not allowed by the active policy.',\n });\n }\n }\n\n if (entry.startedAt && entry.endedAt) {\n const started = Date.parse(entry.startedAt);\n const ended = Date.parse(entry.endedAt);\n if (!Number.isNaN(started) && !Number.isNaN(ended) && ended < started) {\n issues.push({\n code: 'ended-before-started',\n field: 'endedAt',\n message: 'End time must be after start time.',\n });\n }\n }\n\n return { valid: isEmpty(issues), issues };\n }\n\n /**\n * Validates that a time entry does not overlap existing entries for the same employee.\n */\n validateNoOverlap(\n entry: Pick<AXMTimesheetManagementTimeEntryEntityModel, 'id' | 'employeeId' | 'startedAt' | 'endedAt'>,\n existingEntries: Array<Pick<AXMTimesheetManagementTimeEntryEntityModel, 'id' | 'employeeId' | 'startedAt' | 'endedAt'>>,\n policy?: Pick<AXMTimesheetManagementTimesheetPolicyEntityModel, 'overlapPolicy'>,\n ): AXMTimesheetValidationResult {\n const issues: AXMTimesheetValidationIssue[] = [];\n const overlapPolicy = defaultTo(policy?.overlapPolicy, 'reject');\n\n if (!entry.startedAt || !entry.endedAt) {\n return { valid: true, issues };\n }\n\n const start = Date.parse(entry.startedAt);\n const end = Date.parse(entry.endedAt);\n if (Number.isNaN(start) || Number.isNaN(end)) {\n return { valid: true, issues };\n }\n\n const overlapping = existingEntries.filter((candidate) => {\n if (candidate.id === entry.id || candidate.employeeId !== entry.employeeId) {\n return false;\n }\n if (!candidate.startedAt || !candidate.endedAt) {\n return false;\n }\n const candidateStart = Date.parse(candidate.startedAt);\n const candidateEnd = Date.parse(candidate.endedAt);\n if (Number.isNaN(candidateStart) || Number.isNaN(candidateEnd)) {\n return false;\n }\n return start < candidateEnd && end > candidateStart;\n });\n\n if (!isEmpty(overlapping)) {\n issues.push({\n code: overlapPolicy === 'warn' ? 'entry-overlap-warning' : 'entry-overlap',\n field: 'startedAt',\n message:\n overlapPolicy === 'warn'\n ? 'This entry overlaps another entry for the same employee.'\n : 'Overlapping time entries are not allowed.',\n });\n }\n\n return {\n valid: overlapPolicy === 'warn' ? true : isEmpty(issues),\n issues,\n };\n }\n\n //#endregion\n\n //#region ---- Period Validation ----\n\n /**\n * Validates that a timesheet period can still be edited.\n */\n validatePeriodEditable(\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>,\n ): AXMTimesheetValidationResult {\n const statusId = period.statusId;\n const isLocked = (AXMTimesheetPeriodLockedStatusIds as readonly string[]).includes(statusId);\n\n if (isLocked) {\n return {\n valid: false,\n issues: [\n {\n code: 'period-locked',\n field: 'statusId',\n message: 'This timesheet period is locked and cannot be edited.',\n },\n ],\n };\n }\n\n return { valid: true, issues: [] };\n }\n\n /**\n * Validates that a period is complete enough for submission.\n */\n validateSubmissionCompleteness(\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId' | 'totalSeconds'>,\n entries: Array<Pick<AXMTimesheetManagementTimeEntryEntityModel, 'description'>>,\n policy?: Pick<AXMTimesheetManagementTimesheetPolicyEntityModel, 'requireDescription'>,\n ): AXMTimesheetValidationResult {\n const issues: AXMTimesheetValidationIssue[] = [];\n\n if (period.statusId !== AXPSystemStatusType.Draft) {\n issues.push({\n code: 'period-not-draft',\n field: 'statusId',\n message: 'Only draft periods can be submitted.',\n });\n }\n\n if (isEmpty(entries)) {\n issues.push({\n code: 'no-entries',\n message: 'At least one time entry is required before submission.',\n });\n }\n\n if (defaultTo(policy?.requireDescription, false)) {\n const missingDescription = entries.some((entry) => isEmpty(get(entry, 'description')));\n if (missingDescription) {\n issues.push({\n code: 'missing-description',\n field: 'description',\n message: 'All time entries must include a description before submission.',\n });\n }\n }\n\n const totalSeconds = defaultTo(period.totalSeconds, 0);\n if (totalSeconds <= 0 && !isEmpty(entries)) {\n issues.push({\n code: 'zero-total',\n field: 'totalSeconds',\n message: 'Submitted periods must have a positive total duration.',\n });\n }\n\n return { valid: isEmpty(issues), issues };\n }\n\n //#endregion\n\n //#region ---- Assertion Helpers ----\n\n assertPeriodAllowsTimeEntryEdits(\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>,\n ): void {\n const result = this.validatePeriodEditable(period);\n if (!result.valid) {\n throw new Error(result.issues[0]?.message ?? 'This timesheet period cannot be edited.');\n }\n }\n\n assertCanSubmit(\n period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId' | 'totalSeconds'>,\n entries: Array<Pick<AXMTimesheetManagementTimeEntryEntityModel, 'description'>> = [],\n policy?: Pick<AXMTimesheetManagementTimesheetPolicyEntityModel, 'requireDescription'>,\n ): void {\n const result = this.validateSubmissionCompleteness(period, entries, policy);\n if (!result.valid) {\n throw new Error(result.issues[0]?.message ?? 'Timesheet period cannot be submitted.');\n }\n }\n\n assertCanApprove(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n if (period.statusId !== AXPSystemStatusType.WaitingApproval) {\n throw new Error('Only submitted periods can be approved.');\n }\n }\n\n assertCanReject(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n if (period.statusId !== AXPSystemStatusType.WaitingApproval) {\n throw new Error('Only submitted periods can be rejected.');\n }\n }\n\n assertCanReopen(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n if (period.statusId !== AXPSystemStatusType.Rejected) {\n throw new Error('Only rejected periods can be reopened.');\n }\n }\n\n assertCanLock(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n if (period.statusId !== AXPSystemStatusType.Approved) {\n throw new Error('Only approved periods can be locked.');\n }\n }\n\n assertCanAdminAdjust(period: Pick<AXMTimesheetManagementTimesheetPeriodEntityModel, 'statusId'>): void {\n const isLocked = (AXMTimesheetPeriodLockedStatusIds as readonly string[]).includes(period.statusId);\n if (!isLocked && period.statusId !== AXPSystemStatusType.Approved) {\n throw new Error('Only approved or locked periods can be adjusted by an administrator.');\n }\n }\n\n //#endregion\n\n //#region ---- Period Resolution ----\n\n /**\n * Finds an existing open draft period or creates a new draft period for the employee.\n */\n async getOrCreateDraftPeriod(\n input: AXMTimesheetGetOrCreateDraftPeriodInput,\n ): Promise<AXMTimesheetManagementTimesheetPeriodEntityModel> {\n const periodAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timesheetPeriod.name)\n .data<string, AXMTimesheetManagementTimesheetPeriodEntityModel>();\n\n const existing = await periodAccessor.query({\n skip: 0,\n take: 1,\n filter: {\n logic: 'and',\n filters: [\n { field: 'employeeId', operator: { type: 'equal' }, value: input.employeeId },\n { field: 'periodType', operator: { type: 'equal' }, value: input.periodType },\n { field: 'startDate', operator: { type: 'equal' }, value: input.startDate },\n { field: 'endDate', operator: { type: 'equal' }, value: input.endDate },\n {\n field: 'statusId',\n operator: { type: 'in' },\n value: [...AXMTimesheetPeriodOpenStatusIds],\n },\n ],\n },\n });\n\n const match = get(existing, 'items[0]') as AXMTimesheetManagementTimesheetPeriodEntityModel | undefined;\n if (!isNil(match)) {\n return match;\n }\n\n const createdId = await periodAccessor.create({\n employeeId: input.employeeId,\n periodType: input.periodType,\n startDate: input.startDate,\n endDate: input.endDate,\n timezone: input.timezone,\n statusId: AXPSystemStatusType.Draft,\n totalSeconds: 0,\n });\n\n const created = await periodAccessor.byKey(createdId);\n if (isNil(created)) {\n throw new Error('Failed to load the newly created draft timesheet period.');\n }\n\n return created;\n }\n\n //#endregion\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-timesheet-management-client-update-time-entry.command-Do6s9OrI.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/time-entry/commands/update-time-entry.command.ts"],"sourcesContent":["import { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport { AXPRuntimeCommandResult } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimesheetPeriodEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport { AXMTimesheetValidationService } from '../../timesheet-period/timesheet-validation.service';\n\n//#region ---- Types ----\n\nexport interface UpdateTimeEntryInput {\n id: string;\n data: Partial<Omit<AXMTimesheetManagementTimeEntryEntityModel, 'id'>>;\n}\n\n//#endregion\n\n/**\n * Updates a time entry after validating the parent timesheet period is editable.\n */\n@Injectable({ providedIn: 'root' })\nexport class UpdateTimeEntryCommand implements AXPCommand<UpdateTimeEntryInput, AXMTimesheetManagementTimeEntryEntityModel> {\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n private readonly validationService = inject(AXMTimesheetValidationService);\n\n //#endregion\n\n //#region ---- Command Implementation ----\n\n async execute(\n input: UpdateTimeEntryInput,\n ): AXPCommandExecuteResultPromise<AXMTimesheetManagementTimeEntryEntityModel> {\n try {\n const dataAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timeEntry.name)\n .data<string, AXMTimesheetManagementTimeEntryEntityModel>();\n\n const existing = await dataAccessor.byKey(input.id);\n if (!existing) {\n return { success: false, message: { text: 'Time entry not found.' } };\n }\n\n const periodId = input.data.periodId ?? existing.periodId;\n await this.assertPeriodEditable(periodId);\n\n const updated = await dataAccessor.update(input.id, input.data);\n return { success: true, kind: 'object', data: updated };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Failed to update time entry.';\n console.error('[UpdateTimeEntryCommand] Error:', error);\n return { success: false, message: { text: message } };\n }\n }\n\n //#endregion\n\n //#region ---- Private helpers ----\n\n private async assertPeriodEditable(periodId: string): Promise<void> {\n const periodAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timesheetPeriod.name)\n .data<string, AXMTimesheetManagementTimesheetPeriodEntityModel>();\n\n const period = await periodAccessor.byKey(periodId);\n if (!period) {\n throw new Error('Timesheet period not found.');\n }\n this.validationService.assertPeriodAllowsTimeEntryEdits(period);\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;AAiBA;AAEA;;AAEG;MAEU,sBAAsB,CAAA;AADnC,IAAA,WAAA,GAAA;;AAImB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACxC,QAAA,IAAA,CAAA,iBAAiB,GAAG,MAAM,CAAC,6BAA6B,CAAC;AAgD3E,IAAA;;;IA1CC,MAAM,OAAO,CACX,KAA2B,EAAA;AAE3B,QAAA,IAAI;AACF,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC;AACvB,iBAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI;AACrE,iBAAA,IAAI,EAAsD;YAE7D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,QAAQ,EAAE;AACb,gBAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,EAAE;YACvE;YAEA,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ;AACzD,YAAA,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC;AAEzC,YAAA,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC;AAC/D,YAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE;QACzD;QAAE,OAAO,KAAc,EAAE;AACvB,YAAA,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,8BAA8B;AACvF,YAAA,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC;AACvD,YAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QACvD;IACF;;;IAMQ,MAAM,oBAAoB,CAAC,QAAgB,EAAA;AACjD,QAAA,MAAM,cAAc,GAAG,IAAI,CAAC;AACzB,aAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI;AAC3E,aAAA,IAAI,EAA4D;QAEnE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC;QACnD,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC;QAChD;AACA,QAAA,IAAI,CAAC,iBAAiB,CAAC,gCAAgC,CAAC,MAAM,CAAC;IACjE;8GAjDW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAtB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,sBAAsB,cADT,MAAM,EAAA,CAAA,CAAA;;2FACnB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;;;"}
1
+ {"version":3,"file":"acorex-platform-module-timesheet-management-client-update-time-entry.command-Do6s9OrI.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/time-entry/commands/update-time-entry.command.ts"],"sourcesContent":["import { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport { AXPRuntimeCommandResult } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimeEntryEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementTimesheetPeriodEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport { AXMTimesheetValidationService } from '../../timesheet-period/timesheet-validation.service';\n\n//#region ---- Types ----\n\nexport interface UpdateTimeEntryInput {\n id: string;\n data: Partial<Omit<AXMTimesheetManagementTimeEntryEntityModel, 'id'>>;\n}\n\n//#endregion\n\n/**\n * Updates a time entry after validating the parent timesheet period is editable.\n */\n@Injectable({ providedIn: 'root' })\nexport class UpdateTimeEntryCommand implements AXPCommand<UpdateTimeEntryInput, AXMTimesheetManagementTimeEntryEntityModel> {\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n private readonly validationService = inject(AXMTimesheetValidationService);\n\n //#endregion\n\n //#region ---- Command Implementation ----\n\n async execute(\n input: UpdateTimeEntryInput,\n ): AXPCommandExecuteResultPromise<AXMTimesheetManagementTimeEntryEntityModel> {\n try {\n const dataAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timeEntry.name)\n .data<string, AXMTimesheetManagementTimeEntryEntityModel>();\n\n const existing = await dataAccessor.byKey(input.id);\n if (!existing) {\n return { success: false, message: { text: 'Time entry not found.' } };\n }\n\n const periodId = input.data.periodId ?? existing.periodId;\n await this.assertPeriodEditable(periodId);\n\n const updated = await dataAccessor.update(input.id, input.data);\n return { success: true, kind: 'object', data: updated };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Failed to update time entry.';\n console.error('[UpdateTimeEntryCommand] Error:', error);\n return { success: false, message: { text: message } };\n }\n }\n\n //#endregion\n\n //#region ---- Private helpers ----\n\n private async assertPeriodEditable(periodId: string): Promise<void> {\n const periodAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.timesheetPeriod.name)\n .data<string, AXMTimesheetManagementTimesheetPeriodEntityModel>();\n\n const period = await periodAccessor.byKey(periodId);\n if (!period) {\n throw new Error('Timesheet period not found.');\n }\n this.validationService.assertPeriodAllowsTimeEntryEdits(period);\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;AAiBA;AAEA;;AAEG;MAEU,sBAAsB,CAAA;AADnC,IAAA,WAAA,GAAA;;AAImB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACxC,QAAA,IAAA,CAAA,iBAAiB,GAAG,MAAM,CAAC,6BAA6B,CAAC;AAgD3E,IAAA;;;IA1CC,MAAM,OAAO,CACX,KAA2B,EAAA;AAE3B,QAAA,IAAI;AACF,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC;AACvB,iBAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI;AACrE,iBAAA,IAAI,EAAsD;YAE7D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,QAAQ,EAAE;AACb,gBAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,EAAE;YACvE;YAEA,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ;AACzD,YAAA,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC;AAEzC,YAAA,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC;AAC/D,YAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE;QACzD;QAAE,OAAO,KAAc,EAAE;AACvB,YAAA,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,8BAA8B;AACvF,YAAA,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC;AACvD,YAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QACvD;IACF;;;IAMQ,MAAM,oBAAoB,CAAC,QAAgB,EAAA;AACjD,QAAA,MAAM,cAAc,GAAG,IAAI,CAAC;AACzB,aAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI;AAC3E,aAAA,IAAI,EAA4D;QAEnE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC;QACnD,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC;QAChD;AACA,QAAA,IAAI,CAAC,iBAAiB,CAAC,gCAAgC,CAAC,MAAM,CAAC;IACjE;8GAjDW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAtB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,sBAAsB,cADT,MAAM,EAAA,CAAA,CAAA;;2FACnB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-timesheet-management-client-work-item-search.query-BA2kvF-S.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/work-item-search.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport { resolveMultiLanguageString } from '@acorex/core/translation';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessCollection,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { isEmpty } from 'lodash';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementWorkItemEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMWorkItemSearchQueryInput {\n searchText?: string;\n employeeId?: string;\n isActive?: boolean;\n skip?: number;\n take?: number;\n}\n\nexport interface AXMWorkItemSearchQueryItem {\n id: string;\n code: string;\n title: string;\n sourceType: string;\n isBillableDefault: boolean;\n}\n\n//#endregion\n\n/**\n * Searches work items for timesheet entry pickers.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMWorkItemSearchQuery\n implements AXPQuery<AXMWorkItemSearchQueryInput, AXMWorkItemSearchQueryItem>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input?: AXMWorkItemSearchQueryInput | null,\n ): AXPQueryFetchResultPromise<AXMWorkItemSearchQueryItem> {\n try {\n const opts = input ?? {};\n const workItemAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.workItem.name)\n .data<string, AXMTimesheetManagementWorkItemEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [];\n if (opts.employeeId) {\n filters.push({ field: 'employeeId', operator: { type: 'equal' }, value: opts.employeeId });\n }\n if (opts.isActive != null) {\n filters.push({ field: 'isActive', operator: { type: 'equal' }, value: opts.isActive });\n }\n if (!isEmpty(opts.searchText?.trim())) {\n filters.push({\n field: 'code',\n operator: { type: 'contains' },\n value: opts.searchText!.trim(),\n });\n }\n\n const result = await workItemAccessor.query({\n skip: opts.skip ?? 0,\n take: opts.take ?? 25,\n sort: [{ field: 'code', dir: 'asc' }],\n ...(filters.length ? { filter: { logic: 'and', filters } } : {}),\n });\n\n const items = result.items.map((row) => ({\n id: row.id,\n code: row.code,\n title: resolveMultiLanguageString(row.title, 'en-US'),\n sourceType: row.sourceType,\n isBillableDefault: row.isBillableDefault,\n }));\n\n return runtimeQuerySuccessCollection({ items, total: result.total });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to search work items.',\n );\n }\n }\n\n //#endregion\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"acorex-platform-module-timesheet-management-client-work-item-search.query-BA2kvF-S.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/work-item-search.query.ts"],"sourcesContent":["import { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXDataSourceFilterOption } from '@acorex/cdk/common';\nimport { resolveMultiLanguageString } from '@acorex/core/translation';\nimport {\n runtimeQueryFailure,\n runtimeQuerySuccessCollection,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\n\nimport { Injectable, inject } from '@angular/core';\nimport { isEmpty } from 'lodash';\nimport { RootConfig } from '@acorex-platform/module-timesheet-management-client/contracts';\nimport type { AXMTimesheetManagementWorkItemEntityModel } from '@acorex-platform/module-timesheet-management-client/contracts';\n\n//#region ---- Types ----\n\nexport interface AXMWorkItemSearchQueryInput {\n searchText?: string;\n employeeId?: string;\n isActive?: boolean;\n skip?: number;\n take?: number;\n}\n\nexport interface AXMWorkItemSearchQueryItem {\n id: string;\n code: string;\n title: string;\n sourceType: string;\n isBillableDefault: boolean;\n}\n\n//#endregion\n\n/**\n * Searches work items for timesheet entry pickers.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMWorkItemSearchQuery\n implements AXPQuery<AXMWorkItemSearchQueryInput, AXMWorkItemSearchQueryItem>\n{\n //#region ---- Services & Dependencies ----\n\n private readonly entityService = inject(AXPEntityService);\n\n //#endregion\n\n //#region ---- Query Execution ----\n\n async fetch(\n input?: AXMWorkItemSearchQueryInput | null,\n ): AXPQueryFetchResultPromise<AXMWorkItemSearchQueryItem> {\n try {\n const opts = input ?? {};\n const workItemAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.workItem.name)\n .data<string, AXMTimesheetManagementWorkItemEntityModel>();\n\n const filters: AXDataSourceFilterOption[] = [];\n if (opts.employeeId) {\n filters.push({ field: 'employeeId', operator: { type: 'equal' }, value: opts.employeeId });\n }\n if (opts.isActive != null) {\n filters.push({ field: 'isActive', operator: { type: 'equal' }, value: opts.isActive });\n }\n if (!isEmpty(opts.searchText?.trim())) {\n filters.push({\n field: 'code',\n operator: { type: 'contains' },\n value: opts.searchText!.trim(),\n });\n }\n\n const result = await workItemAccessor.query({\n skip: opts.skip ?? 0,\n take: opts.take ?? 25,\n sort: [{ field: 'code', dir: 'asc' }],\n ...(filters.length ? { filter: { logic: 'and', filters } } : {}),\n });\n\n const items = result.items.map((row) => ({\n id: row.id,\n code: row.code,\n title: resolveMultiLanguageString(row.title, 'en-US'),\n sourceType: row.sourceType,\n isBillableDefault: row.isBillableDefault,\n }));\n\n return runtimeQuerySuccessCollection({ items, total: result.total });\n } catch (error) {\n return runtimeQueryFailure(\n error instanceof Error ? error.message : 'Failed to search work items.',\n );\n }\n }\n\n //#endregion\n}\n"],"names":[],"mappings":";;;;;;;;AAiCA;AAEA;;AAEG;MAEU,sBAAsB,CAAA;AADnC,IAAA,WAAA,GAAA;;AAMmB,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAsD1D,IAAA;;;IAhDC,MAAM,KAAK,CACT,KAA0C,EAAA;AAE1C,QAAA,IAAI;AACF,YAAA,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;AACxB,YAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC3B,iBAAA,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI;AACpE,iBAAA,IAAI,EAAqD;YAE5D,MAAM,OAAO,GAA+B,EAAE;AAC9C,YAAA,IAAI,IAAI,CAAC,UAAU,EAAE;gBACnB,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;YAC5F;AACA,YAAA,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE;gBACzB,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxF;YACA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE;gBACrC,OAAO,CAAC,IAAI,CAAC;AACX,oBAAA,KAAK,EAAE,MAAM;AACb,oBAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;AAC9B,oBAAA,KAAK,EAAE,IAAI,CAAC,UAAW,CAAC,IAAI,EAAE;AAC/B,iBAAA,CAAC;YACJ;AAEA,YAAA,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC;AAC1C,gBAAA,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;AACpB,gBAAA,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;gBACrB,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;gBACrC,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC;AACjE,aAAA,CAAC;AAEF,YAAA,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM;gBACvC,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,KAAK,EAAE,0BAA0B,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC;gBACrD,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;AACzC,aAAA,CAAC,CAAC;AAEH,YAAA,OAAO,6BAA6B,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QACtE;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,mBAAmB,CACxB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,8BAA8B,CACxE;QACH;IACF;8GAxDW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAtB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,sBAAsB,cADT,MAAM,EAAA,CAAA,CAAA;;2FACnB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-timesheet-management-client-workforce-exception-report.query-0q-AITic.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/workforce-exception-report.query.ts"],"sourcesContent":["//#region ---- Imports ----\n\nimport { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport {\n runtimeQueryFailure,\n runtimeQueryPayloadData,\n runtimeQuerySuccessObject,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { inject, Injectable } from '@angular/core';\nimport { AXMCompareAttendanceVsTimesheetQuery } from './compare-attendance-vs-timesheet.query';\n\n//#endregion\n\n//#region ---- Types ----\n\nexport interface AXMWorkforceExceptionReportQueryInput {\n employeeId: string;\n fromDate: string;\n toDate: string;\n varianceThresholdSeconds?: number;\n}\n\nexport interface AXMWorkforceExceptionReportQueryResult {\n exceptions: {\n date: string;\n attendanceWorkedSeconds: number;\n timesheetLoggedSeconds: number;\n varianceSeconds: number;\n }[];\n}\n\n//#endregion\n\n//#region ---- Query ----\n\n/**\n * Returns only dates where attendance vs timesheet variance exceeds the threshold.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMWorkforceExceptionReportQuery\n implements AXPQuery<AXMWorkforceExceptionReportQueryInput, AXMWorkforceExceptionReportQueryResult>\n{\n private readonly compareQuery = inject(AXMCompareAttendanceVsTimesheetQuery);\n\n async fetch(\n input: AXMWorkforceExceptionReportQueryInput,\n ): AXPQueryFetchResultPromise<AXMWorkforceExceptionReportQueryResult> {\n const result = await this.compareQuery.fetch(input);\n const payload = runtimeQueryPayloadData(result);\n if (!payload) {\n return runtimeQueryFailure(result.message ?? 'Failed to load workforce exception report.');\n }\n\n const exceptions = payload.rows\n .filter((row) => row.exceedsThreshold)\n .map((row) => ({\n date: row.date,\n attendanceWorkedSeconds: row.attendanceWorkedSeconds,\n timesheetLoggedSeconds: row.timesheetLoggedSeconds,\n varianceSeconds: row.varianceSeconds,\n }));\n\n return runtimeQuerySuccessObject({ exceptions });\n }\n}\n\n//#endregion\n"],"names":[],"mappings":";;;;;AAgCA;AAEA;AAEA;;AAEG;MAEU,gCAAgC,CAAA;AAD7C,IAAA,WAAA,GAAA;AAImB,QAAA,IAAA,CAAA,YAAY,GAAG,MAAM,CAAC,oCAAoC,CAAC;AAsB7E,IAAA;IApBC,MAAM,KAAK,CACT,KAA4C,EAAA;QAE5C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC;AACnD,QAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,MAAM,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,mBAAmB,CAAC,MAAM,CAAC,OAAO,IAAI,4CAA4C,CAAC;QAC5F;AAEA,QAAA,MAAM,UAAU,GAAG,OAAO,CAAC;aACxB,MAAM,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,gBAAgB;AACpC,aAAA,GAAG,CAAC,CAAC,GAAG,MAAM;YACb,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,uBAAuB,EAAE,GAAG,CAAC,uBAAuB;YACpD,sBAAsB,EAAE,GAAG,CAAC,sBAAsB;YAClD,eAAe,EAAE,GAAG,CAAC,eAAe;AACrC,SAAA,CAAC,CAAC;AAEL,QAAA,OAAO,yBAAyB,CAAC,EAAE,UAAU,EAAE,CAAC;IAClD;8GAxBW,gCAAgC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAhC,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,gCAAgC,cADnB,MAAM,EAAA,CAAA,CAAA;;2FACnB,gCAAgC,EAAA,UAAA,EAAA,CAAA;kBAD5C,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;;;"}
1
+ {"version":3,"file":"acorex-platform-module-timesheet-management-client-workforce-exception-report.query-0q-AITic.mjs","sources":["../../../../libs/modules/timesheet-management/client/src/lib/features/reporting/queries/workforce-exception-report.query.ts"],"sourcesContent":["//#region ---- Imports ----\n\nimport { AXPQuery, type AXPQueryFetchResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport {\n runtimeQueryFailure,\n runtimeQueryPayloadData,\n runtimeQuerySuccessObject,\n type AXPRuntimeQueryResult,\n} from '@acorex-platform/framework-shared/core';\nimport { inject, Injectable } from '@angular/core';\nimport { AXMCompareAttendanceVsTimesheetQuery } from './compare-attendance-vs-timesheet.query';\n\n//#endregion\n\n//#region ---- Types ----\n\nexport interface AXMWorkforceExceptionReportQueryInput {\n employeeId: string;\n fromDate: string;\n toDate: string;\n varianceThresholdSeconds?: number;\n}\n\nexport interface AXMWorkforceExceptionReportQueryResult {\n exceptions: {\n date: string;\n attendanceWorkedSeconds: number;\n timesheetLoggedSeconds: number;\n varianceSeconds: number;\n }[];\n}\n\n//#endregion\n\n//#region ---- Query ----\n\n/**\n * Returns only dates where attendance vs timesheet variance exceeds the threshold.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXMWorkforceExceptionReportQuery\n implements AXPQuery<AXMWorkforceExceptionReportQueryInput, AXMWorkforceExceptionReportQueryResult>\n{\n private readonly compareQuery = inject(AXMCompareAttendanceVsTimesheetQuery);\n\n async fetch(\n input: AXMWorkforceExceptionReportQueryInput,\n ): AXPQueryFetchResultPromise<AXMWorkforceExceptionReportQueryResult> {\n const result = await this.compareQuery.fetch(input);\n const payload = runtimeQueryPayloadData(result);\n if (!payload) {\n return runtimeQueryFailure(result.message ?? 'Failed to load workforce exception report.');\n }\n\n const exceptions = payload.rows\n .filter((row) => row.exceedsThreshold)\n .map((row) => ({\n date: row.date,\n attendanceWorkedSeconds: row.attendanceWorkedSeconds,\n timesheetLoggedSeconds: row.timesheetLoggedSeconds,\n varianceSeconds: row.varianceSeconds,\n }));\n\n return runtimeQuerySuccessObject({ exceptions });\n }\n}\n\n//#endregion\n"],"names":[],"mappings":";;;;;AAgCA;AAEA;AAEA;;AAEG;MAEU,gCAAgC,CAAA;AAD7C,IAAA,WAAA,GAAA;AAImB,QAAA,IAAA,CAAA,YAAY,GAAG,MAAM,CAAC,oCAAoC,CAAC;AAsB7E,IAAA;IApBC,MAAM,KAAK,CACT,KAA4C,EAAA;QAE5C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC;AACnD,QAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,MAAM,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,mBAAmB,CAAC,MAAM,CAAC,OAAO,IAAI,4CAA4C,CAAC;QAC5F;AAEA,QAAA,MAAM,UAAU,GAAG,OAAO,CAAC;aACxB,MAAM,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,gBAAgB;AACpC,aAAA,GAAG,CAAC,CAAC,GAAG,MAAM;YACb,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,uBAAuB,EAAE,GAAG,CAAC,uBAAuB;YACpD,sBAAsB,EAAE,GAAG,CAAC,sBAAsB;YAClD,eAAe,EAAE,GAAG,CAAC,eAAe;AACrC,SAAA,CAAC,CAAC;AAEL,QAAA,OAAO,yBAAyB,CAAC,EAAE,UAAU,EAAE,CAAC;IAClD;8GAxBW,gCAAgC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAhC,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,gCAAgC,cADnB,MAAM,EAAA,CAAA,CAAA;;2FACnB,gCAAgC,EAAA,UAAA,EAAA,CAAA;kBAD5C,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;"}
@@ -194,7 +194,7 @@ class AXMMyTimesheetPageComponent extends AXPPageLayoutBaseComponent {
194
194
  </div>
195
195
  </axp-page-content>
196
196
  </axp-page-layout>
197
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
197
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
198
198
  }
199
199
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMyTimesheetPageComponent, decorators: [{
200
200
  type: Component,