From b9ac5ae0b29311fda54c7ee71b6776bbfd75cda9 Mon Sep 17 00:00:00 2001 From: Your NamebaishaliHolocron Date: Mon, 15 Jun 2026 12:57:03 +0530 Subject: [PATCH] first commit --- backend/.gitignore | 39 + backend/Dockerfile | 51 + backend/README.md | 17 + backend/ikoncloud-dev.keross.com.crt | Bin 0 -> 1762 bytes .../lib/ikon-app-access-management-1.0.0.jar | Bin 0 -> 101065 bytes ...kon-app-access-management-events-1.0.0.jar | Bin 0 -> 31920 bytes backend/lib/ikon-app-core-1.0.0.jar | Bin 0 -> 6277 bytes backend/lib/ikon-autoconfigure-1.0.0.jar | Bin 0 -> 3757 bytes backend/lib/ikon-client-1.0.0.jar | Bin 0 -> 48008 bytes backend/lib/ikon-core-1.0.0.jar | Bin 0 -> 73198 bytes backend/lib/ikon-dataaccess-1.0.0.jar | Bin 0 -> 51760 bytes backend/lib/ikon-logger-events-1.0.0.jar | Bin 0 -> 21770 bytes backend/lib/ikon-platform-1.0.0.jar | Bin 0 -> 43784 bytes backend/lib/ikon-platform-server-1.0.0.jar | Bin 0 -> 30684 bytes .../lib/ikon-platform-server-events-1.0.0.jar | Bin 0 -> 13569 bytes backend/lib/ikon-processengine-1.0.0.jar | Bin 0 -> 64400 bytes backend/lib/ikon-processmanagement-1.0.0.jar | Bin 0 -> 39041 bytes backend/lib/ikon-sdk-1.0.0.jar | Bin 0 -> 14552 bytes .../lib/ikon-web-context-manager-1.0.0.jar | Bin 0 -> 7274 bytes backend/lib/ikon-web-security-1.0.0.jar | Bin 0 -> 16206 bytes backend/lib/ikon-webservice-1.0.0.jar | Bin 0 -> 48729 bytes backend/lib/kafka-utils-1.0.0.jar | Bin 0 -> 7077 bytes backend/pom.xml | 95 + backend/projectmanagement-client/pom.xml | 73 + .../projectmanagement/api/DashboardApi.java | 36 + .../projectmanagement/api/EmployeeApi.java | 44 + .../ikon/projectmanagement/api/FxRateApi.java | 40 + .../ikon/projectmanagement/api/GradeApi.java | 45 + .../api/ImportEmployeeApi.java | 22 + .../api/ImportFxRateApi.java | 22 + .../projectmanagement/api/ImportGradeApi.java | 22 + .../projectmanagement/api/ImportRoleApi.java | 22 + .../api/ImportWorkingDayApi.java | 22 + .../ikon/projectmanagement/api/IssueApi.java | 76 + .../projectmanagement/api/MeetingApi.java | 91 + .../api/ProductOfProjectApi.java | 74 + .../api/ProductResourceAllocationApi.java | 81 + .../projectmanagement/api/ProjectApi.java | 82 + .../ikon/projectmanagement/api/RiskApi.java | 84 + .../ikon/projectmanagement/api/RoleApi.java | 45 + .../projectmanagement/api/ScheduleApi.java | 49 + .../projectmanagement/api/WorkingDayApi.java | 37 + .../dto/request/ActionItemDTO.java | 17 + .../dto/request/ActionsWrapperDTO.java | 15 + .../dto/request/AgendaItemDTO.java | 15 + .../dto/request/AgendaWrapperDTO.java | 15 + .../dto/request/AttendeeDTO.java | 17 + .../dto/request/AttendeesWrapperDTO.java | 15 + .../dto/request/DecisionsWrapperDTO.java | 15 + .../dto/request/EmployeeRequestDto.java | 20 + .../dto/request/FxRateDto.java | 19 + .../dto/request/GradeRequestDto.java | 18 + .../dto/request/ImportDataRequestDto.java | 17 + .../dto/request/IssueCreateRequestDto.java | 47 + .../dto/request/MeetingDetailsDTO.java | 27 + .../dto/request/MeetingRequestDTO.java | 30 + .../dto/request/OthersDTO.java | 13 + .../dto/request/ProductExpenseRequestDto.java | 22 + .../request/ProductOfProjectRequestDto.java | 35 + ...ProductPSResourceAllocationRequestDto.java | 25 + .../dto/request/ProjectRequestDto.java | 51 + .../dto/request/RiskCreateRequestDto.java | 45 + .../dto/request/RoleRequestDto.java | 17 + .../dto/request/ScheduleDependencyDto.java | 14 + .../dto/request/ScheduleGroupDto.java | 18 + .../dto/request/ScheduleRequestDto.java | 17 + .../dto/request/ScheduleTaskDto.java | 23 + .../request/WorkflowTransitionRequestDto.java | 22 + .../dto/request/WorkingDayDto.java | 16 + .../response/DashboardWidgetsResponseDto.java | 16 + .../dto/response/EmployeeResponseDto.java | 26 + .../dto/response/FxRateDetailsDto.java | 12 + .../dto/response/FxRateDto.java | 22 + .../dto/response/FxRateResponseDto.java | 13 + .../dto/response/GradeResponseDto.java | 18 + .../dto/response/IssueResponseDto.java | 49 + .../dto/response/MeetingResponseDTO.java | 37 + .../response/ProductExpenseResponseDto.java | 25 + .../response/ProductOfProjectResponseDto.java | 40 + ...roductPSResourceAllocationResponseDto.java | 27 + .../dto/response/ProjectResponseDto.java | 63 + .../response/ProjectTimelineResponseDto.java | 19 + .../dto/response/RiskResponseDto.java | 46 + .../dto/response/RoleResponseDto.java | 18 + .../dto/response/ScheduleResponseDto.java | 23 + .../StatusWiseProjectResponseData.java | 15 + .../dto/response/WorkingDayDto.java | 20 + .../dto/response/WorkingDaysMonthDto.java | 12 + .../dto/response/WorkingDaysResponseDto.java | 12 + .../ikoncloud-dev.keross.com.crt | Bin 0 -> 1762 bytes backend/projectmanagement-server/pom.xml | 128 + .../ProjectManagementApplication.java | 42 + .../config/ModelMapperConfig.java | 15 + .../config/RestTemplateConfigs.java | 13 + .../config/SecurityConfig.java | 67 + .../controller/DashboardController.java | 31 + .../controller/EmployeeController.java | 63 + .../controller/FxRateController.java | 32 + .../controller/GradeController.java | 64 + .../controller/ImportEmployeeController.java | 26 + .../controller/ImportFxRateController.java | 26 + .../controller/ImportGradeController.java | 26 + .../controller/ImportRoleController.java | 26 + .../ImportWorkingDayController.java | 26 + .../controller/IssueController.java | 78 + .../controller/MeetingController.java | 72 + .../ProductOfProjectController.java | 67 + .../ProductResourceAllocationController.java | 62 + .../controller/ProjectController.java | 66 + .../controller/RiskController.java | 71 + .../controller/RoleController.java | 64 + .../controller/ScheduleController.java | 39 + .../controller/WorkingDayController.java | 36 + .../projectmanagement/entity/Employee.java | 43 + .../entity/FxRateDetailsEntity.java | 41 + .../entity/FxRateEntity.java | 36 + .../ikon/projectmanagement/entity/Grade.java | 32 + .../ikon/projectmanagement/entity/Issue.java | 93 + .../projectmanagement/entity/Meeting.java | 139 + .../entity/ProductOfProject.java | 80 + .../entity/ProductOfProjectExpenseDetail.java | 33 + .../entity/ProductPSQuotation.java | 32 + .../entity/ProductPSResourceAllocation.java | 48 + .../projectmanagement/entity/Project.java | 180 + .../entity/ProjectSchedule.java | 51 + .../entity/ProjectScheduleDependency.java | 27 + .../entity/ProjectScheduleGroup.java | 47 + .../entity/ProjectScheduleTask.java | 54 + .../ikon/projectmanagement/entity/Risks.java | 91 + .../ikon/projectmanagement/entity/Role.java | 30 + .../entity/WorkingDaysDetailsEntity.java | 34 + .../entity/WorkingDaysEntity.java | 36 + .../mapper/EmployeeMapper.java | 79 + .../projectmanagement/mapper/GradeMapper.java | 60 + .../projectmanagement/mapper/IssueMapper.java | 112 + .../mapper/MeetingMapper.java | 263 + .../mapper/ProductOfProjectMapper.java | 198 + .../ProductResourceAllocationMapper.java | 74 + .../mapper/ProjectMapper.java | 118 + .../projectmanagement/mapper/RiskMapper.java | 88 + .../projectmanagement/mapper/RoleMapper.java | 59 + .../mapper/ScheduleMapper.java | 99 + .../repository/EmployeeRepository.java | 12 + .../repository/FxRateRepository.java | 26 + .../repository/GradeRepository.java | 10 + .../repository/IssueRepository.java | 16 + .../repository/MeetingRepository.java | 16 + .../ProductOfProjectRepository.java | 24 + .../repository/ProjectRepository.java | 36 + .../repository/ProjectScheduleRepository.java | 18 + .../repository/RiskRepository.java | 22 + .../repository/RoleRepository.java | 10 + .../repository/WorkingDaysRepository.java | 28 + .../service/DashboardService.java | 11 + .../service/EmployeeService.java | 33 + .../service/FxRateService.java | 11 + .../service/GradeService.java | 34 + .../service/ImportEmployeeService.java | 10 + .../service/ImportFxRateService.java | 10 + .../service/ImportGradeService.java | 10 + .../service/ImportRoleService.java | 10 + .../service/ImportWorkingDayService.java | 10 + .../service/IssueService.java | 22 + .../service/MeetingService.java | 22 + .../service/ProductOfProjectService.java | 27 + .../ProductResourceAllocationService.java | 20 + .../service/ProjectService.java | 21 + .../service/RiskService.java | 20 + .../service/RoleService.java | 34 + .../service/ScheduleService.java | 13 + .../service/WorkingDayService.java | 11 + .../service/etl/DealConnector.java | 366 + .../service/etl/EmployeeConector.java | 71 + .../service/etl/FxRateConnector.java | 184 + .../service/etl/GradeConnector.java | 134 + .../service/etl/RoleConnector.java | 94 + .../service/etl/WorkingDaysConnector.java | 188 + .../service/impl/DashboardServiceImpl.java | 35 + .../service/impl/EmployeeServiceImpl.java | 61 + .../service/impl/FxRateServiceImpl.java | 64 + .../service/impl/GradeServiceImpl.java | 58 + .../impl/ImportEmployeeServiceImpl.java | 132 + .../service/impl/ImportFxRateServiceImpl.java | 141 + .../service/impl/ImportGradeServiceImpl.java | 85 + .../service/impl/ImportRoleServiceImpl.java | 85 + .../impl/ImportWorkingDayServiceImpl.java | 109 + .../service/impl/IssueServiceImpl.java | 112 + .../service/impl/MeetingServiceImpl.java | 98 + .../impl/ProductOfProjectServiceImpl.java | 213 + .../ProductResourceAllocationServiceImpl.java | 89 + .../service/impl/ProjectServiceImpl.java | 139 + .../service/impl/RiskServiceImpl.java | 118 + .../service/impl/RoleServiceImpl.java | 58 + .../service/impl/ScheduleServiceImpl.java | 127 + .../service/impl/WorkingDayServiceImpl.java | 58 + .../main/resources/activiti.engine.schema.sql | 1502 ++ .../src/main/resources/application-local.yml | 71 + .../src/main/resources/application-server.yml | 119 + .../src/main/resources/application.properties | 2 + .../src/main/resources/application.yml | 116 + .../src/main/resources/application_old.yml | 117 + bpmn/.gitignore | 0 bpmn/environments.json | 8 + bpmn/folder_structure.json | 9 + bpmn/lib/readme.md | 2 + bpmn/package-lock.json | 8 + bpmn/package.json | 12 + bpmn/project.json | 31 + .../readme.md | 3 + dockerfiles.yaml | 9 + frontend/.gitignore | 41 + frontend/Dockerfile | 59 + frontend/README.md | 36 + frontend/app/api/health/live/route.ts | 5 + frontend/app/api/health/ready/route.ts | 5 + frontend/app/favicon.ico | Bin 0 -> 25931 bytes frontend/app/globals.css | 15 + frontend/app/home/components/CTASection.tsx | 47 + .../app/home/components/FeaturesSection.tsx | 210 + frontend/app/home/components/Footer.tsx | 55 + frontend/app/home/components/HeroSection.tsx | 137 + .../home/components/IntegrationSection.tsx | 61 + .../home/components/MethodologySection.tsx | 97 + frontend/app/home/components/Navbar.tsx | 91 + .../app/home/components/SecuritySection.tsx | 78 + .../app/home/components/VisibilitySection.tsx | 95 + frontend/app/home/layout.tsx | 16 + frontend/app/home/page.tsx | 22 + frontend/app/home/projects/layout.tsx | 13 + frontend/app/home/projects/page.tsx | 9 + frontend/app/layout.tsx | 173 + .../components/grade-table/index.tsx | 146 + .../components/role-table/index.tsx | 150 + .../company-data/components/tabs/index.tsx | 28 + .../configuration/company-data/layout.tsx | 15 + .../main/configuration/company-data/page.tsx | 9 + .../components/employee-table/index.tsx | 172 + .../components/employeeCard/index.tsx | 103 + .../configuration/employee-data/layout.tsx | 21 + .../main/configuration/employee-data/page.tsx | 19 + .../components/fx-rate-table/index.tsx | 98 + .../app/main/configuration/fx-rate/layout.tsx | 15 + .../app/main/configuration/fx-rate/page.tsx | 9 + .../components/AddIntegrationModal.tsx | 238 + .../components/IntegratinTable.tsx | 103 + .../components/IntegrationMainPage.tsx | 73 + .../integration/form/IntegrationSchema.tsx | 0 .../main/configuration/integration/layout.tsx | 11 + .../main/configuration/integration/page.tsx | 15 + frontend/app/main/configuration/layout.tsx | 7 + .../office-details/components/tab/index.tsx | 13 + .../components/working-days-table/index.tsx | 125 + .../configuration/office-details/layout.tsx | 12 + .../configuration/office-details/page.tsx | 10 + frontend/app/main/layout.tsx | 55 + frontend/app/main/loading.tsx | 11 + .../components/ProjectsbyStatusChart/page.tsx | 132 + .../dashboard/components/Widgets/index.tsx | 89 + .../activeProjectTimeLine/index.tsx | 195 + .../dashboard/components/milestone/page.tsx | 108 + .../app/main/overview/dashboard/layout.tsx | 7 + frontend/app/main/overview/dashboard/page.tsx | 54 + frontend/app/main/overview/layout.tsx | 7 + frontend/app/main/page.tsx | 9 + .../component/expenseTab/AddExpenseModal.tsx | 365 + .../component/expenseTab/addExpenseButton.tsx | 44 + .../component/expenseTab/expenseDataTable.tsx | 80 + .../expenseTab/expenseMainDataTable.tsx | 79 + .../component/expenseTab/index.tsx | 28 + .../component/header/index.tsx | 134 + .../component/header/type.ts | 62 + .../issueTab/components/editIssue/index.tsx | 324 + .../issueTab/components/editIssue/schema.ts | 14 + .../issueTab/components/issueModal/index.tsx | 397 + .../issueTab/components/issueModal/schema.ts | 25 + .../components/issueWorkflow/index.tsx | 456 + .../component/issueTab/index.tsx | 204 + .../meetingForm/MeetingDetailsForm.tsx | 305 + .../meetingForm/components/StepIndicator.tsx | 44 + .../components/steps/ActionsStep.tsx | 134 + .../components/steps/AgendaStep.tsx | 129 + .../components/steps/AttendeesStep.tsx | 152 + .../components/steps/DecisionsStep.tsx | 85 + .../components/steps/MeetingStep.tsx | 195 + .../components/steps/OthersStep.tsx | 36 + .../components/meetingForm/components/ui.tsx | 125 + .../components/meetingForm/lib/constants.ts | 11 + .../components/meetingForm/lib/utils.ts | 65 + .../components/meetingForm/lib/validation.ts | 101 + .../components/meetingForm/types/index.ts | 81 + .../component/momTab/index.tsx | 382 + .../component/resourceForm/index.tsx | 1366 ++ .../component/resourceForm/resourceModal.tsx | 123 + .../resourceForm/spreadSheetFunctionality.tsx | 359 + .../component/resourceTab/index.tsx | 137 + .../riskTab/components/editRisk/index.tsx | 333 + .../riskTab/components/editRisk/schema.ts | 14 + .../riskTab/components/riskModal/index.tsx | 442 + .../riskTab/components/riskModal/schema.ts | 19 + .../riskTab/components/riskWorkflow/index.tsx | 445 + .../component/riskTab/index.tsx | 214 + .../create_task_group_definition/index.tsx | 321 + .../component/scheduleTab/index.tsx | 74 + .../schedule_form_data/index.tsx | 15 + .../ScheduleFormFunctionality.tsx | 296 + .../schedule_form_definition/index.tsx | 807 + .../schedule_show_gantt_component/index.tsx | 321 + .../component/summaryTab/index.tsx | 153 + .../component/workflow/index.tsx | 68 + .../components/projectWorkflow/index.tsx | 458 + .../projects/[projectIdentifier]/layout.tsx | 176 + .../projects/[projectIdentifier]/page.tsx | 143 + .../app/main/planning/projects/layout.tsx | 7 + frontend/app/main/planning/projects/page.tsx | 390 + .../projects/projectCard/projectCard.tsx | 193 + .../projects/projectModal/projectModal.tsx | 308 + .../projects/projectModal/zodProject.ts | 37 + .../planning/projects/types/project-mapper.ts | 36 + .../main/planning/projects/types/project.ts | 73 + frontend/app/page.tsx | 16 + frontend/app/proxy.ts | 28 + .../utils/api/apiRequests/baseApiRequest.ts | 73 + .../api/companyData/gradeApi.ts/index.ts | 36 + .../utils/api/companyData/gradeApi.ts/type.ts | 34 + .../utils/api/companyData/roleApi.ts/index.ts | 36 + .../utils/api/companyData/roleApi.ts/type.ts | 34 + .../app/utils/api/employeeDetails/index.tsx | 43 + frontend/app/utils/api/fxRate/index.tsx | 109 + frontend/app/utils/api/fxRate/type.ts | 65 + frontend/app/utils/api/issueApi/index.tsx | 55 + frontend/app/utils/api/meetingApi/index.tsx | 69 + .../utils/api/productDashboardApi/index.tsx | 26 + .../utils/api/productDashboardApi/types.ts | 10 + .../utils/api/productOfProjectApi/index.tsx | 48 + .../app/utils/api/productOfProjectApi/type.ts | 112 + .../utils/api/productOfprojectsApi/index.tsx | 48 + .../api/productsResourceAllocation/index.tsx | 85 + frontend/app/utils/api/projectApi/index.tsx | 111 + .../app/utils/api/projectManager/index.tsx | 88 + .../api/projectManager/projectManager.ts | 54 + frontend/app/utils/api/riskApi/index.tsx | 54 + .../api/user-dashboard-platform/index.tsx | 65 + .../mappingFunction.ts | 145 + .../utils/api/user-dashboard-platform/type.ts | 54 + frontend/app/utils/api/workingDays/index.ts | 38 + frontend/app/utils/api/workingDays/type.ts | 40 + .../app/utils/context/AppCacheContext.tsx | 186 + .../app/utils/function/nameMapping/index.tsx | 34 + .../utils/function/projectDuration/index.tsx | 16 + frontend/app/utils/interface/expense.ts | 10 + frontend/app/utils/interface/issue.ts | 35 + .../app/utils/interface/productOfProject.ts | 48 + frontend/app/utils/interface/project.ts | 46 + frontend/app/utils/interface/risk.ts | 18 + .../mapping-functions/date-format/index.ts | 14 + frontend/app/utils/mapping/country.ts | 197 + frontend/eslint.config.mjs | 18 + frontend/next.config.ts | 28 + frontend/package-lock.json | 19944 ++++++++++++++++ frontend/package.json | 47 + frontend/postcss.config.mjs | 7 + frontend/public/images/dark/ikon-logo.png | Bin 0 -> 54699 bytes frontend/public/images/dark/keross-logo.png | Bin 0 -> 62188 bytes frontend/public/images/dark/symble-keross.png | Bin 0 -> 318439 bytes frontend/public/images/light/ikon-logo.png | Bin 0 -> 54512 bytes frontend/public/images/light/keross-logo.png | Bin 0 -> 61729 bytes .../public/images/light/symble-keross.png | Bin 0 -> 318514 bytes .../public/images/white/symble-keross.svg | 49 + .../public/images/white/w-keross-logo.svg | 100 + frontend/public/jira.svg | 1 + frontend/public/login.css | 81 + frontend/public/login.html | 127 + frontend/public/login.js | 140 + frontend/public/terminal.mp4 | Bin 0 -> 1215544 bytes frontend/public/vite.svg | 1 + frontend/telerik-license.txt | 1 + frontend/tsconfig.json | 51 + helm-chart/.helmignore | 23 + helm-chart/Chart.yaml | 35 + helm-chart/charts/backend/.helmignore | 23 + helm-chart/charts/backend/Chart.yaml | 24 + .../charts/backend/templates/configmap.yaml | 139 + .../charts/backend/templates/deployment.yaml | 62 + .../charts/backend/templates/helpers.tpl | 49 + .../charts/backend/templates/service.yaml | 15 + helm-chart/charts/backend/values.yaml | 31 + helm-chart/charts/frontend/.helmignore | 23 + helm-chart/charts/frontend/Chart.yaml | 24 + .../charts/frontend/templates/deployment.yaml | 53 + .../charts/frontend/templates/helpers.tpl | 49 + .../charts/frontend/templates/service.yaml | 15 + helm-chart/charts/frontend/values.yaml | 40 + helm-chart/templates/image-pull-secret.yaml | 13 + helm-chart/values.yaml | 90 + skills/master-prompt-generator/SKILL.md | 161 + skills/suggest-mapper/SKILL.md | 77 + skills/typescript-upgrade/SKILL.md | 73 + telerik-license.txt | 1 + 398 files changed, 49583 insertions(+) create mode 100644 backend/.gitignore create mode 100644 backend/Dockerfile create mode 100644 backend/README.md create mode 100644 backend/ikoncloud-dev.keross.com.crt create mode 100644 backend/lib/ikon-app-access-management-1.0.0.jar create mode 100644 backend/lib/ikon-app-access-management-events-1.0.0.jar create mode 100644 backend/lib/ikon-app-core-1.0.0.jar create mode 100644 backend/lib/ikon-autoconfigure-1.0.0.jar create mode 100644 backend/lib/ikon-client-1.0.0.jar create mode 100644 backend/lib/ikon-core-1.0.0.jar create mode 100644 backend/lib/ikon-dataaccess-1.0.0.jar create mode 100644 backend/lib/ikon-logger-events-1.0.0.jar create mode 100644 backend/lib/ikon-platform-1.0.0.jar create mode 100644 backend/lib/ikon-platform-server-1.0.0.jar create mode 100644 backend/lib/ikon-platform-server-events-1.0.0.jar create mode 100644 backend/lib/ikon-processengine-1.0.0.jar create mode 100644 backend/lib/ikon-processmanagement-1.0.0.jar create mode 100644 backend/lib/ikon-sdk-1.0.0.jar create mode 100644 backend/lib/ikon-web-context-manager-1.0.0.jar create mode 100644 backend/lib/ikon-web-security-1.0.0.jar create mode 100644 backend/lib/ikon-webservice-1.0.0.jar create mode 100644 backend/lib/kafka-utils-1.0.0.jar create mode 100644 backend/pom.xml create mode 100644 backend/projectmanagement-client/pom.xml create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/DashboardApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/EmployeeApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/FxRateApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/GradeApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportEmployeeApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportFxRateApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportGradeApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportRoleApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportWorkingDayApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/IssueApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/MeetingApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProductOfProjectApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProductResourceAllocationApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProjectApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/RiskApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/RoleApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ScheduleApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/WorkingDayApi.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ActionItemDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ActionsWrapperDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AgendaItemDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AgendaWrapperDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AttendeeDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AttendeesWrapperDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/DecisionsWrapperDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/EmployeeRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/FxRateDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/GradeRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ImportDataRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/IssueCreateRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/MeetingDetailsDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/MeetingRequestDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/OthersDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductExpenseRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductOfProjectRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductPSResourceAllocationRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProjectRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/RiskCreateRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/RoleRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleDependencyDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleGroupDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleTaskDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/WorkflowTransitionRequestDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/WorkingDayDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/DashboardWidgetsResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/EmployeeResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateDetailsDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/GradeResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/IssueResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/MeetingResponseDTO.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductExpenseResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductOfProjectResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductPSResourceAllocationResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProjectResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProjectTimelineResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/RiskResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/RoleResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ScheduleResponseDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/StatusWiseProjectResponseData.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDayDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDaysMonthDto.java create mode 100644 backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDaysResponseDto.java create mode 100644 backend/projectmanagement-server/ikoncloud-dev.keross.com.crt create mode 100644 backend/projectmanagement-server/pom.xml create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/ProjectManagementApplication.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/ModelMapperConfig.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/RestTemplateConfigs.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/SecurityConfig.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/DashboardController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/EmployeeController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/FxRateController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/GradeController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportEmployeeController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportFxRateController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportGradeController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportRoleController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportWorkingDayController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/IssueController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/MeetingController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProductOfProjectController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProductResourceAllocationController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProjectController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/RiskController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/RoleController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ScheduleController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/WorkingDayController.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Employee.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/FxRateDetailsEntity.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/FxRateEntity.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Grade.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Issue.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Meeting.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductOfProject.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductOfProjectExpenseDetail.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductPSQuotation.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductPSResourceAllocation.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Project.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectSchedule.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleDependency.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleGroup.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleTask.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Risks.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Role.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/WorkingDaysDetailsEntity.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/WorkingDaysEntity.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/EmployeeMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/GradeMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/IssueMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/MeetingMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProductOfProjectMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProductResourceAllocationMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProjectMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/RiskMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/RoleMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ScheduleMapper.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/EmployeeRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/FxRateRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/GradeRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/IssueRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/MeetingRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProductOfProjectRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProjectRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProjectScheduleRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/RiskRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/RoleRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/WorkingDaysRepository.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/DashboardService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/EmployeeService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/FxRateService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/GradeService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportEmployeeService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportFxRateService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportGradeService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportRoleService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportWorkingDayService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/IssueService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/MeetingService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProductOfProjectService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProductResourceAllocationService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProjectService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/RiskService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/RoleService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ScheduleService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/WorkingDayService.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/DealConnector.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/EmployeeConector.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/FxRateConnector.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/GradeConnector.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/RoleConnector.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/WorkingDaysConnector.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/DashboardServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/EmployeeServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/FxRateServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/GradeServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportEmployeeServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportFxRateServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportGradeServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportRoleServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportWorkingDayServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/IssueServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/MeetingServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProductOfProjectServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProductResourceAllocationServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProjectServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/RiskServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/RoleServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ScheduleServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/WorkingDayServiceImpl.java create mode 100644 backend/projectmanagement-server/src/main/resources/activiti.engine.schema.sql create mode 100644 backend/projectmanagement-server/src/main/resources/application-local.yml create mode 100644 backend/projectmanagement-server/src/main/resources/application-server.yml create mode 100644 backend/projectmanagement-server/src/main/resources/application.properties create mode 100644 backend/projectmanagement-server/src/main/resources/application.yml create mode 100644 backend/projectmanagement-server/src/main/resources/application_old.yml create mode 100644 bpmn/.gitignore create mode 100644 bpmn/environments.json create mode 100644 bpmn/folder_structure.json create mode 100644 bpmn/lib/readme.md create mode 100644 bpmn/package-lock.json create mode 100644 bpmn/package.json create mode 100644 bpmn/project.json create mode 100644 bpmn/src_ed3d5e4f-1ea9-4008-92f9-6d09cec9e0ff/readme.md create mode 100644 dockerfiles.yaml create mode 100644 frontend/.gitignore create mode 100644 frontend/Dockerfile create mode 100644 frontend/README.md create mode 100644 frontend/app/api/health/live/route.ts create mode 100644 frontend/app/api/health/ready/route.ts create mode 100644 frontend/app/favicon.ico create mode 100644 frontend/app/globals.css create mode 100644 frontend/app/home/components/CTASection.tsx create mode 100644 frontend/app/home/components/FeaturesSection.tsx create mode 100644 frontend/app/home/components/Footer.tsx create mode 100644 frontend/app/home/components/HeroSection.tsx create mode 100644 frontend/app/home/components/IntegrationSection.tsx create mode 100644 frontend/app/home/components/MethodologySection.tsx create mode 100644 frontend/app/home/components/Navbar.tsx create mode 100644 frontend/app/home/components/SecuritySection.tsx create mode 100644 frontend/app/home/components/VisibilitySection.tsx create mode 100644 frontend/app/home/layout.tsx create mode 100644 frontend/app/home/page.tsx create mode 100644 frontend/app/home/projects/layout.tsx create mode 100644 frontend/app/home/projects/page.tsx create mode 100644 frontend/app/layout.tsx create mode 100644 frontend/app/main/configuration/company-data/components/grade-table/index.tsx create mode 100644 frontend/app/main/configuration/company-data/components/role-table/index.tsx create mode 100644 frontend/app/main/configuration/company-data/components/tabs/index.tsx create mode 100644 frontend/app/main/configuration/company-data/layout.tsx create mode 100644 frontend/app/main/configuration/company-data/page.tsx create mode 100644 frontend/app/main/configuration/employee-data/components/employee-table/index.tsx create mode 100644 frontend/app/main/configuration/employee-data/components/employeeCard/index.tsx create mode 100644 frontend/app/main/configuration/employee-data/layout.tsx create mode 100644 frontend/app/main/configuration/employee-data/page.tsx create mode 100644 frontend/app/main/configuration/fx-rate/components/fx-rate-table/index.tsx create mode 100644 frontend/app/main/configuration/fx-rate/layout.tsx create mode 100644 frontend/app/main/configuration/fx-rate/page.tsx create mode 100644 frontend/app/main/configuration/integration/components/AddIntegrationModal.tsx create mode 100644 frontend/app/main/configuration/integration/components/IntegratinTable.tsx create mode 100644 frontend/app/main/configuration/integration/components/IntegrationMainPage.tsx create mode 100644 frontend/app/main/configuration/integration/form/IntegrationSchema.tsx create mode 100644 frontend/app/main/configuration/integration/layout.tsx create mode 100644 frontend/app/main/configuration/integration/page.tsx create mode 100644 frontend/app/main/configuration/layout.tsx create mode 100644 frontend/app/main/configuration/office-details/components/tab/index.tsx create mode 100644 frontend/app/main/configuration/office-details/components/working-days-table/index.tsx create mode 100644 frontend/app/main/configuration/office-details/layout.tsx create mode 100644 frontend/app/main/configuration/office-details/page.tsx create mode 100644 frontend/app/main/layout.tsx create mode 100644 frontend/app/main/loading.tsx create mode 100644 frontend/app/main/overview/dashboard/components/ProjectsbyStatusChart/page.tsx create mode 100644 frontend/app/main/overview/dashboard/components/Widgets/index.tsx create mode 100644 frontend/app/main/overview/dashboard/components/activeProjectTimeLine/index.tsx create mode 100644 frontend/app/main/overview/dashboard/components/milestone/page.tsx create mode 100644 frontend/app/main/overview/dashboard/layout.tsx create mode 100644 frontend/app/main/overview/dashboard/page.tsx create mode 100644 frontend/app/main/overview/layout.tsx create mode 100644 frontend/app/main/page.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/expenseTab/AddExpenseModal.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/expenseTab/addExpenseButton.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/expenseTab/expenseDataTable.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/expenseTab/expenseMainDataTable.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/expenseTab/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/header/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/header/type.ts create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/issueTab/components/editIssue/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/issueTab/components/editIssue/schema.ts create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/issueTab/components/issueModal/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/issueTab/components/issueModal/schema.ts create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/issueTab/components/issueWorkflow/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/issueTab/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/MeetingDetailsForm.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/components/StepIndicator.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/components/steps/ActionsStep.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/components/steps/AgendaStep.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/components/steps/AttendeesStep.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/components/steps/DecisionsStep.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/components/steps/MeetingStep.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/components/steps/OthersStep.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/components/ui.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/lib/constants.ts create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/lib/utils.ts create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/lib/validation.ts create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/types/index.ts create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/momTab/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/resourceForm/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/resourceForm/resourceModal.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/resourceForm/spreadSheetFunctionality.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/resourceTab/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/riskTab/components/editRisk/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/riskTab/components/editRisk/schema.ts create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/riskTab/components/riskModal/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/riskTab/components/riskModal/schema.ts create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/riskTab/components/riskWorkflow/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/riskTab/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/scheduleTab/create_task_group_component/create_task_group_definition/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/scheduleTab/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/scheduleTab/schedule_form_component/schedule_form_data/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/scheduleTab/schedule_form_component/schedule_form_definition/ScheduleFormFunctionality.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/scheduleTab/schedule_form_component/schedule_form_definition/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/scheduleTab/schedule_show_gantt_component/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/summaryTab/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/component/workflow/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/components/projectWorkflow/index.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/layout.tsx create mode 100644 frontend/app/main/planning/projects/[projectIdentifier]/page.tsx create mode 100644 frontend/app/main/planning/projects/layout.tsx create mode 100644 frontend/app/main/planning/projects/page.tsx create mode 100644 frontend/app/main/planning/projects/projectCard/projectCard.tsx create mode 100644 frontend/app/main/planning/projects/projectModal/projectModal.tsx create mode 100644 frontend/app/main/planning/projects/projectModal/zodProject.ts create mode 100644 frontend/app/main/planning/projects/types/project-mapper.ts create mode 100644 frontend/app/main/planning/projects/types/project.ts create mode 100644 frontend/app/page.tsx create mode 100644 frontend/app/proxy.ts create mode 100644 frontend/app/utils/api/apiRequests/baseApiRequest.ts create mode 100644 frontend/app/utils/api/companyData/gradeApi.ts/index.ts create mode 100644 frontend/app/utils/api/companyData/gradeApi.ts/type.ts create mode 100644 frontend/app/utils/api/companyData/roleApi.ts/index.ts create mode 100644 frontend/app/utils/api/companyData/roleApi.ts/type.ts create mode 100644 frontend/app/utils/api/employeeDetails/index.tsx create mode 100644 frontend/app/utils/api/fxRate/index.tsx create mode 100644 frontend/app/utils/api/fxRate/type.ts create mode 100644 frontend/app/utils/api/issueApi/index.tsx create mode 100644 frontend/app/utils/api/meetingApi/index.tsx create mode 100644 frontend/app/utils/api/productDashboardApi/index.tsx create mode 100644 frontend/app/utils/api/productDashboardApi/types.ts create mode 100644 frontend/app/utils/api/productOfProjectApi/index.tsx create mode 100644 frontend/app/utils/api/productOfProjectApi/type.ts create mode 100644 frontend/app/utils/api/productOfprojectsApi/index.tsx create mode 100644 frontend/app/utils/api/productsResourceAllocation/index.tsx create mode 100644 frontend/app/utils/api/projectApi/index.tsx create mode 100644 frontend/app/utils/api/projectManager/index.tsx create mode 100644 frontend/app/utils/api/projectManager/projectManager.ts create mode 100644 frontend/app/utils/api/riskApi/index.tsx create mode 100644 frontend/app/utils/api/user-dashboard-platform/index.tsx create mode 100644 frontend/app/utils/api/user-dashboard-platform/mappingFunction.ts create mode 100644 frontend/app/utils/api/user-dashboard-platform/type.ts create mode 100644 frontend/app/utils/api/workingDays/index.ts create mode 100644 frontend/app/utils/api/workingDays/type.ts create mode 100644 frontend/app/utils/context/AppCacheContext.tsx create mode 100644 frontend/app/utils/function/nameMapping/index.tsx create mode 100644 frontend/app/utils/function/projectDuration/index.tsx create mode 100644 frontend/app/utils/interface/expense.ts create mode 100644 frontend/app/utils/interface/issue.ts create mode 100644 frontend/app/utils/interface/productOfProject.ts create mode 100644 frontend/app/utils/interface/project.ts create mode 100644 frontend/app/utils/interface/risk.ts create mode 100644 frontend/app/utils/mapping-functions/date-format/index.ts create mode 100644 frontend/app/utils/mapping/country.ts create mode 100644 frontend/eslint.config.mjs create mode 100644 frontend/next.config.ts create mode 100644 frontend/package-lock.json create mode 100644 frontend/package.json create mode 100644 frontend/postcss.config.mjs create mode 100644 frontend/public/images/dark/ikon-logo.png create mode 100644 frontend/public/images/dark/keross-logo.png create mode 100644 frontend/public/images/dark/symble-keross.png create mode 100644 frontend/public/images/light/ikon-logo.png create mode 100644 frontend/public/images/light/keross-logo.png create mode 100644 frontend/public/images/light/symble-keross.png create mode 100644 frontend/public/images/white/symble-keross.svg create mode 100644 frontend/public/images/white/w-keross-logo.svg create mode 100644 frontend/public/jira.svg create mode 100644 frontend/public/login.css create mode 100644 frontend/public/login.html create mode 100644 frontend/public/login.js create mode 100644 frontend/public/terminal.mp4 create mode 100644 frontend/public/vite.svg create mode 100644 frontend/telerik-license.txt create mode 100644 frontend/tsconfig.json create mode 100644 helm-chart/.helmignore create mode 100644 helm-chart/Chart.yaml create mode 100644 helm-chart/charts/backend/.helmignore create mode 100644 helm-chart/charts/backend/Chart.yaml create mode 100644 helm-chart/charts/backend/templates/configmap.yaml create mode 100644 helm-chart/charts/backend/templates/deployment.yaml create mode 100644 helm-chart/charts/backend/templates/helpers.tpl create mode 100644 helm-chart/charts/backend/templates/service.yaml create mode 100644 helm-chart/charts/backend/values.yaml create mode 100644 helm-chart/charts/frontend/.helmignore create mode 100644 helm-chart/charts/frontend/Chart.yaml create mode 100644 helm-chart/charts/frontend/templates/deployment.yaml create mode 100644 helm-chart/charts/frontend/templates/helpers.tpl create mode 100644 helm-chart/charts/frontend/templates/service.yaml create mode 100644 helm-chart/charts/frontend/values.yaml create mode 100644 helm-chart/templates/image-pull-secret.yaml create mode 100644 helm-chart/values.yaml create mode 100644 skills/master-prompt-generator/SKILL.md create mode 100644 skills/suggest-mapper/SKILL.md create mode 100644 skills/typescript-upgrade/SKILL.md create mode 100644 telerik-license.txt diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..839c2ac --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,39 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ +../.vscode/ + +../logs/ +logs/ + + diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..c604e7b --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,51 @@ +# Stage 1: Build +FROM maven:3.9-eclipse-temurin-21 AS builder +WORKDIR /build + +# Copy the parent pom and all module poms first for better layer caching +COPY backend/pom.xml ./pom.xml +COPY backend/projectmanagement-client/pom.xml projectmanagement-client/ +COPY backend/projectmanagement-server/pom.xml projectmanagement-server/ + + +RUN mvn dependency:go-offline -B + +# Copy the entire backend source code +COPY backend/ . + +# 4. Build the application +RUN mvn -pl projectmanagement-server -am clean package \ + -DskipTests -Dmaven.javadoc.skip=true + + +# ======================= +# Runtime Image +# ======================= +FROM eclipse-temurin:21-jre-alpine +WORKDIR /app + +# Create user and group +RUN addgroup -S spring && adduser -S spring -G spring + +# Copy the built JAR from builder stage +COPY --from=builder /build/projectmanagement-server/target/*.jar app.jar + +# Create directories and set permissions +RUN mkdir -p /app/logs /app/bpmn && \ + chown -R spring:spring /app/logs /app + +# Copy BPMN files +# NOTE: This expects a 'bpmn' folder in your project root +COPY --chown=spring:spring bpmn/ /app/bpmn/ + + +USER spring +EXPOSE 8071 + +# Environment setup +ENV IKON_ACCESSMANAGEMENT_INIT_FILE=/app/bpmn/project.json +ENV IKON_PROCESSENGINE_BPMN_PATH=/app/bpmn +ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" + +# Run the application +ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"] diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 0000000..5d25657 --- /dev/null +++ b/backend/README.md @@ -0,0 +1,17 @@ +# Getting Started + +### Reference Documentation +For further reference, please consider the following sections: + +* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) +* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/3.4.4/maven-plugin) +* [Create an OCI image](https://docs.spring.io/spring-boot/3.4.4/maven-plugin/build-image.html) +* [Spring Boot DevTools](https://docs.spring.io/spring-boot/3.4.4/reference/using/devtools.html) + +### Maven Parent overrides + +Due to Maven's design, elements are inherited from the parent POM to the project POM. +While most of the inheritance is fine, it also inherits unwanted elements like `` and `` from the parent. +To prevent this, the project POM contains empty overrides for these elements. +If you manually switch to a different parent and actually want the inheritance, you need to remove those overrides. + diff --git a/backend/ikoncloud-dev.keross.com.crt b/backend/ikoncloud-dev.keross.com.crt new file mode 100644 index 0000000000000000000000000000000000000000..dab588394642a62b6f4ff901f23642c25b9bf781 GIT binary patch literal 1762 zcmb7EX;4#F6n^hz1Hv8*s4QU@2+2(Vfnc;Ki))|)ik7GtULX(%CJ&If!4nct<3_0# ztrOd-U!`xKwIUD5zM}(TYm}ZGxiy(CPHYow?`CcfPZIa{x~60ywEf zOF&=*F@^L;n(ld%&xZpGvZ=3Xrs{i%>bHU@698FhdASB+F#W(QKJQg309hY)&BH8iNQlzYpAT zs3=E{GG-XUC1Qyv8ABQ2Iar!ZF2V8{{)}iYaJIML268yuU=Rwp0U?VGW)O$V4Si<< zcaAG?dCTh{$&h7#i_ei;lCV zhs@r&E^NA#AC_Hqn$kV{ki$-!VZ7z?ARb%c;vA|zNB4N8xHW5osZ+ZAp^zIt;l z$N)~r0Op2qI?-VG4G{qla57q+L^`k|oA{Ao5{W{9-~W(NSvgr5!9)T=(gMB_?n0al z4C~ecElb55lZagU34tiYl2opO;~yLXSR%O;h>YP3ViH&k1Z3(m)l675k_A)jVKB`= z{jLB6rgO$vKPcxv^ao7HW#f){ zd3mhQ>V9;0mP9(yE}q`*nDAhR>B_Ac{DHc9sm6v9ZIJ(3vYBD0MEH6>LPUr-oMm|F za2k{c***~jo{p2xEh3L^-ZD)|dwH*Jxw>R`CLk64)u-~}K@eOf{k?uY1Q7|)Ob~^* zLjRbmCsjl=D&qb2mu#gpRg{$qE1ys|@9XH})ArNPMHnEbl})~06Y~Pv&hRg_@~GQq zoE7U5eiL_{611`3s1MG7a-cPfoNc>T`mSmx8Z>ohlAqs}KI+UzS2a!Zpj@bJ$SS>fg(>>Fd{@uxdNQyW|hZ~xls<41_SG=cx^swW;4Q9`9>W3V8uU1`4k z6lP_y*@td*366E{=)vx2Q%ez@Id!lloX}cbec|c=_V|&|?eK7Ez+#t4yLdRbe`s^9 rjV-Hoa{Jlmg4g#=tB;<&kt3d)UqjQFC6)$ndU`u@u29zFwaCt^cZMpf;s%$2LMFTXDz*D@l?0<;pcqV)0~VkjSC zQ2!8ng%Gsy`FNf4@&9=Gzr|z(WFK~NDU-xaUdG?T*Tdz4 zRjvQ%@_#?F&mUdZx3>Jpp#FP_KgRxtgsHi;)nAC={#P+w8yj7HeM5VDOI<5nV?#?r zD~G>mO7VA1^{uTO?5r&;4DJ3x3*p~sF>tW{i{|A2PIF^BYe$>EP(uIjE3q@Qbu_g9 zt7&2QpD44pv9_`|{EM!U{X5z|Ci$;)(EZyw{(f}-)>QqYKX!(HJ2;ZR>)3|@nmV}t z#q?19n;QPk0x17YJ%2OPe`}3~F8YQx4yJ#(B>#3+EI-!iU#_XYU70p^)@FwKf76eD zN6SY)983-E|Kbb%trj~&8*6)02Wz{(`p%?(_kHXQ?VL>Y|7sQdt)sEGG5s&&=>3;i zg7DFU{}oH@ZR|{~jQ@-DzeXPT|0->%>ty&>J{aTw6#nqsbbsTyng62IA5CdLtc3QT z?ws~t{Q3V5gT`CC{bisaAQGQIK!iRN{;!Df--QAJ8ykUtga?`b6&?f}9jt|{t&B{K z9qkP1^euGl?ei6-WA0)af?ki2F9yXS?iJ(;H6-Jc2 z>=fFS67L)pv`HK5T(2c)7`+bMvW-+Hw@5w)Jj1Rd|uGJ|<_1i`{MF zgth-vF=~cDYNqw;7v7g2i)(w*1vptvt`J-Ce&7d{mic<$g;z*!UD@2s><&)f>L6MGvChayP2na702#E0CS;K#c?h+s7_F)`i ze}vf&Yxs|#|4(xmQ+sq@>BaOKNUWsAw>^$#@sEZ{gZa%#cTio7b{n_gp zm-)HkeZ>R6li_XAhm6JCWNIpuEpTmQFV@sRn%ok=<(#a^E3_Pay6`3uxaY%DbJ_@V zipAyNAZW~C8uCk*9(sVmo^z(UaoC`-*`o(3@;p>Ju%(}440C+9Un^!JLU=V# zj!w00W<|T2cHD+WU8x9tR0(Mt1{q1CArkL~X@xj3s&VC}DTTSOVy9_eE}FmC(Oe*a zRLjahr2`R`oNFow-t?g|(#yhNK~bMhh}u&J1@<1EL`o)cL1`^t7r7@p<@2HOGqtG3 z7G32@r&y&(4-Z%U*0(@nxW(Y?87hnbLT35pxu4kx6{4!9jZvGRn+0(6`%AKJYpgXM z>WyLjzUTYllxMsC+m{M;8diH>ak+Pm?u2=fFtmHD0<%*P6x*S0Te26xqM6%G20md- zR*DULJJDZIN1f$#lYTD9yvL}GDW2L4%QePuB0pA(KImk_iPpU(=#v0HFA^IJ7QYlm zaK!)380-i8+RLu5Szryb?@K+1*FN@TO-Lja>A{Q+O9!U&>ZkuTL!=2u$u-D= zMqoM1ePLf~hefjopl^~L;mLcgfw_Nl^dZ^bVQZTU2_pw1@31F1e8*JNOux0JTN}Bv zQa{VVQA=z3&I5Wj&PBL~G978rH1KRocUUV!ZY?7pfzB7{25Y87!E`%3QsL0_HP#tc zVZ$01qlXi2n`?Z;qcWR-azSEi?NrgXN}HE5ZODUcMy!doSRX7do?yqTEV}3GtTdPH zk89U~*g4kmK>FSrFuWOte0?l*%(HUAKsy!*QXPyU%Cct0ybN{RsO@b79-YrdG;899 zu7}H+lb4@)hbBqTFlCjcy&WOAL!Mc9b2n?aq(>QXf??}M_vh@A2g+KhuR|TWu1DTP zss__B1%)#jES_PQSrl#=!~41rn5Xe4)PMVnA{qE>$w?+q+Q40NO*1h;%+vZub)Vuc(K(+Bg``Iw{bX8L{8YjVBBrDz~9@NO681 zPz@z-7i?o*7wp0~_c7#x_uH(YkD#PbA}#Y;7UB+2J@4+r zQL%;un(az}J$GAz{35FNQbi3d0J|N2|5BtD`^|5TD2y~6Ew;Xg{CbfSS|rXRNRNS% zhMC#Cx&GxVx8@6YYTBW) zwbfwkk(T1NNCVdu3knzlvh_7~w8Jv%46POvn|0lVR+??_S~GM2qS5Z?;Y~@deH(euz8DVXqx_wy6EKkr{AY$vRRE)?HT5 zfntv}a-uVgof^HckUb>Aet&WXT=ahQuVZHOAw;%a#qpsDQi-MiRk%hAmKIXaUP+~4)V!M|ZSg^1;)tN}wmmNKFJ~0&;BF(Is zf443^lnaXcQT71fx&02-{)1j|r08Dih7=v9HY<7Qll!`lXh*pxdu8^Q_s-SQ1;8a< zy>`y{>2uGxw)OU#`NF$VUY?NpHo}vw8f7y*0vc7UwN5`!T$hh+v(zQf$XfZKYJidY`f>xLULb#waeA$z@B2< zv?^y^c?j?B1`op%QB_b-HLv6V4GV+jiyn1*cg6A=1D3X*%eR$~83mt#x@CI0SDjeJ zr-a4QDvGP2y~HGsD2wiDh|AdGQNg(IA$40&hi{D8Ybc5qkrY0 zU%aps0iXrHR=sc+v9p+zE;2hM;-C-vzbpFJ;#zMQv*78u5O-f(L-o)T!FDKPu!L*^ zhc&&lJDvutbY87Pe>ZG2m>r$xRKD`mc|+B`1i(Ivy?pVGTwCjw!8*>ZqFxBRUs}2Z zw#r@BKX&{XMC5?NzAr(6fEW_|8<6t<1QCiKx$M7Uh(5JP9qa+r_ehT3Do|-yHYXgR zaD6)W?T27wMDjGYx=uQbv|Nd1ahP8*PP?n9Uma&^4_6CJXPSXa1;*3Oh3N&2PD?lK z({D1bH)AJeb+M{~V6ksMoSco;+}9u5_17-Oy{$XozC*oR@k6QTDoYg!&dLo zhqhB>rgs$eTLdl%$jqO_!K(1I+20lkd1AmJVG%L{aF}DO>n#qdV4V@D0j~ST{he)Y>U({!=mi- zYlxmUo+*zxqP74b-4g>2Ej#C%!o^ais<>6%Pfohd7|s$4el3`hR{nT_fk^|9J&JOs zv3}ntBdHR<6O(4`wz9iF}E16PtLNrbak|5kk(4=B^16l$1dBplIpiSqYc36M!{ zv}ydR&(|YFdOBd)!)Vnk$%B$xuMqX=;7cx05dR7D4pqb<#mmT|PgWClGv=@=`&vI2 z_Bq!ON*JpW9nuvGSC0b|0cn>4lX0u}2Iv0K6Y1-=*Oe9*>OH`?e47&=hUjQlT`tLF zAsU|3S&S5CyEkAwV{;NO+6D|BsaE7So+Js5Ng0pTXrU!7p&08(fko(dhVUTLv|i$! z*%i|gngkhz53=e ziarMXcD(;g()R_0&sZwLB_OcmZjxry?W|V&;r@|iqt=Q4~ z6HKPu`-LN(9%^VB){J#t8zEbMg#d{ehXBbqE1d_OZQJ9((NY*)^TNLejYdi%pl_lh zf4VT8my!mQF_#!QYU<#hXm-OqGKQiuY?pxkM(M}`rz*ZKJdVk68g948CJ!cyG#Pow zB18I{b8LE#lE87bGJw5EF$0Rm^138P^9n2=LbrT4l$-!Q-*UU!sKi$Bd7A7FC%Dcc z1zPS))r8qMUrOnmlyceprnm{}>zsCxh@{vgCFuz77Qf$jv7(;=)kAi@-&IoZL|&IQ zU($wntcQ+d%YxAYXEXzXvgz!Tm~j?=h!s<&E1!}Qd&zDtS5cl~She1J{LJ(b5joc2NSr{QP1FK>!8N=aSwTv54XaKoh2@}sTvwOaWEJVYclc5(+{?p4+ z%H?r%#iw{2b6F+vCcR>(dLM(}&n(=#kV3TcJctu;pRxlsPx@KmpXj7!v94EbH6j!7 z&!DY`0D4XwI9j%oyyV7Q^Ux}EhD1rqR`#xGlQqL!SEB}+2EH5R^cMb^t6QRtVE3n# zYgu7}Tuu3d7~fv_EbGJpO}bTsD)`DTyo+Q^l=m8yem!^auDhp#yQusNqqLx|CE(qq zspHwSkbSzA_lWxe+*S1ly)Jijy*35mQu2?WnsSYBW=<|chZk?8JIU98s|D5HJ2Dif!N!cr2F&gAhs9$JTV0F!2TW-T}Lw+OYTMgx-( zA(G0Kfk_7ays;#%^2^y(RF@I1-bH#RbvUw~YI{0U+MYmN&HCcJG?&_Rq@(!u{tEt5LGQ0s1Tk1VZFNJGe8I7) zJeTo5Jdb?STtLhDzE~9)In+>jZ;N$;Wdqr=-r2^^XtT;ZP2kjkZ^=Ob>&P{%CGSx=EO%*KPMbkKDi#0`MKr-hgVQPBD^58Ffj^xGU$>K-C-1b zwNK!_Lf|Wy8wtn($dTKEIBW&z*gi zx$>uw)gX)~t8Il1G*O|OYu+PQju#)A9V*bKpZ-3?C;|hMK9H5@@K0IyEtAI-PP~2- zv5RdxdlOTdP?_kF@J;sgZuUACdMBjT^g1`E0h>~NS#n0%nbhb{xu3r$Wktn4UOJ;b zjojQBdi23XQC5$)t)2xAJk#4mm(_GJB9dmxeQ`LAj7LX4Z49l5HDX69cZ<1Th3}r{ zfm%n1A-Gh2A;YgV;pw3k5zw~b=Rt%uOW@aD02En+`#!O?Z~LY=2-G!Y@e(k2GH{G! z5)}frduI1^&3Z~7tk7mk@e0ntckb@}6!#$Uq;i{O|5NzeMnTXL<>|$iQ z6infSXs%J%z@Z>+hcdaEWDm(15?_yizQv`_kK%9>`t@Gt{MIHhvEGPejf`yG7_xk} zta)?C-o@Ipeks@L7x@nQFVHEWoG9jli4*q%ntih*H4k#HQEoK^KF$LD&?YMEI( ztC={ECS2>f`ryiq1W+k67PHY8<(onyyr%4j`t zOUBR@*wU_hmB7ob7S*-BH$ICBQe^ptkp-PItdx_glO2-WA3uY)hMA$AquOEu`-dwF zc@FO=nuX3jZ*{@LN-@5P|HQg=n$BUA18>*pg>3A%vF&`$DPEzQm&@bL`dQIbN~v;h zMoue7EMYq+|C(_{1(~ypC#mCvQ+3uXX&*;y$GYw`o0a=CS8o$AP**ub(n0P{H}6A^ zQBHbQ8#_9Kg(=PcQ>MAb@-Xz-hq8xQHUqZx$j&&^eY$m^+tia_sLmv_OMujlFP*~k zH5`!W6u>KgCvIt^#*g37*c9BH#1$QdilCFUT4*<0a~`chKCH zS=*4kq91OC=G{EB^cQbxmn3MZ+Q?RB!D>b@2YS9%OD%u})| zyvX*lRW_(NKuYof9JQ4!JYTbs7{1?tSniAkY( zwo^}G>ae^~@dO>;SG1H_J;M#a5ephIIL$W1Sgw5d!3v26M3F#3pn=n4|2fM`3UnPp zaj(1)YTtF0?e|H^FE8pV-44MW+@bGI!F-O;9&y;B3V1=fBvKVTDW?>+nIwS38RArK zM}ys|!C`WuXOzr7QnlO_tgPY8B7in85uX^!2IAf~J;GIW6iL!LqJ~S?aQDOq?6#7w zmrseX7A#{^H_+#w;xx-L0gaXb%3sPh*O9 zKWp0Oy-(Xub4Pl6yWc$r+0z{fhN3|ECE34FKN_xDW)|Rk#(_FEE9oY}zA8Oc$3(hZ zqQYGNR$0JpWt2RodNW*LHGv)$Xs)(LI*$bh)cJ+En`1RV$gfODNJhY>pA^VVPLP7N ze(=NhE2b@Kx;!{dJF?E_!4(=H%4D2()~QKyig`Tq@o|%sx|3dFsMSrh`q4Ren!mmQjYOTcV8Rf)bVjUjDs(zDGaa;kKxz(()LZDK&N9Q5`d)wQ!U;h>3HzK6xzc4W^i58-<83PYtua zE_s3$c6X0MIvYF}EsU2uU}QpZXie4Mf{)OcoYD5=+sh36mQH->h+S&AwqzlMtiBMI zTuxD7Vr?)|G9d?B8U2jRkeENn)@Ft(PsH>dWG-MFig&x}+A|9@A3Z6kS0@{rgp>TK zFlE0NxrvdN!Y(uN8v|s-sog?_t?YEP+Ulr&@2HPPNdvsBHG2`l@4{Btc_a&NID zXz^;P{SO$@9#T|lV4h;Tj=5Vq$16R-xPZkFZ6b5&^co4rjrFRxRQ(G4n;Gz8;*Wqa z=(qvTjHHDPQ&o)f$W1RCQi~x5HGMaJl~scg2IpUvtK?(HDpDFat3>dSRUZ)K&H#HAYu*DcTYs`z>W)QR)3z`~Uh&Nz)OL3MkabPnvbhU-Cw z!|qlU3Z@dU$Wv=c$0JOA|258@*^AuZN+6d6;$3xPHo>dJ1k~ z%qvBQK;tXeR3QmWQnqopXckOOJ755KP_4u8X79Nu;4Oqc!|XNK0q-y;zONqbt?{Pib@@h~_Zq=53ZhKSM* z*77$V+bPI+Ncu{RV}jM~kQ=$^-qjGk>=!7?X6{SK_@6^J_OKU}U&K_&4;g7?UjxST z9-!OgvSdm7_Bk{fFp?9<7MT;`lVna%pE3wy;$y4Oa;r>TV|jk&jfSJFi_20u65F!J zuT=oVuoZawRU~0N)wkS#MbinYn0^20pzvfty@4e`L~8S8ULtmI53HSlGLT8T3!7x9 zvKV1rT+t>Dfjnz?nC~DqyR|fG=sAfdce{{xM z9ET;q$bLOGTXrIW>ly6^6yp%m4|h1`S;VwWAU`mXa|)Zzy^#j^0B&)L-D?1}M4IBE zZ=v0>d$bWUQXUd!G!h<%CN9u>t)D!tbA`9K*i5vELak#^1k#`$V+%J(c)Kk#d^w4B zzRH0TKXUi3MGKO|g8LNt6SNXu?*Y0|f(U-2I$~F8@22)?ILM4-C4_$htmV61X-pEO zj|<}Hp}aw>UK6h|i1tW9f9mR=U7St|6vRe;#cn9mR+A_Mf@F5r0k$Okj8$!r5xG99q z&A&SP%#297k-Kw%cQR4=x9ytGk4*M z0EY={bjooNL=C(Fb^c^~PuO$o1>duzK{=2er<`D|Mv*;g(=?`;lVjj_Y>m?hzS}yXqWMEX+I|QTy0@gb{-Yqz;5wq44r|9A zUb;CgK(Z?;eeSK2pzKd1IesTG@NYsE90eK` zUkzwe^Lv*I4il~p-v%ov|G=@bjq_d*4#_Woq>EoP@sV`CDo*xqMZZ&rY`NKMa_PKS z4v+gvf2B!nUejp%nwu(1kEk1~0U}poAWKMdKKpB%__5bs;W58Vd)pB8F*MWCrIufy zn@iUDj$Z`Y>uvrZdtSXL$0Vd$adgI^HOc%{l82{k+jI`YC38J7Y=or=J3o#hgQYV) z2M^3Y50FnT4}|s9{Bc%@cwGe&NScyw(kieW+*GVzE$AC=wUhJIEiKlwLima&b}r8(bQz04UZT~DfOiLJPJz%*D8r0y zmvu%6SX%GU%$^pB7xalyczg6qdqyw9Wbeb#7eT%bgl)O)Hj=m5}}y@sIAuq}Ztl31UUZ+c_iE-AICzBS1yRSR_@e|CH#*eUwM=N@TI5@whqv9K*5a>I!vY{G7w7CdN73U8d*uO2oIEBk&Bf^w&DcSYXP(rhRF-eGVm+xCW)9i>U2Uv6RmXDE^DaIR`NU(ou*sm&aKOT)z>;*(MY3mx zgElL{@%XB(;2Uz%xbRAoYO{HKTYeJ|BW>WS!kHt;wLpvgR6Eq;U>13W8h(Z?{F>w zstZZSHCW%i8y9M5X~(4Y?X!A-(kt#bIXXM{m1B7Ip(3kwbApdxjc9}5>b_1MFo%)m+`Vh~1gh(t3ASm37Hw&rSgITD$Bxa( z-0vx*jLc7DECLl`<`Im2NrCx2r({skCv_?xY|H_2dbeNt^P(Zf>eY>%qqenw9f8g| zO}P$PN7(EDZja?$Q8szb8cEJN&-ATN$U&hrteVX2iE53-+466$HBLLP7@1Le2+^H3trJzghnd`{`|4xl8rpSKn|S+R5q6;jq-#9m=~%bXcs zxMRWF1t&1tFxxPPHQNKqy*5Vy5g3HV?@$4Sa3TdV+Ymf;AU{$U3Y^&ywQnI1BJPlI z`QlA%38sYUr-p<=4yHMN9H`Mx9SVhf!@$VhZWI3FsvpRBf{bcHMoyKG{*D~Ke$No` zD9sE?WT0o-YuwTIGMiCU(tN1XRqA&j79}~sx>|sLp8LM^{V61OT2AD!@ado<(i%30 z&q>*BjnncenfJ;1Yvk)??sR5w|C=yA&nq7ELEkfrW4r_YxUu&qbvKT8=c0~4z>CeB zXVG!f331v@5Q&E#u~?LE?S));ULHKdCCHMXq?xZSax#Y3|Lshq?W zH=->QNl-ho#?50<2IwzIS4b&+#AcgINFp{WW?{@oOpE;9GxZb|-oqHdkHnG`7^J*a zE)gRk^?Gs_#5AiA(x6Q_Mz<{? z{BkJeegF-$30*Qi9L2K84dGc_H^*l>M#1=ci75*pf1IGO5%dG{x}rxtuQr1O}-v5jaNIfX-JwDQolaEsk>i=_epkib2 zpDD*5xyGMw|CC_V{XDi?7XC;umbG>;P*XW%aKZ8?YX=WSRw(mKC2(S0%%){$K8y2} zo%Sti%wd`CCbxfy0%bmor(_0z!1vkAA(dI0GG!d@_~otU+IzWMwLDLB(7!`e`e@+o zGZ^YF^}`xrhRV5Sw&2|_pZWDGP0hmAIOoydY6nsl+HnNo?9uF4wt}bXb`&?4pHQst zw&7W`iC{Q2O)Te7dz{wS+AaHpx>*r;MF+~~Ez5=Gu13A^a@viy5eMTe7z4&<~oyz;(fe7KoyRx@e05rMk~ z)%r{8cYQ>3O8&LkYB>Za1Kkka*9hO?+;GFVv3m?F?(Mh2RcWb6svuXbZb&q`_Fnr}%rovd zm!w^LjsD6PimSSl(3JJWYzr5?p8KDB1t8hQ$%V~uziplU>A@s*!=wvJOGNT1X7lOq za;$_tM{#0)qzyZ3gz$OE6{RrJhwTbygXAb zigDeG-1wAwwlS8`VC81(CUozx>83C|*9h{aq;|3FEVpMvBnGe795UvSoGhO# zlJHOWwf0%xE5mt@r4E&-pzN&nw&-Mfn002Ybc)X~+^~tVzCL`?Mx1#cIXC@N!?qWD$7n(3=WD;=~W;TUF=BDLmu;Wy(s&1dJ8GvuIy=~N287tFVK}8R0Sc|4Qhwm_fF%BUG-MN2 z8$alP%59w0IoQ8UOgwGU=Cc^)Y?_s}tNauUtmhEO>sG%f@qQ#c%mp`AUiFS z;8(;FWURHGXV@5-p7gSBMeLj_9{Es#Hi})4Sg|h)YS$75SzTi`9Hx>zP}8s)KWAIs zx~MECL2%z1e)DE<=3nKS2BpL@K~4bSm;& z5k}ZOhHSmPY$13EGMSUNqT@}D$j7Se0=r% z;uq~gADlZkv$>jRa?`i~$H$)>>x>mxKrSqQ31R&@geSm8S*0$|Sk9Q2Y9HCn-#vLjt!9-%Rbxw&^pR93 zTSoYjF*g$^?|5ofmu78y^A?+;g{odfy_?3UZLp*26&D7-b0#{%u$!u&eoZL7l!e zcKhWw$B9YRmY3+w=kNUw{1dIE%|Gce#y8R|t$~u(cTzq5*zi)K*bk@d&cvB|lJqF5 z((_sIGu3FQ>&gPoIDRYh^Y#6xfbSR|<&!7~BbV$#l(_%~S@}4;oH>eYzYc)uT-Uml zUidR{TfRwn4szlJW*NCDD?jnOlJ}>UTbyii7UM?g35E!M_JWtk+R4e%!S&>9RI$Ng zoh$$%Syc~AUnNiL{hH!GdFwdAUk2}&7Oe5S>*MN+0n>&)W z2pXXPizs)KcTaIlp}d!sUMN(77yKskrF!D`_q1yzg;*G@!wTJUT+e&2LsyO2gIwC1 z>(fK`J1Knl=>g3H^vVT6?;FamXNei)wh`?e0U7PjE;kl|^-i%TQ{qSDgVWnFeA&Fd zIBtL|$k|7SBh0U1q%x8Dhu66s7;0I+JCj(R(3_E_rEX3Hv1P<37}NsbqlQf1V95<4 zzjO$n(={X85#fMDL{gf*DI-He7W0Zr6sbh_GE>jm?b7p$`0r42@>Q5klBg|Ua?X| z04R&m)#<;z-#y6-D6AdNjD@3#! z_dEQaQot~YCYa3_Pgqay(Q!RcgGf|&T(jZ8=fEZ*o2ZKP@$Wvn_h zj|-Ii_Z#GF&fh|7R+3lDS03q$T&7lZiGBK$OqMYY(RHMPJR`%#^4IH(gMMZ|7X!1> znIgnEVh*Z{S#G;$DI9+(XU-N>nfSi`YA8*J5_>5hF>WPy3dXe7A!OXP6hm5EA`ZzI z70_B;@g=bc{$wAIhCpY)U{WyMD3a-3*{MT>%L3F@s!Eg(4D0pAEmiJil0jz*qh3N4+7PwEhm_2fH}%5}eBBd^c8iq_3a^>sOPYU;GT~**7f< zEs=*Lj_m>m(c>n=CVec=MP|+BT1Ez_=)!HM$Ldxv(w4Aa|5;XW2wg#mE0<(Atv#0` zLJE`a_n2TfA21SqVH|(FBh}|zkWaI`vPMTgZn9m0JxDMTef3+_RfqvrMYe5CxqSEJ zxkL!UZfOXGlT0&`YQF9U?vpF6jJuuOYp*t9@Hz`aXhUR^rd&#IdbtCf97kE8F&+N# zGut{FL*#L-No&C`V!cXj+IG|Lg6`?Jhhg2NO{z-j(-IqKJtrcnj1dwmbBirK7n+wZ zu_8dSZ@Ky}l8on~aPdyl6glyo@jfk$&IJWvsFGKR4VrqEQJb<=cI`Vxk_rb1D#x{; z$mfjVEDzag(XtVx=QNJ|JaV>TuCN^_I%wy8q_#1lBCz_{%4VuU@#(}PH6`^f2ONsF z=@xQ{CA8Qot|oLaVvSlMTr!6`(T-F()CE+#mGZew~uQtbx1a%jDM3pqU*b>=mVBsNZIPOG`dr+_>`P6 z0Vuw~$`$3s4zxHnVrU*7$}HNM>kUn-xR%*J)y|RimR!t+-W(tejY|~+cCU=0-RMI| z12ZS2L%$Sbe1ot*SsRP{qysM->A=ImGbDH8a0JHV37Z+rExX34It;5v8o|^qyMgUl zuZ#g*Xsa6f?u6*MJu7io1|N19AU(7P6Q4|N zhwr@LjesbA{jo&-v==#O$LRKmfw?-4h^bwNxG3B!nu7P#n7z)Mmm#58K&mv+`F2z2 zfkO2Oc*)on!4I0bp=8Fb5Z?U+>&a^pX!O)2yXq-f!KbJ2Xu|^*e+GVh)x?%%x@i9b z+aA2FbDE6*%XV-=_@T+=z2bIs!tp6H?Be?JWi#XPQPzvM8=uq));rJGOJ0o7o246n zz`~#J4n?2m+Ajt6aU1bX*u%^EW;F9)^jz4VFX&k}yMk!f51O9gu}3-eq_#MGDgKBp zKUYR-uAp+M@e($`WxI=)qW8>?{*s{fnujz0wxBMe<6^ujIg1;Ig;-#F**((P#|o`b zpXTdiCMu8qTew44qKsb563I});UjdE35)O*$!iW!7j9h-Irm=+$b!A)gaIG5_o8SZ zAcFswF6lp*bKv?P%=z2gv>EVfIH7Ez*k+n+141*QED(&a8uy4Jgt{{QJGtpG+JVN} zg1J;niPJ8ES6#lmWcDt*QqosIXLRDIypedfKPE(AGSkH%vNxEV=Miy!n!Ph=S)S#I zJk#X|eeQAJa-YGozmnVWzCVr+I=V>??M9+SvG}vKN&kaC*Z3_(+G9)AoNtYV+GBT( zU7o)FYw^~s-H1bF*)H58rV{2C*Y;9wSJz>)`Wl1T7x7@TXv8>#R7Tnv9#TRkHZRVv zsJ7r=;MyihMq4ujNGZBCR-&UdR_2^Natx~o)RW<2r2VR~eBxnFAhbSXqT zcSGqZ0j9kOexjcPlfs&6>{G(#vP zX%Xov*R!-Xy%Yu(49?-pQ@w&+;lMn`i!Pi#26^S-=%duf;kkk@aGcW9Lu_!)*_*vx zRhP2tWYGgc(2?d3Q1q!sS|Lu>7i>6WuSJ1To7+gW5XJjfpWv3VW-#Bsz>&Kmhi95U zq{Gc%87)MU^q9@uT5#rX#<`GG`tQF6nS{7s@!6-(F-$DWus1Gwqz|aW?N{=jEl;PH zxw`k*>oEEd@#cS^ceJY6J*0CJl!O+yCabg#qD{4hhC`=*g551wIP?q5FObwvk&McIz34m{o=lVTg{a7`?s}_*s(C$b-LaMbga{exKnp7~o>DuBwRU5wR zX1H3UJv%>=hpC>8!ALDSwZw`Wr)-~K*uv$_7-ZjK0h~KcfAQ7DWL;%tD^NF0yty)L zGhzyuKz3}9PO&-iwDd}W5hC!M)=yt#_DbH;AF^pUiGXp7i0xuEtNpcCyE`C1=)9W@ zYhD0O>W3^H2ojbEHZX8T`^hDsQLU>KcB+b1H9!5#AZys50VvBCPdZrN(&v*^B_x)* z%RxC?W~(!DlHSAza>0TpY@I$I^qCcG>$6An6@!4vcghLIu6)3lJj}Gy@Fqz0ShSYo z?euu;x7!}E_DV%9E-5QY#n;@0qQqi^lCo_wUr4FXQIpH{^TIa3PlPa~<*O7_^iCr4 z?z@iUL=5ePP+v;Fpb&qW6V#9GB+NjO{E|*?!Id5z3_FL++ zSf3P9z29}e$H16m6S2&|W!51FUM)uFd8zmNopIkuM(D>k1dp^9w-I z@cOSt8ZCE`o0${TE&IXa<=Sx<8Vrn{SBfBaytQ6<9AEDi<{TFwnfUIoLtO7V+^uKy!({S&DBUgrSw2U zdDyUf>&eQ7)yxTR!BAD(pFkd(PjNHkrP6o;u!a z!C#>F1YB`WvfXd}-)N!MOlzEayZ}Xwnz9D93tk!WWXOem9 z(Y{ID%)I*$#)tD-%GJKPff>p@$3#IzRP-QvHXoeAM)nSTV*WVEiR|s$96z$w4cQm% zuh04P9Kbh7H$$NrEc=GqmVA(k(fHMp3Artx7~*BqH*MRPhM1Y`jtruLI5~#73gkdo zVCYh5i~?5CGdfn`QzzcDf#wf*7O^ORutWt?iM|QbJ!X==OKRv}SQ1}e0=%X;Np82Sl?k+CSzf|;4b$^T z*1DmbB#wGimd23+QE%4|l(Njuqr(BOzt?Scc$~vJsFA)Mil3lZ;?O87O7q zrWwXim30+U$yAcQ28c~5trdGD3fo}oWVvLKrEl$ok=)8FxZvts9rZK~kR{q4D-^$SJhYl&NpBdFug27gC-xj8fJRqbJy( ze+&#wyd3Uhj48(zbygqC#EbXph3*8W?=}mm=2X$o5bi2jZMo!tIo+M1wj%?iM&oC)U5;Y|6}bOqbuvS zbzN1d*tTt372CFLJE>^JX2rH`+fK!{oeJ;z_CC9v`|WmbYvifOhd40qj^!uy<0o10}wkY%30kHn1KSCI4&>^P87 z!p~j$@*Qz6ZzN^&dEL_g)cP&Cg9C{bMEfE>|g`MQ#uSt z@a`i-Jca~;$u=qm48Mv=f5YhT1aHIX8(Bopv3T$qKA@bSKs)Gig-Na-urYAdyZhGcl*9xEd`R@OsRN+ zQD><3GpoVv`=r}pr4ETm5>``{%ivgx^{2q@H!Ndj`$)K}EL&1ZaY1$r%6md`${2vD zIZISCy{U5iYBdkoC2d=pMtzZ8_~F1E{4E@E0;>gZHjG7!kgM6;x`A}|gi(b?MgD5v zg+Yp2h?d2yzpDcX1FMdRcP`WRF)Q^+^9bi2GkR{c*X*E=9uUC_#wcPd*{c9haNCU6 zyV^L6I~44;9cEpsYq7bSY-l4!+qWXIDq_-%V!24S8FCs{F8&58C~^^6+Vb_y!>Yn% zLXMJ0TEmxCw_II!p?E#pg3R#G?%4^O+((lOI5&$3>K(-rs-gqDYJ;k9BUqLJcgU?sn9=muLUP(qa(uFTQ;@&Qa_sS)SXt{2MgkDJD5B>y3y zW|(x5#$mdLPqOfA2|HZSem{(dut(_PY~p%4IGf;%oy3DXzI5;hwMRdLs!GEfu?GKB zLV2oS+=}&T$!aZ$qy}#P&?4hH;nRPvZ$A?1C74jTT(I6bpjKScn%p#7W)$g`$lv9E zgYa2@H=)y-1w0GJu5=*v1N>YYiJY-@4bacx6cpe1o@)46)}Ck zS1No!9|1UjUNa)Zwvo4>5j$#r4d38TITpDz-2vqW&Mnav zT6q}R(OgiiCJ8-L9poq8zHDk{UE^ z49&#JHhG^iw%#|qrn8(bXSY7Qp5VV6UK@e(BI(ksEe5pOXn}UB&I4zW9LoOEQY!t9 z(AZTvzbn?FG;?h^SbA@<^wwmeRxJnE{pOOkXf5VQ`+SItJ_d{4IMfhs%h9JFaT$*f7n z-E?9NUAKI1tk5#6V!ICy+PUe8o2t}f9J`ztzzW#L zv_r>|$-%*g=xPK7%9FdD3V6D!`*khZ;1$@s!*Bx5;*EeGpTjD_n{s6}2bMYY3~$BJ zo38(+J%44LI%^*fYr#~}q&=Nn%;NnWAC_jv;}cSI*Z*x=yO?F-&NU=W8@G#YI}%W@ zPVi)NGPTsvxzk#mCJ?pPT-{cAIqC(}r&BO(7Bw8B-ZHTQcb-v#)l8$Q{O-w#W1ia8Wn+_$1|wNvS;xo- z@Yj@)_S_kn(ld{P+js$_8QzeBX^ZA}M@w^_3`OJ=3iD(bxA9Gm>SanH?R?pCD_OBQ z7%^|_tkD|PDtQ1$FAQXjyN84ITkl+ens_*Bha)1sp3!3Ld?ulC)%ld;>2UM+71w4C zE|$kL^>WeT;5Ob%tMpFhC-5&>LxIN^cQ3IyqCYZz!ZYEKl|a!PaFVqo7Gv59amjKb z{cy#YE3eYs)Sa{PMHxL(law+Wp(UjXM|3qkb10TB^b&dq_4s9cTmT;Z^)BZm{-A7qis&!@wVZa20^QkpQ6U1>UN zap^of2+ZGQg;XOhig~roNV*NtvfURLkK!?JuMOUl@#2U+PUhO4(Xhzl_g_|e2J0%_ z*3t%a(;8IxNYAgV+re@${nz?glU7 z6D`CB$(c%6F3m@>vkV(}4efy?4pY(2xe>v_En)|DSKv=txkEce z>Vl;1rDw1Q-XrPxsc9B=pP8Xq41+RWX%m|VzFk;=xJUohUct&Lb|Xh@WJMG{VVK>n z5+)~dV?iLpT1`4OCYkMGnC;RDE6EHeSj8v9+Dr=7oP@}mO()EY(+N8y&U{yQ7khOh z_57MGERBF_K^7uQ#O?t-W+y0}rjK=lz=tf=8SpN0SUe_j^IPJRvI9jVdy|^iOfaIW zJ3=>R^Swv+BqX36|1?i8rf92K?In)jT^!v96IMq-kwFykN*k0)dcGx{HC-!haKAw8-zVa#$>OVaU+OdBk}G{+Sp`>WOHa6wxHgT z4e<*uJ(Y)VnMSZc8N6bh560&Z>fFON#)rSn+@L*IQiO@gV94XzP9u+E`X*XE$bM^1XU+W@arMUw;2IPB#!o zQ9lb+VFGN5kA;bSSPG?P2hHPbnxU20s8_V4{5fV^`msLXIFsW%@YMuS&N7jv6|LkE zNlT6wu*f)xsH83=OQ047&MMpoxKVA9GOqU)Q{t646?6Q7k>FKE*&Hx?r+8uFBhNDr z?ix4}K~Xu8@)HoAwMy)xkDzz~-4N14`AgGOk=;ZyyTc=;6eAPEBUrH99jH^ETY@Db}ZnS zqsirHJgYUXToU(o>5~2J`*T3C04E~=0W!{YkM&;3meXRl3m#+d(dh+tiz3M@9^|k~ z;*?@MLUs{$4?65(X!ew(6Ws||^5d5=lcZ3sBDsp@-J1p^uB#_<8i%JDVv?>0Bf(v0 zE;^DfDHFn*#uNl3J;`tiun?5lH3m>ONbjUOpYasK=fiL%#p|W6fa-9>*JG7KLW?1GJzc^!~e%hMakK~*}~{wt*3wF zF#dk)Z-S~Z!L|3AS#hQ!NPheSljf!PU{bq|RE-9#@se)BaUUTC) zyo%dC7Sbii|HP;{s!*nU3UZ%YmbIeOQxjp5c-`v-Y(!mYn}L12Uk&nqx!e`N0>O|r z80ldU#i)~WPfv$)dz!pBMK+)W#H}@1m2<-c2Jc>Ch%zP%uJ%|lVEEP<_cxr)u>#c; zt<-OHlblTKr)bxt7d4vaeEG7sGf#dwxq@CG5L_%xG|nd7}w8>kebVw=>76 z-LmigjfoejF?dPK$u0!{=tnW2mDt<>^f9V&%xdy^);8dkhhg`fdo1+$RJ-lv60J1f ziu@&{agp%&Y>;+T3(XY!Y*@XW_T>3<z;3y^tbgbscO9(A zm`Je)djJ+ws&%lO+{N53sf60?+k|f<2Uw27e<=L4hmK-}-SqtZgOT@oKs?v)qYqB_T2cc5XovE;;y8nQme_I(wp zYc-J%mw82nGO3zp6Gm(hUnFd2`TIPx60Pv?AXGc2pEJpE%AU;Ual&PlFQnT!vBNT1 zXJ7a)MDNTYE;hyA3)qUk40bp))@;VxLLK3rN?iIRt|3Q>|j znDtqhd#2%>(ibe7?1uhf68;SHhMCcqj`M^4?^2Y4i zBa;6W#t!(X8QJdi!1JH|7ro2$?5iq2zM)T|ZOae#1_l=M54(x?ngv3BTuY}A&DmT> z7m7kSI{x7##6Il_#2uo1%M@~*~i%eT2rmSn8qrw&&0FzAAP0_U`W~R^Uuwz zADBH{b=h&kwew&pY9;P49o9peLTPH17PGa{c*Uk>v1n>K|{k^O(-lysyVKgT&dL8^Mu$O zC}|HRLDQ3>S}TM-G+t6aLR^eJ zG%c1}cX+K>CT_{f#hfE|ZI*-<_1MVs_Ua z7UGcAALm7f5nx0wg2YW2NifqYYW@wid_7=n*E2_xo^=T?WsAO za%}?X8L9xdjM1QMiYC6-F7w|GM#Nl3;&QXG2H)i`{A?wdGfF<~Sy=z$BIyE$mR`g*WZrC^hmVk^#p*Zf@}JH(_uSia;2>OzeR7N*GjU+PevA6qLI}>xM^*uK^Q;@<;XNr13|#b?LjVI8IVKh7 zG}sRWq>1C@2M2fiPQSv@D&6WO7p2ag;x~)7iOj`X+IgU+2M2~Ri&=B85)Jj+%XF8qEvu>8sLVUJl5 zyDZeG(T#fpQL-7UWLc!_Z%&n!a3a>KX*klmk4x_@y0>Oot)rCG=-lp>OX8 zEl}DBS}e$Xk}T~VgFi}5hpiRiN6zr0^1tT3&zbetPm3OB4>j){!vn|4nl;jWSp+|E zz1ao*_H}SJ>3Od<+1^1AU(Rl7`P=kfYVFU5iSF+?x96ok^Qu4!UhSzqu_?dk7efMlBKzlAdPzJO3Dn4mJIP*)ftY_MpZZOCBi{!x^;f!=?caI$J z@-zYOm$-#*qa7;9aoe5SuUl}NAq+JFkBD#BK>f1A;u|9~M`{n&9V`(qeY|WRND_>8 zifSE~I6!-@pH6~0jW|Xm(XVy?)iI#}#a9NOikqbHhP~`gCI00Gek=e>g3B7q15QKb z6&|i+=01j@Ebqr>+C3uNtD&V`ZR5V^bo}_+4yN%!e!-r%f_tUcxEe=pqN_AY_<$&R zE>&Dmo*hGX(SylJW!&Y(#Ds>&qq(VRI*{Ky!<1qxG>WloCh}P0?lPK2&obX!a9=&$x@bet_ONNR3EO7&-s zd;pW>r6nntMzaCXmj=-Ys{dV5YPN4=qwGsE%n8?suFV(K_C;LpNW$Yh5t>Zh8@AKm z2{hA9@IAwU$JyH%&%}oupzf7EH<6#7vCB6;+TT56#Ce^CvqE`^P`&9#Uerp9C9n4W zJk^jyk9zyV)xWXea{kGXCKvJ*&i$4(O=@&{{*`e~Bs;g0HX2-vLdv`60Wu7}C@A(B zCN6m3Ko=1SeXroRcxwTNb1N~vp7+qT07B(bcniF%9>z%6CMVpbgF$TR4~LkmJ@C9i zWquNg{3oaTS47?KdXq2WOV>zA71?{}&!mo@pnoq1*tCfhM}pc!PYca`YKW=LW@G^ z%Zc2~`s=sB5aq6nJ4|ew;h^N}msfe}DrTid3qT3dwb7fy(YjMib@j#P$LAaUPt1t} z`!7Op0G&vJetGvv_EvQJ#!K2oJ?Je4<4Z}>NtS;3);g|m8d2PRZJeO->xE@nIkv`I z_x4F2Jz<3i>MlA>LCk7{2K3V(?z!&sh;cWTx!a;N2^LewVOcBIVqma{OvaVNM0SvX z+F)E(YO+MjPRl)f*ElhMLi7{XyW|kVE`dHH>*0|euMcnEst6n>g$Aa(WG7i+Uy3zR z%LDz4+!xqYCyJd^nH4#h=J9u?r|=UoWmTtVOmdvJ-Cebe^HFaY1A8`)8AK^77qUfzpcm?`to)l;`qZGw$4y8v^w>QTeP550TEpN4p(8QaL!g(s7=0Nlk?&3qkBgLuHwr7;w;1G1NcqS+6rx(3#fX<* zQRs-4V*6=AeZDij=ZN*0>vK2EDe-*g^ET-GF7`O7w_e%(d)Na{dR&xj~+PiP|Uf*F;s?_7jo_42G?1k3WJN?cMr@0~90SZHyCrgkg;7liG%d>*L ztqI9iF`IPF=Ec?^+|-IO?gZ^W!-JM0UcBHZV-+b8BkmpXwdQuRyJDZayy%o z;BRgjKzz+v$Ak>KmUCr=O_KZ4;S=?`L%kB)vQC$Hp2ad2L?xYaq+;9}BZD}Wu`p(y z8SK10IVO=%e|e_-Y$-ueE;N?VB`%$*{NQ1S?jg+Riq}h17VXKQr|W1VtP?MJ)oO7r zHY6a`Xu}2nm~9#z6N#^B7pw4mOwxB%h>Z0fDyj|ih{X-6srCRX88g2#5%A9O;|bOI zZudQ0*H9dmRomU>0*}6>btnBBFer@&$LL(?4v54q&|B3k`T;#X-FfGZnqX zMPKF&cmjbPX6!*A-z)^PidQ*otg`b-!hd z+(`_m0KnfUh!g9XfSG8~t2{Th!;r7G<}8ko9ITLI@eP{6fRDY9W!FsvTH}6=`ZFuicpS}&)GCET z52rPI7^KX<=t03}xN)VVLmN6_H?`l;yU@Ycs-trCpT-a@Hm2|{9{4(El=Y2!SR`6O8ws6e z+(lb!>(=P7Q5XPM?@H6!^*=#e7Em}kgBH48HncmMEM z9YDEDeS8i5DKXK;^9UV~4Hd!yKQCv{hU?>9eNPn5`f`c(5^(`UbW#I3H;AaOQ0!<_g$|~9v%38A70~m-9 zjU=8ydB8tc%IWI!1%1CSuT$eVmgB}QRymqt;Z#G~au+zCij@`?Mbq6_A$4|~r1&M> zstmtzkUTScl&nW^juNF1UrFL7AhtU!vn_T920OU?QRe^AgT%Fs*K3u zXJxPb*tEZzd~Snliyt8I+4o}&03AX44g?5t z{vY?OkR*;wM*ETsk7?TvE+Gg71Ztovktk@OHRgd8(bmaGEu%5zjiOG`w&-L3JU{yhmR(c)*hDN$o4#A#hOnFgpINZZrjvN6Fp^2 zD`doGcs3(rstZ;0W~K+Eozvm$$l8Plq#E4^&KwNOTeZZWSKD{NY(1$B=4sPPS$w7Z zniUFE;t}p~L1aZd(Xm@X?*A?A@P}FSJsnu))dJa+uKyp~#6O&70VgLrBMYGM{7*vV zf0lj!hhP6z1`ev)00BS6>S}hC?Wgw!s}ItS zDQ&RYD~(n!&bXg_Yjo+U-MG;SjOen!l&X{#XqctaCBYxY4rK&Nqg4}(&sd#SQFCjy zb}a8r7C{8isddn{31T*zG@MzGnPdehfpjtDXpbHh%S5v(EXlccuxu0ofLWp?cVMA8co?rxQw27E-*?OZuSSz8OM--nJm-Pylec=y_K;F-i1Bu;7GW3@Z+ z+V;D;tokggbEfoJf?27%T^HJj>oL+~f>JEjUWSrPwTRi=70rGy1N2_omGUsaYsOW^ zk$V+&&SZaMZ`FapT(Dv1e)Ka2i+c>8S$gv_su(qpZ9CmBy&DZR?(Oc2FXF@u+9KE%o1fZNmnkif4Hm0d z84V;hEqZK^ORB_DRSmKyG259t;4>+FJuoO>rWo%2n7+uMQXeuC0+5`nRG=EnY1{ zbU%!#j6iakz~@pO?ua2^pNtl#S0TRK-tEFPf*U4*IWDJvLv!bL3RWR*aOEk{eyY!i zV<@%~vUSmD;d#P(t^%g$y2YQIW*_xU9VspnRZ=I%UQUyv&^`pxjoDeiA-mxkCCe0p z@NzI3{k_eQzlg!g0Pb#IEED`erJAa5AdyLZzybsmdU|_>kGZM9uALRkD2AKX;SX28 zQs5gMxf{xG>9_3W>u&-RsSEBEoLR_!M50FGbcgTIV1D`JO&>yDP8T)f1d8{`^f z?%(*J$NMTrxx(bCmU!tA{?yptE%WkMpOf^v<&hc3Du4TQJ4-OoR94M5SwqFH1Z#Cl zx}q459z>*W^#XBZ)^+U|if-0wq0rt*$g@;n?1XY_YPF*d#SlwyNoTA0Oqq(SI`P3} zW{_FQ=`MwzCMh&+E)84?uJBrkduUloX4qqlK8Yr`H4sDD5F>(qNhkT<`~R z{#r0G_%xCS*pPeQGkcYsf!OuJDpujb1=heUdSqTfw_LU3tHm!;6iCF-t{6J1k{kTy zSHJAH9L=UBNv<`gv*4&B3_4_&+fk-w4YM{+hu;v-H?A1&QDO!j> zTOwW2%%sH69Ci8MsF?q7TjQXcnGgSNkC<}20q<-{AkPNLa`S_rtxNuU{0}3EoP3a< zc{NE$Kkc?BG2}tjgUNZ>KWQVYkwaGyZp29tiK#3}78F%IOXQwJ?0p!#9}RZIymrK% zdhNEE8W6hHq4^(O)Q#Z*YM_Jmg~-%{8kbZ!CF0 z+wZ!2-oCxeZ2ZYKsG^_P=ofyL7|6$lzE__^^XnIveMOB~_is#{zua-x+8v1R%E>y( zs4|}GHhhDt6VLR*-hz?2+`435lLL7TgTyZ;OvnTh_)HbB;D;0u#;NOGr? z?jK^^g`Hh&4zS5%iSPQ^95zS!t9lPNZ_d6XX^V91r(DuIo&wn>`GAKy;14()Cd1WU zs6XWk>xvH#R$PClG51J%ScT>3R!EDvE@{@-uc|!Hr=MxF+_ES8W2)@IYEO$WI;Z)% z#>FR@WSfn(yO=hd(la-;hM99l(UV*LweIlD*)$;*vkQW<5o*#&4dxb}67VVaQ}K9o zxcC_XN#X|97YLl6U-=4LGQ+Ql^AtzqhrMx%wo$VB$qk@XDF}F^{h@AY3qFYeq5`Io zf{;TWL^qdil8j`z&6qZrmD#8fg}q_ICJWFK~8`7NQiwRU19&)+9}-M=D6>PE6vB6hDdR>w49*Iu^*eHouNt7!eL+( z6cDARa;!18)GA7C(5;A}^4e2W_5mj?b3l;9wgKuSB=%+uZlu4AZ z3;D2>Pbd{46KM$hnWkgjBsp*BFMoiGcU@{KraivYGhmfI<(&_rxCvr^Pp(@i4m6E$w>* z2>e0WUlkETCEvfkE2vxFq~tZZa}mFCVI_0D+^>Hh$6IA z&*A2fCLMrT-4c+U;N9xz&`336V^);)P*5iNfhEj*v8NZtjW_|JAQ+8t=4q_}19Mxc zy*$W5P0Z#pU*~^1swQ`7A$dzV_J;p-R6E$}{c#)>8g_w>s_4HQ)l`GWSK&k<$YE>Q z80K|4H|ovGa%=^Su^kdwPL97k)63s!7=7CnH#x*vG|bwYm&BW`HF9G6a}-S4ze0CrvjV)d6mgg`G><8WwepIVj7iS?Qxzq#ZISU-CSjb* ztI{_?a)re$tY_js%4}yukB$nE?lM(%f~GlW8_X~6^ut2trjU)gHIfDzxZD^T#a}iH z_lq6vFQH?CH5Q|ac?$0Ig~fZjX|L!?Ko*$gn}xL4w#F&rOrtg{ZWTEjYaAomkY5Z{ zSBW_4(HC9X3cSwa@;z;hV6g7U`_dA^bX%@`JD(WbG~iG z;)$<>8;#Fv9*y#v-)oBmQX~nyH;*NNt*?@jt9|jOSX_=K&L7b}oVQ+k3%y>BR8x*M zY)N=!m?CG>6Go7ilEP(37<7x|T;IeOp+}G7I@ET1%$H-z0>2dV{kSBJ@!w`OG1yXc z+frB>nKx=rmVwZ8UMV1Iva+ z#*?DuChuFu^@l9bQ*}?cgO*iat;YE3i3nee0Kc6Qh05-#?zd5sbdCL>QMUm+AB4=D zP56=K{nr2i%MjLl!jc2I3~=W+^F z`6}BhDhS<{V@*1=??8Xmfb$1IdW8hqSL`PNtM!2Fyr17546xuGVT!Uu2NY17uTLuaY2ZBAQ{6V_>2 z?xxXsI6v*}s+1`N$GM%hVRVTO4Dn)~cDL%_GthqRJz1E)05%GMW0QWS4oHCbXOASa zG7EL6g}MI_!=3Gdfjp?K?z977;5@l2zgT8tRh-@<+Q23;jV)WtGfF~bVvzhU~ zELJEhB$2~9pv9`%&zUPqq?|uiU<+f8F@W%^p|m|c;SuYJI4R8F`w?mZtM^a%auz6M zQ+ZeC`X2Np%qccUfzCKc$$=PF?*KW>=)-#(J_{|4jdm+{=c)tGwu4rf=9e=!Jkh!k zHB!KWVef4ujvk}7(c=Cx&G@6U0beGWD-i8iTs(?pG>KkZFNiJ1E}nhgaUpYbyE)Iu z#3A-aVw4hNG=>*#us#II|JYO210J0LaCtg^$up^z{o5}T`3Sm50=#IfRns9_1b7C5 zrMxAK7RuviafJjaYLzpyXcAOL z_oTA2HnQgLa;p#4B7U`6%&`f*5AN9Z7KqMk=L$4GeckN4dy*-IDkBgne%d{zPh*<`c#Rc>X+&A< zS?AD(KVY!cl=dL#SViPES9BX({9fZ>AvQN=_FSsRwfwrJ(nj}6x2k~N{dv%aZQ zXXI*Yxr{BGZSKp5{^t<3qV#D|tFe2=t=zb}^3Q~#%eIU+x6_~DYCi-nxf2qUU1}3*c0Mm?$JX1Jv~C!J+q1f5(?d zcn|tGFq7E_AF5d_3EAD`e}K7OkrMIGrOrM;gwA0P`0?V%y-?qOg?B5mAVav_o|YeI zDhjv3P0cGt`@#@~>8XZ1i{AcKp(DBE>_?sxEGw6yl=JzIJnR;UOLXDB+CJLZ-dw$$ zH|73hLXSop3V#r%c6wSNpeBPEIba!E-$hvJTA zL>1?tGbo5;W5)V{zV0Z{*Nqx*8c=ei()@agtpWi0x|H7v00g9kXaaLpdR&dFd@v}q z8h>D%Qi~r*x(2_Ercr>yu9Im5U3zPH3lN9h>VrkF#6$X^O0k6Z6@2RyA_j#kTw{t- zu0YsBU=eu-uY_7)KUSQP>8A1uH0rHsbyRo0)Q)l@bqIztatkviVye3a!rgNdq(n!J z$Gkb6p_o1qM zr&T}2PI@P8Z6JA-BF75RC*ojOU=xh)jG(vBA#2{sS3ovYMt^!o$mkVw-wx3az`31) z_qV@A7T${gK}60hTJ_z?4pKLZ9Z~?vQ9*t{d@&CJtui(#u2J#Z^7Bo(Vt%V&F*I^Q zUvQsJx8T0d7B$nC#wf9JbDmK^RLBQy#hE_+jfTy^5d675Qy1LbG2unx@djn+8yy>m zbf>9(fqH)SPPzb~0+ub610a7yTNDO$`kuPn`?D>UTRvlvgn<#dotIg8@S zW ze=9s2RnBaI^!5+3=BUZJmRbizs6trE-xep1-3Q;ogs=kF^4cH;ug!q)_R?i;Q@5oO z9w1v$QC=a={R^msB66&;H1;wj#rLJ!J z+dEhMR=uyBEI0+zGO1zS;)*Oo?Df4luNpcwfBpZZ%xHOFYz!2ZxD(ReR7ZJ6lJ~x^6|oWg2BYh#Ph}h6W@lld;eJS|bYlm3A6? zDJbN*Yx~;@^7AV>8A$c&I`4iL%d0R)ehjGsKHJnDSpxg8QFE@Ru5vIp5Vbhfyne)+ z8;oD@JHOq{_WWS>obQr<{F>eZpQ+5%R(G;#BHp0=HUK4vwR*9>yIOg)WAjfD)O*wK z1hPv-sGVd+g2eWquIg{66~VZL&N)7tG1TZ2MhR7ht90BglIz6mE0g6C_$=e|x@NA^ zTI*!xbQ3!fJY54#!MO8amN4bTgyMENZA4)tmoQ!(l}VqeJIgy+u@pmaS5Cl}so$8Z z%ziFs3r!3-^fWH{WN1wwMPR*blPLuyU9a+5ptPie|0b~9nUP5a-Hch4O$i3=0-#P% zIq?Zka){bYpgb*SW|{MXupDYg&;MhSRy@HhVnnK`rern<^M0E;kr#t!%B7W`B&29c zVkOt(8zXH?GS&mSUN9StdJShg%L6kwA_6{-IK!oZHC)+im6@8;4 zq(1{i`3Bk{R?6_~2Ds6SzAm2rX?Ht#{c*<-S>QQl9=&Jm8*4~sD&~4K5r-N=OdTzv zIyFR}iP_B)sfXA9iGWW^x+(E9`Ll2C$%=fyNf44JS6)`$GeBx3$e}Hnx%`8XPof4} z88^S#(EfA43XCg@Zb&Jts960gS#5=J&BX5f$ZkF2$x)njm?PMW0!GvES`Xa?ngpL5 zxgKE%@A;mU_6z*q6{|n5>&yVKqGd(=FY*}wHYV_I%fdek*+#Vur!{4?&(S!V6@|3w zr9m45A;@hG$W0RsSBW&|wT42|gr)(RT<@*lmU%Z!8>s~VVGI^sVmDDF!SL0 zuFxRN+~d&P^?viW4pT|i<8|W948}+sPSc!EZdaV$UeSr4KA(%-Uo(2wxR{`-mNrxe zHytv=e{Y~Zv>m+C?u62on{WygBDSDT+i0Rrw=FikkRq$fp1 zowkZ>9><0$L{iSIH59F0ziz17@WEwiFhwrS6B+_xI1aUxpCFrP8gDjf z1O~^T$Uw6@U_Q(z!|UI3*6dq99$18@A~xE>L^j#<3-Y$w*#6CAW|&1w zrZIKDn=UvwV0XhEZm0FUMs3?4-=T8%%$qfL1CA`W7vm#V0h)DTtq}htTyLY(mAhTr z;9WtcMk6~z>OC~@4Gk5?CJfhV(B+iKy%)}0Zx}uZS>Cuh5lroaM`jF>LqF-bbVVx~ zVigb6iz#kcNund9B?T z7K~{*jde!qB#r{`F;0rpB0OZW)?yD<>1b3}Wfu3VwMuFFwoBLuUuBIQXX>}um3!kX zK&;Dp;L{Z@!~`UL#Y=#>FuJgTagaDFlC9@;IZwU-*FlyrYiCp zZOG(x8xD8GV(W#@!)w{J0mUC&)7!_$I?uDmk{Qp|b=k;#y!^neu_Htm4}TqhWxs$h z6k$nc<*o_!tUr|x)UbfsYNl`sz85Xpt5yyL4;L8TLg8uXrq(%}!GxdJvJTfJq+)ub z6;K3hJ>Kusk{p=4q(|O^az+z{%s(?vPS03}i+(V60UY0f98t--fcpE1IS8CSNs{aY zG|xCOYHAiE_{ulA&b`vaV@X| z?eN_9g~vx5a6PtGXZmy6Z2a?Q(Prj5*wF9{;Bx8%d}vks4_@>bCFC&u<{6HRudoFQ&~N*h&&zobPx}@!G+=~ zI$oCV>Icb9eTA$Qn(+)ENcyY|ef9%5PgD&}tZ#()R$|wS#w~f?>*3~P^PTmds%{o4 z95qDIW+|qSjFJzbHHR4*SwF(v|M7C)jUtt(90TNGX~2;2u_U3fSj@GNRT`z~j7Taq zS&d1~hdJNU0nEa_VG2T5@3_=i2~T5_m{4r66OeesAgH9rcbM>mwUJzLMduNY8Y%Jt zqqvmHL?Q|lTk?tc<_30I27`#^xFW-17iuE5E2&jSzZOKNJiFVDvJG=cA$@7WnUGyr zRSu6xlO zVS4NhtNh8@Hd$AL-azZhEMe5Lw42)qn5YvZmBata(ssWri2YVH5o@g}_b_ZyV|f|RFo z6x`^~$<754dTUCp8Cz*s6*QW?knw;`6etxDQ3@wHi0#UbG+BQ2rOBoUYyM z^W*41@5|B*#qKvU8tK*4J{F-rlvhsd+dH|hH4n<}X$CLRFoj*?3_A;tX7W9e!Ff^a z`pi7H%EL)EsBIl<2U+C1E&W2i6kJ3LRnIM`s$Kj1f2-C`Rh@IS-u1S1 zv2Ny^eU9G8Gn(v|N8exci?Jf0f|gGOD?YAv*X;&m^pmRz%>DB?L5||V?yQoem zo_`4C;ie5I1+kdDZjGsjui2;!)HjcUG+c#TRf^;Dm}lEvmEOs zM6c{HT@0;}J)}mK0IYGzb9J%qEMp$p{$hhAN;-0~bJ41+ljWpXqZ0`^js&=t1Qk^( z8Kai)u6DEiUJf@a7^%9CGy}aB5iC(h6t;-cLNk~?xK%zC=??&*7(d*-qC&ZAb($mN z+vMd%L+z;i+uQY09MJ_2v`Z0MGG!a$ym|!$Z!FOD!dthN+I!62rW%5pTfg10m9phV zIK$H*z?MQkamV@EfB)B8X6byveP9P7Bjd#G#)2L_d?mWm@YeZLPnf``5Mpb<8l44iLnUfP};Ud2aS! zR`-AAW~H1^R8YQbOT9Xi&f^UP{r64gKp%`j6$l6+h(U=wGSHFu&!@B#Ntw2XoaIp1 zYCk|~lViA=3<6Yu(Nr}$2PplL!cU!_rB6sCP!*-0J5ICTw;y_Q`o28Au>GT6B!!at ztvAL?s$IrpGhVwhWTjT8Gg><+ofe)HF=r)Ev#X_1k3I{XdzK7&jXWJ=)s1o&Ra!cg zn;S7T%me%l`9+ioJZBndZoB!5%iJn3IWt+BF~SEBFnoi8ATvUcF#}$Xc$|i$QF*Ac zG_|uauuqI!G0lav`ORu9n8?780(4iJ)s!A|2O8CUrh@}quL!xBt~IcW$x<_VR{MFu z&5isS&P$5IX^1r&sJ|GS=hC^Wu(Akvj?_`uRGF( zlF3v5gFLc3#0@x6IiC*MA@=mN`m_*Wi?wiH<%iG1s^bZ_PO}b~O!onQV<13)W&qiJ zPL`+YG5dQ6u2`K5v0TM{JqigzcF&91XWD61Buh%~TL^}~Cj?stn?0~j83k+(WHU5{ zc08pMU=%~7WG5X+>A2R<5e;!QnQ`g3)Ua6Uw*BW!d-JdKrW080-=*8?Q|i?wtj=9n z5dsdiW*#cCH0o8&@rkI`Yj@Ijxv~3Nm!`c83dgaDmn-GWX^M0-%;Zeh?#YhsXZ>{U z8HG>9dqyI##>LWpH^l%1?bFDsns38f0w;)n&EfT4)gLOjFWiHl}G)fg=cnu?IC8%?3v@ z(PUSqZdGI(UY1&gZV{EXlAczwrYqF)#XK7MLPoYG^KQ)KXgj~>N>r6SQ!`TRFDLTA z1C)4}2Mj^NB%OZWbsU>mX<(=~SxMnM8EX_=EXC6FQ2JhWo0YDXO?hLO zxwzUIUNCBK3^d7ij!?q_*LZt7jY!;kGH*Lc)_9iEc5+>kLupNRD^V98w~v66R4Te> zv&n~-QgkRKUPk{x?mJ?~W0T|kol_NLdKyw0!xQlHmtlU>5zyj*Gpz%aHzs0_jlx{B zWBjUpo)|<)snw+JY>$yJO|U}P%&?$=ObB`dh-f+p5WIu(8k6dnSsHy zhlqQs0?u@;e=KQ2FZI$OY@fpVyYf{6Z8XuyR~CriwxGFKLoHV+n;9`Sy}94*T&QCA(BJxCJ0tKkYcU7#3hTOOD-=!N^*L%!Of;8xSZ z?CpW`Eok_Q%N4S#X7Sm}>HbCzy*I*cV?(+#^wo=BKpFS;?f->fd8F`tJ68t&mTTD8 zM|?2%r5)CCDih!nHp>7SbZi^fU#hH#QZw>@laGF@cZ{=u^0s6FO|c7bF; z1Kcr21xg;eJyHb)?)-6wC~{amC1qRWl0zmz9R8}(?-(5{=R=Yw%d^t&PWOmUpmlAD zRKXr~WXq7g&LQbs61-E1V~kZ+T@#|^Mm5UU#^#jYmo5>-bldsZBQ~C55oRM{vlPF= z4u-6<8*dB7%vcLXr@4OluBh{KEFOMl&4K3~@Z{}s71t9~1S91zVTOZ;DeD!did52Z zF0s>{g8UMMCu)zHbqG76WTcOYO$R7w`-H%ilZZ-)RhWiY&O_~_n$n~tTMg1q3fU(=uD=tDJ)>tI z=sWIlIL=mhC~#pIp$0Lm+tV-L7q}olVa}|!_BLDxt5CcNoSRqxI>SIQIO#s3fJ z`F|?he_{;(1&Z zLWq@#qYF7%uaHk@Rzi;FFOHu--^5|gc8T>Gi|BONc20-atstXdyPzma=t z0N$C5P#zG)8Cg6}iP@54dAa(gSlN^+=-X+>o@D}mUB)hcFc5~c(5OFKKS904Wadbf zqI$D#S?e@+ohVpMJr?o=C6z_TfTr0b}dd4zbJtlpKMo{qP6|@=#;GvO8f2oP%!UHQfYJ zN6xEgvbg2vB@s1EZqxquQQU=gs;MR&T{Uf}&l?>O+kP45d5zkRMulg21|*$`iVkLJ zMEA#CtAqdvcR9B`AK;%S%S(q8cwbEuDG(3unC-A`3-m_*kguttKhZ!J%$6+buZ@7+ zrVdo_rj8GJLlXquVB3GY2$HTa7zj*)j_1RAFesj7fbTnP0h2q^7E6#inPysover z*+!X(t~Prds4Wyj6x$G*2j=#reK;?1=~Uz63dT*SgvD-ev_g zl+Pe~+;#J-YkVn!`c@u2t;CR))R644=RMYKdgvy|*GyN3SI3QELo(pu4Gh+oxl5?; zCX5@6w(2uj`+z?Gtij;C4 z&3N(K*#349ONFfWof!iWt^7AKI@y|@IN4I3&K@W_XTq`sG@ab;XyU%*_^eFzV4D_e z^IW&cz>8@b4i2PM)Y7zT(Q5Na&a;poC_1qPhVf&Zs3z3!&I%Khie=ZWn}+2YS@~bx zpZkb{)JkI%4kPtHMFsX`yRYPD7q{_a)fiyCKyBSn{IK94wyf(S@xcQaw+4Up{)}tz z?LI_@MQFdBg;0OFn%~7{!1UD^Htqo3ya(0#NbP?Q`+5=Ni!^u@v7|1C%{pSYgJ z?|Z+@2bTh5z&Fr^NZwy|hsj$c531w=(Zf53qj>?k*yN_ScYP{cKF?1Qyik;nmS^=7 zi^dDg529Cm(67npBfpmLOCH7#6mR5?Ot)VP_wXkV)V-MDOUKb$_cnlQp_!)* zd+Qv{hgUP}4)YCuQ0o0LP5u=ex4Q|{dqNoSy2`we_%jX9F5iHE0Ze@uFy-+tiLM^c z&x3tCAuDF7dYlDUkhG-GtT$NFylGa3O47u_h!`tFhb(n}Qt9qst#K0w!3;^`M<{RH zH+Q6sDf16K1I`Pg^fz7m7bsJpjgCwS`;DVm`hnYUoZd)kN<>{#kQ{CUsDDm=&pQv@6MQ=!hjKq=4$PpyiK&&ZH0QTkYYKJi zE>j}+*;%$1*rGEHI!0VpX<4r-6|6C2w_9j?@4K@`WLV!ce)peN0T}V>R;3+gneonW)(z;Rd3`#Y0 zRUJYc#Wmh~2vxF3cUf(wNyS~Zhk2ey;aw;R-LB>;##q~K+@B#9zi$tPKM-o}h_uyl zZ>&%wfjI^4>S}B?QQpcJS5d`VwdW%hUw58)<04jqQji@Y{)2RY9oluI^(!gssznSK zEL-``Ka{90^F}9p#`caDXVhDKNbF7lQUZUmX}bW;a?Z2*ivc$74o$JRcdHdeinn$j z1;oTV-@iefyJ(-;v?t=&zX#6sdbdd(C~xjgBAeuw^~KCdcFzrFL3TgR3{`vnJ`t@; z&eUchsEJq|YYbHzv2?IT`?oyiL}X*A*gXYg5etCk*HjaEvqP_=x$3CB?P!taTI*-Z zXXe5u`I#-RgpNQWMwf-1dc%tC{1vrr%E{Ab#W-)&*%pOueQdb7!(?VkY@C)!T#ZRp zYE-Kd)ASD@y(?mdgGS!&Jl2Xiw^k)e%hP0YpJYRFM9e~ar~WF`p~YY|Ce#WGu3%#D zuGwT!PE$~6rTdLwAIsy_hlZosa49NkzymNcDXWF0=ssQcG=csEzux*f7>9vLuf@vh z$@Mw{JpV}q%r+(4{1#=CqAdN$xTvh2p_k-<^URTFV@85# zXN_0aPNO}?^H+K(dcxIB;%ynXNa?k$BMj+!&S4F0A*8KWx+OFZ7w%a&&uG59J@Avb z7p1^T0jp$MLMWHMjyF8h8jtrB0aeSDA`a7Q;F-Jt8{ z^Y&X{L6^{6XW2Ggv72+3x}_YHxoP!S>8TIg3;=XS8}~r7+opcyVN$AWKiSm9i!lJ5 z5xpM*+8cCB`GVJ0fld`c5365 zbyaT_caizK0=v-H=~?ztXzG0VqVXInIZ<=HaDz*288_@*xU{dA>Lnrg{kg>tj4#1{ z_ogzLGM7KOnR_QM15E(5QB_P~i(Kce{RRo(Z3g}m=tKpJuwQEo`gn36*E zmAg)8xs;AQ*B=i&Z-b8eryI6!J-jb$3hzt9s=a;RT{e@=O9Ai8U;9ItTXbJ$^Xz$E z_g`D=Vb9Qh#OB$*eD2!n1!l}%UI{)hhQywLWfZk(L$h!$MB#a5 zBW{{!bGUiJ9=xD_!nj08 z0;ZaBWD1kqyG0v>k;BT(Pn^;hmw%4}fmJ@SilU&L$))U!8pK84%Crs|RFQoZe)NI+ zy5|w$iKR{T-p~vU+$C+YCX6F(=IB>FiLiYRK1p8mBlxHs^d#nT;O6jT=B^*j0sg~d z3RnE%8*&qor#gQ_QEAx?KZggr8R++bVlvozIh_JWA@}?ciAMNQtGI1MsT2cYWQ#~c zYPqsvu((AO3Lz&J9<Zb=lQ?jU+NRzC3uW$)S8AZahLp+N-W?IaPJ zS2aCH-u;y8di0$h8hsIfRF5p(tUGRQi{`znD;XB;u>Q_^*Hld5q94!)E8g zZE8Ilv^^JQua4fvh3T8KFo+Kd%e-PHDs53@ufXGV*YBPat#8n=VSM{oA^)L}&uiGS z^$6kKfJuHkBN;HP%ZNERny5()w=iGahaQ&C{@fZ}(mpY;IRGl8;1(1l;wGC;9)23X zNH%R&w1V)siSciYH!GUr&d(9aG@f8rUzwMjEQ*^dkiY|93`CT++VcGNhTnk)p$O2- z!I1L^hD2gb4D+9uk?-VeT)Ar&NP3qQaC+!lr+2UnhEhIBk-{NJoe%*Fgnwb)!j13!jc(z>j$k`CYF4DA zr2Gr?Ca*Ho49eM8yl25$ z*KV)v(?K?vkV{1gryzsQowZycL?<{&+MS@uexL1UV>zlgc<`-f5uE3a1Fk~41dc9vA7Lv znah=T+KH7iL8Pd1T=g>$bQS371S?JjQjxf>a#%1L2QGX2K!ZaaP{l!D*^Mafk-19z zr+b;_m}{h&J)xgwI^MxfKOLJ)h$>t$vU%`G4|bSBqcVCDmRPWJhOnk7O?<{jz^IwB z&mMBk|KV_`XXAL{t4-dx0EV4;if^xu;6XRC47?mTQ+B{Vt0z3n8|(|Hre9j43S zm$l*3rLh1vV5Nn%A>xG~hKTmSDm2IYS^`~xZwps-J;ll5XML3))UNG*!;dAe&(Zkng51v~x-WH>&(HX4gWS(1`WuUcUgpSCwE2Y#Ew}nADaWU?)CbB0 z|ADR{-Hv|x+R)aPZ=ej*EiAVnMXRy9Z@;-jwoH<9dhs!GhniGFW1@jEYBm%r51+pe z!w~u<@r1}=ckUV0cCJ>^Jwdj2497P=oz4D_-M`jaBw2FP#Q_!rKEPs-{Qqf{|5x+| zSq0_WrYmc^SZkrQIbM+hzogVc3gtd1xNuGpq8Ut!{7*rn4DEEHF`F@4j=`we7@3*( zg2Sj+*nX*YlRs3;;epbGy~F$@k^?2JOFSuk0*N z@94^5f@VWyqD(1DJBCwctv*Ug#WX2%tiz?!B1NrYB0JKGlRA-jNn~-N;Sr*e6R45l zaGk(^osp?A(PRmVWQ+?Xh$KiRGwCcRaV8y26IMW2O;lI}-5H#b=70prvn2t zKQf3D?q0@I)8U*v+U~;s5fN96-7|fzE>gVxNd*_Oc3Hx!6Ay-s*d=;(8~xKgl%e8~ zToFZXz#eMRH5W3l5wSbgh;nDn0msgk^LL^aON|QTMW#Y!gOnR_H24VLY9|qL(Sn!O z7#BOCf!sQIqs8U~<_*hYi4V;f3-xM(J=J{gpFRuV*nW`I^D`=44@rIDfp1@EMrX+G zDbZ8uD4M1ANmQc};Y^>X;W!Ob4XbHqX~mpY>P;5yq^Clt465~G)UI^SF=|y7?bKQO zk{l+Z?AkH?34(T%#l{`EgGI)?)_eXM3{c(+NSM@KaZb9*Ef zm)Ghoe0(-~j<7lox)tt|YPEHzX7Wnt8@om5%Tx=YH?Zv~TO5MLA51MlG@P#AdNy(( z$h9FCZ7ROooMcsu$7@xbtXGc4@L`C*$@N4d)b(R8vBM9TTCX{6m&@I?xv(Ji1PS;H zS-vPN4*b#i(y;CyBGA8+nbBYkSOS5iQQbV^$R#n>e+OFBtc#qG4Osz_5Hl@R&m`W< zTlC&yxACX2RC@mOM?I@6u=_a6hieM$`G8q8K9S8QCQs zC^B*L6TZ#)ggU=KbKoUX?IUvuu>x$nFDGvyp?l6gQYbPV;7MLVmck5!VoVg?K7QDc z;n;&OGTVZ4B0(%|LoERu03w9)GSqT6t^9lb{9e`kwN`#6_9$7PSYB+H-8Q9{ zFVmMVR`<93KYJx|!!kecV#xYJi0b0L!LO~zb1o121hewQc}M-z6Y1OO1>%~yU%5ID z{xCiA`txF@;T!pFAKGhX00QgU`@98a;XM3q+7V%y*`kXVpnjGPDO?u4Nm#3y*`o{l zkYCZmLt7LFTp@=Eok`uYWjEGRA|p|y36Wy${!x1zFW^qam;DgDW8CMQ3BzXU1QMl& z6bDEWP#PGtNhpF53(vd~l$FUXB8kl20=UKz#q_%^ zLyuJwvkj}rL*E1|kezda@l$+NK3{V2u}xL>rYmjvdKSag^2O+EXL(jddAyE2T+}|2 zMH7oFNgNb%kcnZQj9`W8mzaJ(T>dbS+R8y%n%IU<_KF-1dzH>N13=e9#Y-|q=kfF* zSf%mwuwY4UJ6uut;$#!*qb!Y7!m~e#UE+6fwb74oNh@t3{>biQ*h2lOHG;Q={KHPM zE8rynl_8!$Ji$hM4o0(;?q)B-m)u!+^UF^4)wY0iJJhUd#Z8s1itPggrnxvI5B@%3 z*XYz7a(0$bc3RFohG`$RXop^ONU4&qnRQQG34|AA&HtQlzE$=M^n3+vvBic=?XE$u znnbf=j{SFlFq@pL{H%OUf9Je1v30g^_MkI!v~#hi`=7H={{uk%9~6*(5uP=wT29z3D7==mz4gqbkZ^=D z7X7f7%m9K8SRzVhFfsV4V7642W0DPtf>9lJS7XMB%pkL^Rj2l4e`u$J*C?A8^jmjH%Xm&qOeKT+YU^T@rIxEk z!&uss>sGF7Rs2y*&;TWhl`IYa&=~WtJR&*VBWP+Zhp4lp2ZjV@5VOfj#SECYo?OUo zZuht-kF}&Pg^Aic5dIRUNu{8?ufifuVGm`EtfbI6x5APhyoBBQjDk9#HO^})v0P_m z#d?D~Wq~c-=j4n;Bd#L^=TJSs#+o9pLWX<8YJx_q6Q`ACc})eUXpdNmw2(_qm(ee_ zx#b|my=r5bOW9$!W4DP)d6;UPbsvfC#|hX>V-I96Hqgy^;R5wt{-lNXWYsRR`4Hsg zx{=Ixy}>SpKh*E9fsu%>INa5 ze9obTY8o){i*~l&Ov+M{J8AdP4DZ63}FQn zn-+9!z62Z#pMkR0 z3?8JBT}y-S(g(4SIANe#yDye+Q6?6<;Y@E1yY;co-^+7!N5*FC1wXsv-z09uY#*m* z^5{%t+i)(kEQCCkN$kb?P>6|yOU$=U4?WL#&}SnmRrD{lai^D0Ho!_EFWWL`*g|4d zqzpwMETp1Tx44^%>gD#*R-nGYo$J6gNFUfTT|%*%DIr-b(GX;KP^oUBJwLM!T7T+| zXWn`n?fFfmNq8D#+?8+zz9YKl>y{b;SERzXYapLaIfcBd*ZeB0r`1%LuRXi*O3D;5 zmN5xo7sGe+(dR_tOyigTGF~;mB9<$bM$R)Oc)hlM))o*YkTMehB!`qNz* z$P3f{>AUFc3)A%}7jnPc05}Zii`Mmv9p?)O&t4VIuljXq5E2b*hSKkJKe`pfij8PlHekCM1os^6aDKH-=psWabT=RciXn)72Tl*aCAjUZMSq%Yi)U7X!; zbri$a$?U1N?rR|*3f%h9ti8O++(jsRNJjpWQ8S-y-L!8?x6350;?5X8pz!`U8|_0G z-`Cp^zRpZhNq6&Vn9a@H2#kt z9RF|9|9`!e{&%H6t$yi+V}klE)7Zq-m7$%qb*cCr=Hw z9Gp*>Q)k;+LltxX$^;3?u$2B+fz?&9tK_5#Zc%dA!_43r!l7IFnQ&TgF+$edL}#$AT77YbQwK$v zVY-uGvz7?_WjA-bu1rKYAtD>xyTs12*v`loSl3_Ld^}*Sy87>HAYmdLB`aFf27Qsbfv~(vC4uC zWKMux-U4pGrvNHus+QGKH%o1r+!?CZj(W2aal8tHzW}790@L%3+Oi~)Clk;v4!46M z9jB01sfK%2Bu*`v!4Te)bqNO43M{4Vu*^|A$M(8jl&G7j6gwWpR-hL0TEPLU>L%)n zu9iKuthrgO*khtZ3XZU-5w}Yhlh&*~bq?v$#ma6Z!>vn$W4WDntCI zpUUk9-MPxzssxx-`3G>UZDpaT5LkZC>5&f7@$V-rUcSSb4%=$t`v|;={l$?KIJWi? z?-t3sWzC8zeC$;Fo#kuHTt!(=w}_~2`?ipm6B~iNh8ZH$9h3IrbrxKi=kkNx$rie= zzSGidaw6c@Xv4(CWE6O!8hnOpqY;U`)|shA4XeL@Q<*OZsyZ}p5dm70xjHqLoI)}P zAuoSv{8FvZWR1Y3J3q;0+J)lu`h9NNqPzf+Gx~#%7!sQZ@k!D8Z{*2YwJ=(5n*HCz zLZYu?+lxD6gFrjOr@H+%K1^A4yTS{q*JYsrzZ9tcO&>~(yOfDPK}smRXp-E zN3xcKz-fZsGDo*LcX%1Oizd$y8*I&shf$V?M}w$5;=<%{1Rv8`i;d1NOaa?8GnX=U zy8TS?aG$BiUM^NvZXe~rf@N=uGvc~DnS-h#7kp-y-M3;ya$u2ZTFdSVR?*Xt$){>t zTs-U|7P75B#QXh!uzf{BVsQ^_uV)yBmdGkUM8Y_3i66Zzbm`?ph&`Xx$0_sb(H!4h z7H4~J7^=!sV$D&52)VP z*^v?^Qj?#Ra&n~F-mN$Vhc4P~Cp8&Dnjw~uHe`$w9Zp|0+y^F!6HwBc=BBozc;0 z^VGK{T0v2zNpbNGBU=ckXNz5>Sy{C~m2Xk?SFBM))bW~0q|v25Vr+c)(8<=pHfzpi zj48Nv32)NTx~!0=w#;2lgK&L8!4ohq~K|)M&5w7 z^6j2xa$NRW`fUYN%Yy)7%@-)SoG0d(gGXM`TeMyeFDIMF-Y{Q$nmwc8v-=RM=)=YK zGz=dFm>3M_^(PD;W=;WTg)x}NJ;P23u_9aT3Aj$NMJH7ZuG6B~#m)R@34kqePCitu zKuTZ*xel9qMWjO^{=};sE3jZNR8b?DWL3#7;`r?K=R@w5rnm@w?u}7T_|E^7QJ+WF z>v0S$jCOfvBD;O`hvO3}u`U|vQku;u*;z#=@Cz}o$gL}$pmUw{bFh=Z$M!y;^55$SbJKudBA#Da4WeDEqn$0f$0Jd} zINM;DyMe}MmE=JJ@uEPw>tNVBOZ3l%{=gqSU++76yE-`;;0epcTd}bNo zi=-19sMDh8_R9CXJ12dq+pChf`#hcNQ*?i(e%h( z-5U$MTV?dVgxc$%6@LlsgLOBpt+hv{aCRGJ6N>CZt$FE8p`2l+n2~R|M>X>v*@dI% zg$=3|(&`l14@t)P-3!X$>beI@KFe>*!*$1*d_QpIVT~w6)C#w7>tR>#6DYd*&`@Jn zM1$)EZ8gKcof(@mHqCPHt&4YL#!b^C{XyfLC*Y+iI|d@y^$;Q8OL-0oO_3{4R0A3u z`Y^r-e zHqS9f`GH3v?hx|e`9RM-@kFy8_cneBx%o-;16K|ib;uxlh)H;S>Bk4~E+M6CfIG}A zQcC{eUj^?paojmiEeS8i3j15J5toDTg2tiK1IS$UIof8f$?{c!i{^m#!Ik5 zPIEB&*xukjcFx54<+n&NT4! zJ5Wt>H8YCb;=&NW)m#y{h^*Hvbr~-*STZzPWN-#p+hs$!vgYJ>X39`0e>I*P3)6IJ zp5?kQd`|ZaUCyK*>{N)zZ#^_aMQ$dg=eH-tgN=yr(UQ}SLkc)hsDO^N&`?-v<%Nxk zw2U@|kNq4!DLw<$AbD2ada-vKqyY_bJg-q3NW;!19&)*?8@{eiD%V?lM?J`Ga>#um z&2z^IR*O(PlX<590Job9k17>*@*}3&8P27dJlN-R>5&+0w-Tyo3`(F;$ zf7KKI>)pRp7Ftv`9g)Qlcn+gfRaq0_8CnSm^OSRF) zL+DnL7DF+_@EDOUdOu;e?^#2T2-ylnD3w&Ukzigsl@A1FO^+GKM5t=Awsubnn%_aQ z8Eqt_`C^@Jex-1F9Kovy0D7^hw$Mv!wBp=%LIYS_03s3_?;Lp)9VV7VXB}KK z^V;b@7MBBEQ&kX}DcjE+tCW-nOl8OR5S5>8*I*x+2Cv`o#T(1G3BqW*~LU zNUrbS1deh>Z5#@?pKh2lcyyAtV${(OkIK^WYFUK|J8be)#X6xUapt-8anlH@(gSBT z9Dx9v3q@7HNj3yXlzPE@446HpnmJxEppj-Q{R&w{{J+~=L7}^f z6|y5lkSRJN4LU90)LQ!xe!Mx~+X=4^K_9P#Uxu812F70p1bzg!}&@6OWiC=KZV zs@dZ)$jH|uu*O2!oA)(0)UoSaLtIS^-vl-RRoqXI%rx$1CIn9Up=LVzpma9LW=C3rkSe4l4Suw4z64bs(4B>_JOik0B1IX+lSin^2Io+)TMOI!USIQ`;tochwKvK0nd#prlX7!xWQ5sCP;SrFa zE-Y~WR(Al!3D$7WS}f3^>_21gG<1@5Z3b#G1vVxuQ0}E*`xx&Sb=Qj=N9;6bO8r}D zu2VfebNefZ>Cz6kBsD6B)L^?qSHWVJk5fDLI8o30%wCIE@4e4oa{HIPZ)bw+kx&}F zBKdDfIjokaStgrUtse>x+j}2r6e;K>yIPGG(?-Be`u}(@R-}(Owh+^2v^$SDPnAAS zUtoF38FrpNcsrTp;TGSn$OgHQXDbC9Ml3+rZdYv9J(ha#t_HDWz#MlRdfNr4X)6enj~1vQ(bTD5lV+guk_3`?~V zo-(a9VG#GpeWwdy?Y_9lB=-j>Z(9>q^Jr*6lkX33_r-a45K33h#A&m9r)zfNWhCKH z!8{oDTH?6Z4_$B{?KezzIzE^*#ymqN3$8fsfGaOo+lk?v#L1qY&aLawjNrfnYgz{i z#JxPp)swsMj0gYH&df#1E%#DmE6^@uvrSG$85?9^87@9*vbu~Gq$}1G5pKtnyxVp) z@Bpe6B)~1X)K^@7D+pz3TdGZlx~*$f^TD26Lz%ftf@mQ6jqU&e4uMv4vewvTyuRHZ z-1WCs%k?hvyd^50@;dSIZR-TfVBCX~yxs}Y^|;H3ht8CAP@QQx;%|5QL~(u2=$L!H zK^R@IT)Eqg=$2#aHVqS$x4W2jD(bF{V$`SA^ECowsA$ixoJt$dB&pgi5d-gwlm;`S zxfHLFTkcQUC<3%%n>uygu|;yOB`Y-Ra}QE5o2zjjnIU{IUCwxXtS{ob!9|gZH6erS z{3zc*TWBz!j~0=(QEX;xK+?;cdj6w3!b7`1OSrd1RxiZoqXcCfc44h0-e&>WhfxGt z4B{0j2KupErdtF)4buLH+8rEZY6OqKukUj`p{*~Z&u<9Yrm9ETd5AYdPqxCeK-4$# zNLMtAQ6$TKC-d%_I;%}c>cve6Fnicli!EqpNT9CHud9P9@t(3v>S z*|AT6tzii8EWcB8(qR^*v>(uQ9z$`$4-4Yt@c48nsYA5GMTIeY7+)4l-?RL?4BHoJ z_zz9S4?w4S)Arpu-pliyFVaUs&|ugy?g0LE03Rj}Ss?nU`Q?v$-YnV=+{!=ZZ+vs# z;4RhvUr9~&?|C&}x#^yx~yBl}_WrcM(^-D|1o*-BU;%pWR;t%+1FpXYH{s^`G(f;O^h(A)|^{ zEbM?#KSIev;O3cLsF|730dT^m@2l?^}w|WG)XQC$*d>)gRDsan`9Zh`LT--br#rT{CAIN6r(usC1 z?9aOy@rln~>?=gi=fleI1+#pj2g4o&G*NVaQ_M%sNI<8_&Q=U0ZfGb5l^l*!v?EYP zS6`PgX$z#Rs8~XiD)@*ebvy^6WEbPrV;1iL#}=R!`v-k6DDoi+6%arR6a*viCA{2p z$6<;Uv;uIVCUjItQZDzdB!}8au_N2gN)fSb<8%(RzP@qSo1`k%BFn~$vMHks;82<-2BBD*2B{megk{9eVe>yet=p@V z42={njU&6X_4plxF5t;;a3$sa!&34a9G?%-P;Y-xW(-4J4zOerP87_;*3E(QLdk+~ z?Gj6tHHgH8?aot64L){6?k;A0f$)yxCA|OJT-eGN$^dtO4<`#4=_2;Osh}MJ!LR?Y z;r>a0{fBD)=iy(Za*gV`BcLyb2bV5!1Qe5meR$NtIGKQBz))hX+n?qT%$P%67wKUs zb>nHc2y0}raDDk9giuV;ya%RSmUfTqZBB1m$wUKpT{f4F-}Lb_S1|;U2@r-@JAtG1 z%8is7pG%BQ-I~WGiT2r0Y_ARF5K5-!i^m=-tuP7O1Z6gr#hEF`nYPIxGB1^WMbcXy zY2BnQzq-1*8W_ud@2nuGNi&RbCh|FDai_fE!a{E8hgS}O=_0~JcvC$UHoH8mfw`*< zVb~(V(n)+qf2;*C?yk_+{y2cr7hxySs*~JiRM~yUB6SF3S249}RjJ}UT0_%O5J!Kn z4J~%;E?`UCKuHlY;3D%}j@SbUmD_RmHB2AnX~B5Lj9vJ`gtTib^G0BP1%75>@&arD z5&EJ-Alz5+{y+N>I1WW+tZ^B(jtMDZ*2CXVzS`Q%nD^2E{LnXIxvNX5iGyB8QQCQcH- zP~VXb%cW{4RB4hjR8f<1?BQ@$^;ozIv_I-Rp1bDkwANTiV6F2!a4r1J^x??RkM6b6 zMUB2T)Kvqm(31I_U+KlBv$)~fL7{XhYt`zFz6v}!9HtO%04+!KqL6d22~(jO+v#DN z6DeA`GteuUoa!@kC-&}Z&F&ddTo1qJ#;AsSe__kOC`AC_+LZ6bS z=pn;n2h8fZ32OZq3Ar{Z^l^4B_&vMz_DfH%vF6r6OfQ<(6DaZ1snTS8BH84GWKFO3 z9Uaz8A4+dQ?*ZoywYRhpH&P+f3Bx|%#Jo7`V=4&!@tq09vYLSpFS*j=fw>L>WuqLP z4=>iQ$LzzM%a_|fuU`=3%Y61_=Z)nK8R&z78XVA{vu8T{l8c7*Vg&SYfA_KrNHuix zeBJ-}BJLf?kLp{G<=a1ifAp_op18XXiB3LNh;m58;7Oo;O;6gNQsQAE1DTT8fJC1f zhdwdEcY>penO5iz=VJbgwK!{ffg+GotVZUsWC3}}JnfPh$yusPgvz^*=R)ax>m9ZX zKC1*J`#Mb-+jn13cpnKzI?F6FLgfwWY?KXafHRoMW!N*+xxZ0*&y%9iXtVGP61gN9 z&m+mh#SGoGHpaB|^>3ToP>{;T03h~Si1p(K+yBkx_MbgD?{3&?h`BAzni{&Rk;q*N zSH!Hu19i&87RZ)l7S?03M{fxm5mMTbfa}B4=t6CkP6uoq8hM?d)=o2+CSFMZ53()H`NA@fmYhSS8hL>tNCgtE=WeF|*x^*6@c6ydMrSH5rzow@zTnB@kD%QG zMdV*()>h*l(p3D3Wo;Ep(wiia4+j!7@Y$wr9Dl|@?4lYf7Np-Ul5=4B{Br#)6P&GC#4;ww}{brM>y1?5)U z)$9MQToU_9QmMC+V==2Wt+OrQM?x-xuW}YI8Kz;ySPmgOw+>~nxlOq}lpfQcP4S+} zF{b>6u}!5AR5tB$8=J`67o_3MUvfyja~1KPJr16ue9p@mVpC)OG*RDjW=oZnPl%;@ z)-3spS<|EnnkJ#K_BirwDN*?6ptq`(G?U_2wIn81(%DRRYbCsvsj3qmGtL={jTjT| z@cn-6Mv7KOMpX`=yq{T!R8kuC`)@a|)!L|_EIzZ$Y1Sff8lpQ4KrsYI`i0G_DQ$^^(|NTZf}ny)H%1WKUj6)j=thcc$7TW$B`aM4%3GJ zjkC9miu+5mg>eWJ!QBGE-QC^Y-Q6kNA-F?u_u#?ZrEqr$?gS^eyma?W&-8!pyQc5` zP-|8Fsy>}M&p!J+vNwHc?*<%i1RBxU@j+dEUm?X+{96bhiz!8Jf(jFPXyydX$;XE# z%s)LYiSu>G5Hai9M*H9>8R8u};nd-5YQyjH2}ZN#Vh|%?-)%!z5!SLb?J3-^iErlm z{0>)WB-e@OrW&NHc+}jZaq@3nB2cB*Kgp3`|2D9_rjI7)oT%vRV7CzVQ z^_Q*j@p(t{OCNJw*mOsrOJ||t>Q2GfpYlwjYLi<21K3yu zhe)%?FRhHS8}gdv*3QL|5trYdO-JX)>|+nXs~A4(9h|7q|CUy-ug4{Nn7r(8SM4QGm{5Ee7W2{!3gL9U#TV~!~ zg4cTF=fL3(oi#zDQxP2f`xYYm_{p&E%lBnGsGYzy&Daji$ZJb38lOd6 z&XD`$bEEP!I;2dfxjSgGWB7+s+%Y)&qVpey9!p_$f@-4L)XobD8BU646b)=s_t&k* z;{$L_iQ5Q;_E;`06O?9nc;(S$_s4RJ#vpa94k-|GlX zHl3j({hRX@7q-zO3U=3kJ2EJeysu3ElDIyDq0OZ81)J&-+SkN?fz52a)D3 zd~f7_ZF&w9&fm&xCI!WahpcOhkNxD+EEsL{GjDV_HPdntck9~dhYJ`(rONotCL}&d z*GnYyX}j2V{gx0HQqiSAZV4pAg0gY@9&g<4bS`cr82%?-ab?C6-JuY`M9@%}{zIMK zz8M*eIxied*UjY%C$=k42@at2?cmZ6PB?e^*yxFL!sG-clU2KCk7`sHvtMl1u7~dN zFvZgz8d!?7gxo@qhkcLQqi#2oui)IeH_S^am4As)NPswJmmIMk57tH_-}E; z$a$v7KO9uP_+W;CoweYCNjty;dFKnVg`z%xyi4Z~VT1`>4H7IB4p`560D@hz8 zaNW+{>8o9+q~H0&$a%PtrN1j-|VM> z_@Z%CfsS#x>-WGO8fOchW0NClKtq8#rCUk4ju>Ju&qtv6^2c$|yScojUfhWy(nQP2 zLhFhHA`)rNZz+FvuD~6+^Vix9^~g*`r+@K76sbh@-CM{GnlB&6k%%$ejv$dAgLiO_ zRJ7MqA?&+6V%ZT-!x?-TtjY`?P($iPvU?pgr73NmzRWZ46N3Ap4Saycy;^g7#ge0} zNqPQ>s;oufM|XEuTyBIa9|9R~{*!6}DS9XFNiCbZjagi$+|+daR`ayYE&jpD5%SRH z0D~|HIm#h0vY@+awpnPzl7ZV7Ru%Ba>U$T0bT1R1*d`=KY3kP2MR0kk#*Y|3FlwPG zkufG|>MQ>_0{FoN_cFD7*0-J6_J%pKQ;sh(M&9J{c}i~r3JmWTgZLJK<4*94HvSpI z`*LH;C-uoi9@XTp7yYrKD5=%ERfgwfdp%c25qEn%@L{jekrbuX@mcePT*M?(fC0Xo z-<`svy?8+3aiZfm=C2rkIGrY8Qe7JiFlk%I6J;vj-qH*QM=R3|8^a`SD{XR{Tj53z z5N=5xn0Ky46kRz{WNyDQ6rkOjpv+j2zQ~Xic%o;diivV5`xg#)ONPRckmXBBUVx9_ z&0ksahz&|^lLt8sa9~2vk*1PMGtZn*DbOBdR!G8F@EH|*wUH3@^&|>%`YWH0m@G54 zR|gl~ks~_CuP-UZ(s;kqaf_haMxJ$*ETgPen@#t2`6rztE$;rxyz@=>J5lT5sAZ0I zCxVQaT%8MhTXI3xD=#IBG@ngMRJ!q2X8L}R^Bq;0;vUX-j$Zx|?AEh0mC8QJHE1Um z69t_k_hafw;bZD4kq`}iNmFcoS>1sQ>mGFqEDmYWUhEcV-?2{68se0@J!??bCs48a zF~^2gUlYD&i}u4{>y^5tX;6}Co@}R?C*3ICy%5NZs=Aq-u z>u9&iY$pz;Df))!H}!mq{G z^TUHKJ$q%P`_1o;BEWT>-VlE7v$^g#2}sea@4l7Dx$$({OzfDC);d)ASlW@5cZXPg{*_ zP>yqLz#PCc9oMX7mACeW4K@nUr~%g&z&yEJ&p&qA!i+oney(ut9do^wSlLV!pPa z;$CBd6LD@_83IL~qg^y6X{muT^~`@O8JS4GQ#V|H`Y0Ls!rz?=7H7aiTKtqQ%!J!Q z{g{lB{g{l3W90i%o>1bttkrpohuCeZoGmY^Ox-SR+-{7h*)$91&y@K-5%Cz+|1!wr z$B^00%GAv2xn9o1jpYnXkr{bErg%oj_pfqn~e7Lw9W)tE^#oq(e)eg=QnA zk!77aqgwl}O-o87Fe5OuC}oO-N*K{Je$Yuc8DMcIwD1$-c3=3=wtr=OQ?uP6<)v?!K#4!0_x`dVXhUw!z&4_c zf@2n64OhfN3N(h(K_cFk;e=B`CC(=#klbq}JMz6*@cCND6nZ3A3A) zcc>HE%(h#dDYPGHwRh!9P-A`x+0it$muOI%B?tXfZKN@QhX*eY660R#D4g!+_u&h^ zdB_iXtE;t}Y>^+i+^qFkb>-c3^ik;jqkB5pFKG;r_9zefO%mKVdJws<8)@dlCQ2om8QqUvB&Gw9CQnG+P>a7Tdz2juv{uzZR+(vm8F^5Y|V4w z0PLs|rkuU_7B-wo;Vtz~7#!ZP4n`e>YN6P$x-c(BdG>n($2zyehZHM^T$h|ry2@jf z%r{B*btMr_ZHO5tTPDokx)ozJ5!)MGCY{Ga$}2Y$eJHV`;q`%TCek0O5AFMG?%p-u zp;6k%`t_NpQv^jh%e&2-`sdvv0+tDQod>!5JKlJ4h^1?=BrrQ$&8xAsj4sAA-%{HB z=6?L7{|yT>bH1<~fWO7&2=;n|`^uB+{rP_2$Bs0vPPky;!IRD`f^XvFwmPZ+W+jLg z2!&V9RwL55x;tYyvy4#4qU#WkuXVk0b~7Zes&IB-?Bth{gITO0S7V*T)oubfb)`8L z@A!VPID8SJ3)rMwwxj|DPEDo$zD?Ar`aWKfGO)0@>Si%G-t07P8zAitYmypl>*Ol9 z-X_s}9`WkEA6n7Uexiv~ZZ5cn(GMT~45VFlPAbR>i(kQ9&Rk!tHT3e^DpYuGu4%MX9qYBQ2(=Fv6+W55N)(3lfp1K zf=*Dk6m92`W6JbgC0e%Y4lhqY4IuDWyxgf*^K=$A>lkQ`B-ZDnUfny3)tJuo;f{bJ z=fZsO=^a3)-=U+{y?%iIAf_x??u*GhoLz$o4bv(HNAQ?;4!afF4XZME8l02YF3EK^ zgd616JdrK(gG5Ta14?ho{vpoKE~Ia$>j^F|^3G7PCj1!;P&7V7QEms1q`0d`rPF3Q zI{i(lPQjb$ir^eqCb7?f@*oHTD;RFqFVm8=iW)46=Yn}+w1Z%O*dh0kpxQ#r$n^ur zTUD+z@d=&*PZV;Jui&$_ieH5jwU$X~f~HKSa4*9ADG1+&jkbC4ws~~6{85oMT{Rza z#6OaT4{I%Gu$$hR4?o+#K6GJvblrztj^eGa%CCS-3jIS%_;H?LmHmTKJecp?iw-~% zxdj3qd!~*?Sq4cb0|GM%YTd&3CZ^w=^gc)mC%(h9RAL}?51 zKTePGX0A%oV$xphYAVXP(;sdy-`zzdPL=$k)kaA>!aP#z*a7{03RE(N=w$1=vV&|n z$M>9bX+biKoHBjnYn4tVg+W5r8)WyDXifkezCRB53kgrSARypMpx7rS&~bHxvx>~U zk*c-)#W~9Qp4?0sN3QN^52twUM92!Tf3APLVMj&auNQKtz%|Aswc@O?9mI`+ek7`4 z6tyqq8p9XLe}!InAqQ=yWJX*ePD4ed-2yaMMo4LRO2nki4rk~coHpFE3ohFok7&e!QZe0B%!oSwLj&3OqE!ycciK8ABeu-| zy^IXc)H`EBnVMtYDN_&mdYQILCOkN?kHJx$8S}FRr%!~7AWQonj-P9WwCz?|9CLez z9)*uDpYbJ=a7UFmBD!%wyAbG#`$wFg?0`WHEE#Gh%fxtjxd`qHI=?+cvzgISY!J+a zB_j;U*YjZzm#bg~sDD$SFN}Z1&Faa+(=D{%T-$yK_*yd!-=RjCx~0F2*Mf-%phLjDFYEVxjDIa>t zHfs-SFlKIJBG~oSLe4+C!=~@#XqNwHPs?Uc5^m^XR(Y78=I zs%H5edeu42_6GB>7o5x23ZPGbYOFZpei#BGqGI#v7qDq}i1h&^?@U!tgQLINC?G47M(-}ivIyeEK(Wk^ ze_2x~dl4kOPU#+24#_T}PCoQerEbQ9k`$&6Hx^;y`{nzbGk3V5|L~l<`3}VxW{gbe z@p_~*jX=~tNZ_lm6xpUVy;#q~d&vA?{xRl(2GD0q{Imst@Poq03h84sT7jORS_{?k zus$Vw8?SS3v|FOHp}Adlc5U8agi<~|rjR+kS4IHjo5G6h2xWnw1?Z_g5PShqTopw) z?I~r)`*k^EP9Un|68$YQ`!-zvoL#e}yp2|$h!*bZs;HA4zvoE%gQ#`$qcQbpW51au zI`1SNvoRniq(;(&6vxm2&khdPhBcAl3=r`?Bx@!hZSqUMGtG{92tc~y(|XL5QO6l5 zJV+@zp#kw@OsTT}jPEO`vBSnHjQn>hH5?zRHR;Ms-Uwu4d*hXp06o+C2_w7Q0=uov zRNj>ZQ!EX9^$u=-D}=j_3VCJDm;OLeuHaA5NpMWJ=f{Kash(}PqS)m`D9}o>OapJv zv{vApuFCH73o6GL1BmOlA}W{k8z$I%{GYIcNQZH)q=cCP@wjrkbQ+eZSSl}qyv@S*Q^VYz&WoW#wLZ^9}#=rIzkZc zmJ-OXq&8*ajs|>g!&GHqOr=}&2U0}o*MJ0hv>a#egu0*o$=CxBDTANeNETJEF9}y? z^qC#@t@_fx@S|~EbBXw8>P6&BEHmj!;*u+q()Ur>poJR_K4|*(-`r+-gaZ>Dcltck03Zqz#{FWkBh*}X8l*w zHC~(JnX?YQsE&9qX{}x2!P=6rYg7NNG;(jkQ~4Bjtk6sbi`-ap8`_+vj-Ydy86r!~ zF``bDT>Ox=&}u_uhg>wEan9EAG_T?(;_4X}sk}tsb{Gd+ggpee-)ybC1-^jC=P(}N z1S8PVuAB0r#=(JG?pOC@i3x=eh^rE97<^E!P21&KO+da9@sl(t-f&oL3mNi zdOnU1=07(4VXo@_Wuqy+x8f${~#(!1Qp8xfUmb-D~zCBLx*A#@M9|X~mdB zESG~^{0a3E??{wtEj;*WtPzcYA^mThS{{3Ed(Wrr|Xwveq9v4ohUhpYzq57nL-Kxkxz1_y>W(Ws&Kn#vV@Z>>qy0BSPN zIm}PU3khwV9^$WwpK7~wE~1ZfX7S@C{O{wUsH>x`m5CA1OvcRfpQ!i`I4o8i`#52c zbyHab6)mZPL>$&VB=;b-#e{k3p}tX`_?}j4i`Ys;1aH-I5<6`{K2Q#{p$9^7*p6)A zOiV66-@RSKgGv0v5rIr0fzzJ;rYLxUdBHR?Bb#)(%2|ATE2O;roeiQdka@HiqRFk^ z;n#HXsO+JIe#sjipUc+s zka zVc*-XqMGH;E)yRl%Tp{;weUw=!|^D z_srFdJA&57>0x*+^cdQGC0qEczE7bm!9~eJpG-;srP#C;?AZ3x$}5x~PA8^JvGo8G zLWc-5GP~+cPOm8Q29h!>vHSZ7JXWUY8n+@hUZo@+`7Ku6TGHYIX{EQovdD^#P;0f^ zPgFkDVoAE8scI^Wdnd8zGz2xoFRt>j;#Ici_KurOn+Z;u4qT#MN&*d?Md<34+WU%u zkEy~AWd}CrE((_0Dnl1lEvSU%(+Q#J%;Q?HyQm~pYH7G4Bay$h#xqVHnmkT`?mwpd zhlV3+Ng!Tzp@BFzamllRcb+_z67fTbp%Sn9P8GF%YmGhCazKXf>7p9ufojfD>!Vxj z<|-{F@;7>+*PE&Yt%ceoqnx~33auaRT?yMN7v!RSjE#r7?0P8QPo*2V&(e0^1VDe{ z>`=b?YrHpe{LxE;s~y*KpO`7RUCAiosr`NZ1sSL-?PMmk4c@=kr5@kM+yB^EJU=MR zM6c{1t>}VXz|knpm{nLq8gpnRo3_DjNb`9)@mA5G#2?F2os5PhrOd(5pp70a0ULdf zq_aLBEY&f6NFV*HSo$neUf7;hqKsUOfAP|x=KP2vYW_H_E~w~}q2;6h1D7t&mV*D_ zjPFf1;WoPzkF=u;2v>yI@Xwp@0Ut6m2 zseZ5OKz8X%O!f5GOYB^a{=6{26>3f|&c=7~R8Qv<3v0=UTT%}7xhu}6y6=o(O6#Rh zbX&K7X@NkkT^SRH1_KiZfPr!UKL*`@uxWKWmk%8vKl}Q>=>Xx*Vuq_0X_LxnlSIPF zjp~K8JB5{6Y{7?Y$>&5X8?-m|#apRD>2?ApC z{OUZ+@jiE%@|@)2cs>-E@`H9HbZ5K$gf1;lW?{$WHd(1Yp)A#AKiDvVsFl!^nzWf> zx=?TF+NJJdEi+ri-9!UgGsikn_tab5K~@C(2!|K7pk2G3gcF@bt6(|`w+hEQ3L|#h zk&`EtTw>{Lqxk|4XaV(nL4_zcWeMEt&O4`yFMLv~wL+ zj**f%&Gw+je)?ULrsF(WD^ud$e{H!!US}Jp%a=_Le4eZF44H#RX~s0w$dk-}br?)6 z)!wFrg2AHIpPL^_UEVK7k7sLGhoMMx3(qYFV%17LubyTOK<Kj>LrodG;GqpydF-&ig3mftED^hzDC{g-e+b&OU8vv__FWiChE-eXe{qY`DZ(?J zq)knwi<23rTvi=$G5gT%uVr1YP-9(3;jF8GWA!0(JnEJ!gNHCVamXh862#w?E_JfY zvp^K~;snOz6R^wr9&a9IwI}e36`rYp;wf6!BXJu$3)jbqGD`GJ19S-GabYzlp&AFlow@?=A1HO6hdq*(FQbS!P>=mKSCrgCFZ}~c=l1oD|XP%qo;LVfy&{{Gs^X1+fXTV3`mqL&l%4OIWz_ivC%w=c-@;#gMf+*Pu# zfp6ch@x6)q(xj;r99xY1OtrK3+*yn3dsQ#ELb%l!ZK#&oiGnA zeWBcsGmp@@eDJZH0)Z%XT)|w4=#`3vx};KrbkrxFi3Kg9?I7f(+wNM4VEc|9engYo znkXzzED8~3dhDe~ZO5aI$O3{noe6Vsj2;w*-BS-a0uH(Rl}SRR{-9>0ZL7WQYHS70jhD%St~@e!d%hqt2e8!Y%JG4&7TN?%m8UI}4}7m@00 z>HT(w+VL#rjQl5Mt9^ZzN?Qqzj_P`8ifr|o(6ArSKf=;PhA*kvsWh;}T@uVlV)s3= z;OS7)rO#SkQd7E{$*1I_d01Ns*Oe=fvd7xwTYScUV&G(6Ivo`AYbT6O4e2|6bjd9> z$Ok}&cH+1?OlE7dC_!4`++A4NlJBd><@*@IBpNX(Yv=4)8LYa@5TVRQ%hHPT870S+ z8m=H>u-%bA)!3XcLQxSAcP+K5@b=Hv0!3IjF}mC+=&U9wW(j_^tskycrDqiR&$6|~ z?B`z-RBjr~Rx?0kvI5BBF@5C(kXh~ds|^!=ql#JhT@Oz-8oYqnT=+;_Hhy8V)N5HK z@e1cAvr=wg8cex@qwK)oE&0B213^}qXh4JVn|OK=jkkEA!l^Dt+sa?W(X&d0u17pU zpo2vAW=@Av^VA>wU&*moOY85Nj~%e_@e=s=cY-7k=%@lT0=l{=Iy<;onf_;<#!Q|^ z9#RPXM&}EHq$CiZc$$%|pg;&+QfL*eLzb}r_qh-2Gb$&Z*yo;nvq~!?=G+Mr{2C6Qlm21aUMcJE@R!-6_=bj+* zy`ypKUr}m($!M<%XerI^HD#PE`#Xi+4ETF2$-O@F<3eX&x9eoqjQ3aKgj=}uJ90so zP<@}w75N-P2P>!5?H%9#a#4U+w16o2hzhEYsQACQr~R!7{r@j0l=T!o?go4+Yt?od zKQNHXk)8~T7C5Igg^dB$~Rc;OU3D+wj%zp7=y^P_QZgIe9Flb<(D(z(o7MO-zk_V2J4 zn+tW;r?rZc^et5TMdl&qMOcxUe-DxGTU)bYX_4<}P9By`lO&YQ$By~iJ=Ug=bUDG2 zFYWS}{)uo|nf{bIg`+PvMDCO0S;C-Rbe&nNa*pzH3A2dsv+rj;>DgIlAX}+5EnWXJ zbX$t?c{KJY(S#;*rMUE%UrvtXvsTvlkJ(6BTJx_)$x}5^W*kbSwhT|X8YfIpRKLEo zl(us4h}U_t-`)BN8e!p_Li(aibpLkS|zW*>L;zeA+5nUkxT3-Cj*R@LF3vSD(6|EZLn zqwPO=tvi|+x?hQd%&gF?u#UBw{y;{_XaR`He8mnUuV|{N3b6=Y9HN*Z42r#|t8V@ZlX0sW_vxQM3s@8lVg` zsRF9z5?bi0zt?QZFfyJ%;O(4b%+OzLbPVcsD|YZ!Fcm}~v%RXPIaw`Sqbo!3>m>I< zu~cfES)?#BVvUe;M4;f>=%ETt{v4`O!&6PuH|-8liu<^Fdw=WFUT*r)A~<|fqQ#`? zjaZ|O61lDJRmKT6P&|3!gCzfJW|adq`j_j>>#aHe03lLn-#}H0-={Vl=O=LuP1nA|;e+3!hI97Vf51@6%Nke#cwW7M0*w9~K#; zf+ys?dJw~X8(qj^L|0vz@0E%`0Gdkl{1n=h*d;x#53g=Mnj{~IX1{^>&7mEgC%6LOkztkHCCUt)#KfRO7k zgg$sY_7ZE;lw=b16AV}E>6;0<_9P1fv=Pl2oC-V2XctMttWN0zAUR#To%+|$2~iCM zj3VDGsIs_ZcWDof-E+F+Flz;C#?lEB(?5>@q$%B{QYh1Cl~yCDss_HJrtkYRE)1-` z1x_dNmB|eJu&eyuJBqe=WK=mqUVR_fnC``9XR;iV)!pAIxpBekD|r137p;U#eg%p8 zSDmaymxZN>4?scr===I#9XJ06p#1H0`756M?b-i?6CHPz59j(4Iq!@;L*Z}wQ2CUp z4QjECJ0XkKQg{(X#kU8u%~s6c0<&10CZYCv{r4cdpi--g`ELq!&$+myY!Cv6cunud zCx1J1`KJ3G3<`9=e=>x=SH|x98T>5@C7Rik=o++Mag%rO>z6+zb*K?g3TBp;1#oC_ zhab)4fwAv>od9oH5JKTs9v+&|u&!9L$8pk!6^OFX7|Rb0+fP-r&CR*LLuZP8(2m_P zvy~hPCz1=>fw|&!n{-fCs;1{bw%Qo zm({BkYOF9&u4Kna=Vu!^E&3Cht_20trJ_oYEs|IdZRmu(MWJ#Ec`5jZJsw>!E&*Sl z6s!vUMlV-r^7|Q}Kkc0GQSa>`A{c(Tot}P+q@T*!S?3prLJMXwwMg}@`P^_@bGwdq zOjgI<4qwMqJUr6buL+`G+>~w_y1I?6O*wgNkGtq#+1Zhmi<0mSj$ z+tk`h5%>&u#;l}ZS5Z+ySP;b9gW^i zU+CH6z1>|7n8B6^jbu*oZtX5x9Zr$ zQVLMGsaE?5rs_P;_`fwW0NXUU5?{@54d#xTIHteuVoI6Uu$msaR4oPJ>7-bCXV^))Cr`c^k z)t?(-9ce*4-BLKFP{w_gi1C6?;#AlbnCc6WI%W$OrW)4kfi4ksRy_S)&P#N9!v&rfxNAR@8Dt+Ty zPuatkG?X1&7_!nO06kFY*JRm2id~sDf6Z~*b{p5kEVKCJPu^sKxivMGSiRwjPudfs z9D&o?z2hZ_5?lH{j9Rdw?{90_B(s`ON)2JiDwnj}P(yK0a^7yAW|-DH>{`WfyjJU> zNpSiR8br18g7JeZ(Ro=a=ou(Vj;jzXgpbrO@pG`!>_y>ZWz47cgCB(A5M}4IpgWl* z;DfW~UE2*kBO0QQI)V_Gvwo@*#uO;@l3Dp>9LU_YH5YP;&%8wj`B@P;(S#OaD_)Z9 zh`sbYcBHUCwcX8P+g6iJF;&UN4--T8dqmi?nC&ijG}=L`Fct_7F2F~Y{o?J^uj<4@ z;L`Y&i!$x6)=OD^Hp2j62Z{@u>zTHvY@w>(Y{gn_*glC(zn5K01RAJZwvD^ds{FA) z--X`*qv@OgQn*g7vj-IzB;VN6{Kj-&Mr@cRig>W@w{$ns?$sNIYk;Z}+A{ZzA(rgr zTggI&DAUGfdlK|7RwiEyy@N|kLom``d=Kg|F6@LWidzFeiP^7=-tVe>fiAm~a@E3g z%lj<(Cy;hJ4B`~TFzTfhBia3-BJd=*C1p}krZ3MyS{i5e$ou`IMb%XcW4(HeEh?YC zMyhhGZy0W!f7_fqEn)(>3EeaSt;L&EGd4I>1x9iuS<|JrJ3^O#EU4HjQo=m{fP_H1 z1`%#lJsw2C%Rgc|RO`~%Ixk#R^XJW(8w{saPM^_Ksavc#?49;GKQ}JC5hZpgAid$t=QRIBVN(`B-dXJO2#l z^GN8u9-M9sO$-ENvTun80s&qnVL?3^i;0zfuTh;}HM=BXE#|JP6OUFOxg=MeDHi^( zG^TwBqQmZUUYy%eC9kWOez3@xFVzY=~X(m zOyYOUh-wr+SYed$I4G09BJ6Lw0cX13f{5D_=d2HIatpW3lPwY^ zt1Ze;CTnkvp8sp}6q$;U7^+!rB{{duy~CqNrtu7j=fe+58J&iIqgeCL72#kQKYzir zPvs-yXVf#Y85dHo9CU{GBQeyouQM{FUg@GW@s=0<$iCkgMn#FhYo$qLPKqO82E zFBGdjw!C~lNw*`(KBX$&|1?IW@#j>Z4|4@n{=&xI*){Cbc;Jp#xRkRxY5u->wbVO9 zPguO^;+05q1KIZu_OA(sBUAN7l@9=<`!Hja`oFkN{f*=N1ONW^?*9aT>UugKquzdD z!XkYsMO5m6O-#@>xt~vG~8=fO5f{AGiWP>xSpg31ZPR7r9mPjnV4ZkN7my z_S@xd??gL>)!gv`n%C62b4ORo?DwJz&Gre<6TGb?^GD9orOv@VQ0*&JeI zfkOtj3{9hPHJfq)0ls19Az^yA$&NDl!5n~&m`uR0^2uk`xp6Q3qfkIc;nW#wKFuhd z|E4lJ65^g7%DsL)>Kpn_dj(H+L3z|RJ=uVxX%v$Tt@_&q1)U`%J8bzX3O1ciN1L;vbc)r0-OR?Sc)0To<47aE`tM!uA+^aimAicTg%64hGFEQw!1r2sOF%_ zhA^xlr&#RPr&!wSje1~`!?5!;6=%6{By6(J(9^M-uwhP}n^a#Iy&46XfRm$g)Kw!v zj*rRZR`m2E`%Ft!{DQt=j+i(_|~Q7NR9uHM(cNPlWf&!64_$U8na4o{+% z(e}!ro2jk%2pvrWavc@j8+ib)V`@P=mu%agq(ie#r8j5g5+L~00-#V z(?!!a2%ZUkb7TMwGl!zK%^`xs3x@&-exsT_8Kb6R`Uy1zA1%`i3_9&BTJL5{DibLX%PB1S;X3TVyTOoBafvZFK_9N7v;szqM=HBy>6#t?tH;i|*xiy{h)3dx{Pc*NScyxRB2YDUnlElzPV8vMWY<5R zr>B`APKs{c-7LQ7Q9k3*^Gr2VI{kz9lX}MrsGerhnj;r5ra?1 zoyenyc@h|sm8VPRG9OPpi-q6e_?w0K``clh0J!NTYar$aj3pN$o&iSad?l7f+f1wx zPIdY&aaK!dLD!`?^hIGBs7Hdlp->>1EdW|*1DlNwcZPo1Q7AF*)FQzz^d?8282Yiz zIav*L8tokIUm6O4+CSxL^q*3@lPA}#@Zw_ zJTQ(uNPv2`uA9ul%~}S`q_W###Xb?lVns&wS0jHtHldm~{DB&D}U)7e?P?E2eV%w8`+u zYLD#2JhID%%RDVzD3*h90GR^`x27a>O&nV#!$gzVjRU#9k43j)M`u<^vJl^ax~OR7 zwhqk%A9o08u(?5lc<(Byd%FD0>Y1-^d2=VNXDw#gCf04%;s(t~|J-@Kp9esYlFH;` zBk@gJU#;lEN!B=0w0g;4Z>}OCWq0 z20?&(9!((rIp|U_f@kXT;T=CA-&ws(0>vaZvNmr%M`I9NO;@p8&(v|MdY&?V2wg;} z%pzj@&=La;+CcltwtXd>Cexw=7toICsCrplbj zmg)B5p0$Vux7Cic+EqQplI@&YGd8Ve^|ViKc43FZfKp-Uew(N*S5pxY{B_#L=P6dQFD5u$#%92S(4GwrM4PRqx@$MjTtxH z23d*w3i{&TsRuA2Cg!Fmy0%J1wi!KWVp^_<3H9@)aoJuFAk}a{CsM^Xiztk-`XiSS z&REqLE5Xo&AfVht#Sdsd5xJ3SU^81BxwvF5rkb7l>NoM0Z@o9MU)NXa&OL*k$TN{@ zIvI33jxJloyKw=SukH;A#hZw24k}V#$5hXT9Spl?MG!`T4oEa;KaVGE5Vr&q&7{ZY zrCr}5Y!O!0y1%mHZW#yIGk1bl$F~x0xiWJ=M#r~eY_X^FfNvmPzSX}5h9Z}GQ)thK zQACp}-y+S(+=Bym$q9_@w^4_VJ0V(i@hU$T3wUXlR5in@oiRHOc4D`=MoLW;TvA3f;{9`*|4 z-2|A19+kVcMR4o+nBFn~p&p)A681nyWCHs4tCz{DUE_z(Cx9=LTNQ~=A?D0`lZvyrS=|| zFUrrSaeJJ?!8*oL&Wm@4z`lQ=zuLdCLLVgnpp}`+-^&0(j*fqA5*Kl>H@C9* zD3txj@BSnIucGs}+R$4G7WGeET1Ds%5^J5GH#<5pQX&P!TIhrGu({@A4S?U1wr-`^ ztZx)@tdS9KVE*5)#+$5^dj?>M+zxcRT)J2`CtsdkUnv4GAJCnLQxz{22cY_2@;Nbi z(c3_|uwiv3IOK#>RliL_eHs_(w`Z{}r^u!6OPE5AQF)PA(#$9=JgWc~<%-vOMo8Gs zC1cZ-PZlZR;8VO`?}t9TmkcKy`Q3L8#Yl&A^s(Qt zmyoi+XZ!t7g_U5l_3`NNLekst&RvXz#L7%~-Go4jw-*EnmH<+bRm9#ZIpziP$ycVkUL4ddua zzkD#NW6~JD2(nFPC0kZDhaL7`)A)RfUhLWBKGuP zZ2CvYr+=iP|JUw(XER3!7b~EHv*+J8_1{DPzorqD|M~4dwsNt`g#4Nya*mv|Y@dTw z*+4QHT(5Lqj;u$`_n{l# zn~8_>iwQa~;I<4HB8-4Zwu@&z2G&qGr}&|BzGx&D^%NcMSvJ2)Pjg4XY z(~n%O&VavfQG(&Pya*4}rr4Frxcn>Jdb)2c`u@3-XnW7sWiFM25P3TD4zBzr&NMTsjCyA=x4s4?Tr{35p+0G_Lo6y z71a+ES^c5V0s%yWAMFE$sb*4csF>WdzT+G$o6+Xgw^QBzuZUo%zhnB519jCLB2OZ! zBN`S87Rrq?r~bSih&(m#5eR2T;#FjgHP119>?9KhDmvNwX-}(p|RA?&`8# z^_Fehwr$(CZQHiHY}>Y`=H8fzx%bOVOho>KeNOINx%PVC2|=xK=Uo&nWvghey4aM< zmjIDSu9Y}WvzA!p$~+9F3T%r}D0RZr6!{MHRHK3%vIjN0XkNNMabW`hKDLKVqx(dy6{e{C62mXfKF zQaMZs1r=WTm={^$gyxtw^OMUhPKM0ctmvE{(%l#OtV&fRsUN*G=-J8W-=bO8Mq?aX zbz&)m`W^*JVeISvE~unZhSw6P3Tq%~_fX-Z+9fAM&RfuINAUS<X&qx zSdks1;+)qt${k+Np+e*%h1`CSswzg06}liOe!ZS39wkha6Q8nCm&u+~lcCULlh^n9 z&Lt&1BAb{v3pCpw(=iuKit|}+*r3{KS8=R~r!&E+R+-$$3g?;AP1QfsC7})g|Lhc*du5fUFw5 zE3@~xL_-0Z{j}4s!|w49Aor~M0Hg;_x(L81GaF~D=)>tomedt~1%t^Mn;D(nsFDn< z;6ZX7u5gk>a3qmnzHc(`+GKTnr~G9`P@A-Z=EdHEy}(o;{)U!KyTV@GqUo4{2z>cC zo{li^3Or_2Y+3n*;;|C{C{A3yTCWCNC4qnwy)iuIIa34&YSFMOo0%O^x&u|nQ!by$ zK=XHCpd^yB0?*S2RKrARO-H0%HQ}ARwnXe?`z>aOc<3l*5Ji$7)E&<@6GZaDjk_Mj zL;-i~nxqr*We7)Q*dtizijvBVoVzpeC&~9DaLe@C;_G*kxd7lDnWSM8wfHLm@db-X zRVIq;;`lwsQOWxtcAQYc!!-vY5;EILLcI+% z0KtZb-Ue|n2gd@+1-BInEeJu7aRK@^{LFaZW|?94#y_Anm}ohZ~DuD$UfoD!llC9H;Stpwq$9kc~mKZ}na zUXYL#O`_#FK}Oy-KXkuC&Q12U){A{5nJMM8~iHz8)@gilkZn>B}oWmre2i z+hy~={gwY?5&XXa$^ZTLT%|Z=J^w%3@*iv9AbIZzC~F}!EvUgUr6NVN_&7@0@`vua zlB?pU>W&WZL#a1lFDQ7D6?2l@DYu36*zk>1BbImJ#8-^cHje=>Ru>ZDHQv8 zVumr<5ZGb4O%rT0aLVEh2pK+#r^sW1P&_ju)V^feQjr;4ov4&LS=++Z)e)bSHe&v2 zkzowNZdnB@jrNZvB82pHZ*TOZy&{R9dye1z+6;^C31z?%38Fhm4bS9LksRv?VUX)b z1INnzw9C!1Evqz~lXAs!@vHu#IedMp|H>0W8T3p4iR-c%MxPArPdkF9eSqxk*zbgNni)gcl*CiD^q~Nbcdg5<>RNd^ZtJvp#OesvJ}^?QRoq~ z;H2h?^Pu3063>x&&4UzS2=GmF$%@E9txU&)#5>!P~?|Qml_TQ1FcF?O72oxC#YAo=B#5gs%|K-4JM_&kzk7`k}62L zgA;Yu{gFW1vM;?OX54w1^R20ZiSUo8@D-&RuBB+xGK?#98tPD_x1#^Um{n@ZE4j~9 z5>+4L$9@6x{1P^G7fpz&qzMrH3SzbalF0AN0BYCsW?(&Qm@)JXHBDLLmfx(xyF9J{ zbNDloXj~-AeCS*nnr0(O>}8DaLzW0*dMUFMX4SEz@>zbLlrT5Br)hs=2S|NS5{*83vB-KG5%ASCdJ%VM><*sQ5vX zZ%~H-&pny<}v& zIiJaDk!8qge%KB_-zuKOK7FAsOEBsZ(7ewS!#zE>%B|6^;AApFUWBNgyGd5-(!nrH zR#XrG2Q0Vm7-Vhf$AD=7GVB{wAC;6ueco=uA^P;bon<)YY`Oe$A6E4J`Fnf&{g&sD z@_5D*pBJW!74r87bUA3boIq$~>ApE<0k**H)_!u85tO&XBuV9ot+FHIR@O3H$MUp= zc{7{uFFm8Ve^y#kC(ozDvIAG0Y{?DSiiDg042+p50}=b719_>>ASX=x2*}u86X{c> z4MebDSY!~GYfe=V2`Z)1R$p?*H4jPa(_TW;v700bvz4u!cv=ploi-#vB`_D9M)#9 zc3ee637vVwDHe815_9HmODf|`;E#D%onwMlS`Coz97ltbNzKar&dJS<(gBw6yA+j* zwoSbn|9Dqg244c-2&R(tFXtH5Tg(wqXsk5%*ZOo7;O-nXr&&YnsH+uf#dq8{ctfW* z`p=rB!Uo#O^>5lU_1LiMg!vMB)hh`@?}Spql7S{BBUkZJQc!`$vk1n$JNW)Yw;fcKzqIz_60Of$85>zud0U*sOz14iOvQ1WGGeU4 zTCAr?yu6IdYf;Gs$$~u%-8>)05SYeeJhW@=xX1-*lgY(-XLGn2i=3{`%@A&Luqo?} zE}86Pk%*n-9Gjkv_;F8xzS+gry4leMspU6(-Jd+_nj^;2MK)uh=DO6cyEWOa0aZbhO*4`8@cH8Fj{yCF z?A=zcbfcSSmqzdeH%%);o`%9A%Jq@nTeHs!sVB|cT#mD(efiR8oEvHn@Es{iDOHnF ze}wWw7#rqS%~tAgCGbUHR90`0cjF@6m%I81?Y#z2i`tp2FS!4bv8Pd1Xy&dacP+;R zhTqL1d8Vfj@Pw6t`KWd@rr()n!;;hIA-wT;AtD%Ep@xTUSaEfg>WRGA#&`koOh?3- zu)A9v?`Jf#CBrlijy22V0GqyA(vJ6OC?Ogl1>=sGsha{HevnjuV(`Gm2x=~8T08wq z?+G+R0idP}`(eWs{W1~`*+?bcpqIebU>N?E-Es5Gre;%gBx6!iHyP>o8fHaQbI@PXfA|>gI1ZzbY#Ngn=6672-KZwgI`h`@8yE{Dzig zYRqGJ0DOcF+6(qqXDJ$nji+`>)u0-G)Mrp{!V5UT7(ugRsSokb&i`%nU*kpY&N^eb ze$6n~Tnl0n#JBKH#|!>4RTt!XnGr-|Cv)X-D-b~Ss>airocXo|*eB#SVtE!_^3T3_HYc_{CJu?M!nnal;+F=+tCi%hhSe1 zS8_Xw*)r7N_* zeB5{U^%|DA(Gp6=u6jzv{17k?OXG}_WJ(S}dD#5#z*_addP;V(_Ri3=Q8GDmik74Kv1h_p#7#MpqSsyD6#9xyAv>drhKE|BOjP!eHR)+-gZL3?A zihGvaZUNTDYWlKBZYSPur7-7Ia_0G(Bd6C3DP@k;oX3Vz`96O38u8TKO`2$12dOm= zSj;tg8_fEJ+c{4|_e8Y!FqTDS;(N4ZTJlULSe+MiJwfC0QNtJz1gA;a*^e<&{~9}N@K6+Y0y-^&csd8louNjJrPNVj$CoF zX0>SB7DdMu$MTYT39n36cw&}4biqhQN5?q+lAG~Jf5nq!4S!MpR6Ry*;Nv}%`d7Dd zxy17pZ~aD6%|dIriaWhaLN=*Q`9qqO1G?5Vcv}{biWK8A6~tllW`m7K!hx}fy5xyi z;g_0QDs;IJNDFQF(0FYEz)PZUM{-5|N<^Um_9Tsafje$46WEZPN%q62Z`RW+$YT}1 zo9$GsN~gt}!+mk?$yM!1iIKtKG&xO9>u<(3tZcojG`Opbhs643 z)jK;!f|u8&)kgkwIFU}cDN1FAU0I&+;tmh=u8`RlNf@Z%C#rnOU!dt+axF`R`N zL{*xp!oL1?0?q3+9*>NW=0U{4ke1rggM()~(`OG0yJVupzUo*wjju}#JnF!3UJE-2O69+Wz~8&j>p*K-KK zrNW9|$$bT-A8tQGZSbty6>rJ?6o&QJli!K3CNR$?C>iDMG1?2MjDNm3P~Wkv&xsn< zx#=6OGOFz%Q8j_%-CjGea!#MS@AJ*e@W>~^{c`chC+X7Nb8>aldBHmL3ceMk?lO$2 zgd%KJ6UMP?6=+xS7N@vWqSauaS2* z51D=o*}O}?5l&hQGIMhlVcO?XhfDlU zPkJ~jG*TC{>FAqwz;2EI zX^p^i&rf3L{^+~LO0|dHdk5Xo^-!zM5WNpP$``^;>o;NR%s1-QbIu^hmxAl45B7CI zRAmLWbX-hsHp{FrsOp+^dyoi0azl3W4cR2JCZ9%D+p!xB!Lh19jb3~@(qP0viIpQI zFx8a#nluNZaW}^)3;rU*h`+k4;>bfmW5NuLfpv9(vbjK@8*Z+1TMXM}fmS1qQ#VRu zTz@2$C!6;Az^LBFQBE$=<}{Rhk5A~+T{lJPSHMDFfqCRhM`^aTij0x z9)^x~eTu95eL;&NX5Mp5*o6exM|s|$iTOy%XZF}m78F+|iP&G(rtZm0%vD@L)x}OF zwfSbBE~($}_WVX|=5K)n%RK$InDvf-G4CCD%X_}Co*)x>bTm1T9K zvATUhni>730Rf~4e}5cre;i`8Em15laE7hWACzcNQAjox51VSK6{3y|LkwruF?`Ve z?((bCQ#Ph}qs&ik&P^??$F1*a_nL*yrxAe}kds0c0mxiIK3O61ama|j#+;UssbRK* zl4ldY<^=`nMEM%Zni8f1?wT?y zdR%eg8oShDjLhtG+~tgAUw+em*-?RLT_Fv%gn{M@WTi^<5Ke)M^Hj}n9-N$1${`-E z$%O*4Ax`TdMn(=3yZ&S&oM?}!GyW$jg^j5~r8ZYxsvM<32I~5NPJ4s!-mX?`n{S5orZfY)fqS2_w z-?;y6@2QO`KV}WQ=TbUqI5O1ueEs28>U5Uf`AHdVVpdocaaq{W*)+RhxfbCj%g6#M zS$N{xcsFZ-bh z*v|lqj}@4`*3vqX$#nlX zwH7eO@zoYWPeCB!k1%%+j`Bfa zFhxvHfYC6ZF%+qFcET~P74o1eCZ#H>HCq0P4K%4U|E0*+-_@l2?)rBd8?G0(%zygp zGK_)_l6uucfaKs!(xV|wT+pkV-apm9H5^ou->NzdYMhTcdCmn^>N>jGU?C5*iU7A4 z8faEtk5H&|F0jF&w!^H8*YhFt)qsKq?cO5ay~HQT)g>)_;?|pAwN>#M&{2;RN82&{ zK1JXmDRIUnw+zOCGCM6AXw(#RY&E^lvgyFrg9`6Z6kcJ=d_GjmG9+?o*VcE1VZ%+v z`INp9ctIh)^IaQmVTY$z*1K(E@w9LQRU!@3_D8Vq7#!_)p9s`M_>JD@Oa1E_c`Di{ zP+J_fV8zZWJ=$-K`YZrQwzPk%&`?!tlx?T#ELOxTy4u%|oQW#XLSL+=jNYmp4JI9) zV~B@7g;gM?kSaVF1ftXsIf^gv8|8$%Xb*lv4B&} zpxgEn#|4%gou-c@JjF+NvQe?ey&-cF&tji~_9r14rzhqBYS{-s;Dp)ltvm$c8jIrF zVABdeKY*LUay(5dx^qu~-#-wD0_xZ3SS@KrpvFLsdcIdXL^k>mL4n^_5Lk@+Jku02 z;k4M8Ef+hHqUebgV|QhTN6usG}rKyfZKbtuucQhd*kFIFp>iMQ8W#AFhgCWz{g1TWYYHvKN-_1f^@}Du)om zRWYpyl;|mYDig&EP|w{$o$%|j7YENA+3{F|$@iBd|E4A5=itpF+FKRqFZH4A9hd<7=f4-axT5E9kO7Ebqd-5q(kAvW_;VeM`K4o}ChC@8UhD z55i^1{&!~OZ=hMpk^K$J8)kHeyR0T*3R70bgPSVRGrRj-8baHE->1Shd?LHEoIEwX zv^Nr9--UZQx3sHZE3HQ7`~=3~a0=H{Op`a#@UrU-f@!5q-T^*JH#QVou|xWPVVMkq zn(K9ew!S_px4&OxXr|yaWXvx(0$KUx&)F5 zCP9}`D9JHb+?dku?TC%h5e(i@J{C~wREay3Mi)#<%m->1uYcny72YeBV;GnIn|oD? zq>(+vG~Zbu)AIl4RtP^!@D#!L8WOEwhD1%$DDs$UeXg}HO|uWHLv<>n#fPyPJ7fmN zT;3R%%-)f*Q#%nEc4s85+PYVB-fnX%pOr5A~crfENhn?D6WjO9EJ%eCCvq4;bx11YIO6K^Cuw2b_JC3qb^_O`s!S; z3nC3(hbNnyF9?Q#4dHtE_)al+hKMPBnX>0c=qDxQPM+gb8g4jjpF#jbOO(9^4XrK zY|kq*9V52wmo-yfQxc7N1Y80J1(4>zkD~(dnFdKixTRNPqRIiwRqN?gTEQlE$P64Y zP-@-i-Q$iju$r0o(0C-aSn+ta`vs@D>&m)cZ)!m6y_V>8$+!~e%5z&-50niGM`g?qSvzirjv;tp%6P?H#hl{_zm(B2)U(G9LhIA>VFq^eBZkNBtJ-#qwPff$0wVxS# z-?jB~0pTd-O3b21spf*g{jL{TDm-^~No4g4@GmyL9&3xvs>ju{;b+rak4P=ao zWoTj8@QCQ%Y*-$>V4udK-lLg5bpsPI`)5Dk^|vw`4C?wun$s=BW#dwD2U3)H^Gv2cMEn*@@VZ`UdTp+OIADtQJ|hs zb7`S2hRL}n?cLt96j5EiElEuHW-LI~$o=f77ZjT<3#d`ss5vX1l2QUVV9KoK;Q4?VBb3NG^x$c z_=l`!$VW`4%fI;pZa(wHV?uj|6`<0wPe}6(ip{axR)?pjG62C z$4~9>4>;qwUJSDXIWzrc*gwQWNlwgyvgPVBN!tEQ0ovjKrqL%?&6l2(O{;8|e>Zl& zbqBIeRNX3)Lx&wJ%9fc#Itd@hxq-&j$#}{pa=f)~X$3TqahSJuU^T9FbrB|?mDn}!tmWj&CgxX3*Ka!u5kZx?EL zDQ#&vaTm~D0R?R@iu`GeSQ56dz`w*1b6LzGW}&?)_AOFtfNs?cw^kfnxlJtTMLqM! zWhh_CCuIhg=ax$NVj_qg>lxF0aLmxY%cnurr7T{=9ig+rk=tHqfP!i?a(wGOft65F zJxImXbNYe3)tSPGfi}Y2X7pFNZ#^NYd*@Ak^j;ZN+58kzAV_ParLzZve`yOo8t?lSPn1cV9)3BsS=L zulPxCV;B6a>-uv?mpY2E>S}jn*5mt*@f7(APH!dn9>>%NH(Z*XJ{Y@EH;{4AM&E-Z1ZoN`hJFZ(zlm*4-qv_vrl znuo_{gYiYe8VQ8D|A1%v{qzy9#zSo98xbRaSYuk5aD6v_BIyD#@tp}UGX(-cmH~)s zV8I^Z_jDU)_m9{J0#PA(!x8{yWT`L&sVG5(_zYEs(7i}9KL{qQrU&dn>XYPD;JS<`q*B#(Fgvlo=%B1w9R$9C zbkK0^S2_~q@9zCZBnqsV`qPuER%yI!>(_~mRP{l&cHZ_M9%wt;N&4)Jb#s>4XTW!^866wpHV-uYSQ zs`WYZLpAPTlc;iX!<(VX&2nxNJ5}@L6`bCE_QS zj#0|L@oXY{Wa<<%238}RN4r!~4Q-&y1pB2+{16%XZH|{OD#d>aAD$&2T^aCozn=ef zJz%|l_SCxfM$9eVnTE_+3bC;Wf0#J|4-BrhP zw*AbfOxtsm%xCj1-!Bv{ug;r46THp*@b*waB54v+_B~jpWI0VIWEC|0qnk4rH$uZG z_2a=)QzH0xaIR?3xsV2D{!)kC#C^PNs~eU}i)y>J30QPEl_Zpi6x$goYwPZ?VT4Y3@HhZrT*5BaQbm}H745r6yf@#^<{x z(>P?*JH`zh;jCmw&ENV*mo=mla^q*s&0YLNf+L;(sc{VN)w~`<;V&P5H%RcAyRd~?ekGejd5Njev+N2=0hC*Wm*1OM6+=Vir;+)Z znmdQ2j}a220oqgl)`c=vc&$Wy>=3mddshxK^;Bn`a;QoREd{J1#YKo+r2@Nxuq_?a z;_qg29DzQg3lJkbhDlxTI^Ey5g`a37<6r23`!oar324Qk9%yV!Y5GCu{M^(!qvfdZ zi1qol!MjMM$^b-&x<1d{u*%3Ce}Qq&yv#g0l!lcHNi3WRnhYC*Q^cUvQa!=YJm$ag zE`rzHl9>f`DkSJ@9Qusqa80U0xCg`Ik#5lUb-uZhSPm?i|7xh50z#B92qucz`1SJs zJyf?Kmvz#CSw}!ZI3buN2qgbtYh`PT-1GssmG^1-M8eug_4LYA`s7r?AbA)W>ir?v z6WVL6W~a=_l^Y=iuvBt41z}L}!fc))gjBH*&Z7B^9z$lYeVqQLEVhmOqOh%29QUaj zL}W+FOo(!(ee%uCw8hyt+s{{kMAD-m!G7_&Q+nvC{D43ME>*4HPkR7dn;p;~6gy-O z>6q4rV*2D=a^=B?*VW8`ae2Q)Ahi!b-3B&r3JfaE zpipN9K?Qj$6Z8Eb@UkcUdkz{+U(vj9vW*i9c%0Vm2HZHY z7ytyV@~&`Dk7#wAC4GpUiWY5`1*&zt_TrzuN}3hqP(=$X8@X1rmbPZpa8M2WWb{CH zpl7UBon0VK(bRfk0E+N}hBu|YlzG#$v3~9r^`N8qF}#bWlzdhlWva5)v>YR;~t({>SR{dbu{f$h}^9?r+$!eHd z?Fwd9?kxjN7-py|5$ z%}6ECnw4&zB(gQ_=Gq(wZt)Ev+DlOmtVYHWq_v`k!Sq;y{wZ8t#y*jp=&I?+Wg%&- z4?hpBlw3ci(OfOGq&Z#xwnbubzKhIPjdq;O=E-oZY5}w)v7^)D%({IPBUXqxTOq0t1i z72hF-RGIgG-QY@O<%OS+9pYCAtP@Fdd$FsA)G)!xiLAnZrw->|WTXZo8%39L*eaa$ z7Ax5pOAx_ju7RNf%$cH8M)RNo!(o?IwDkL#nWYNFz@^Z8^j8x&m@Bo4N!657wxzj> zHqGT!oJ$>qi?H7IAURUXQStsj-Ve*HXqOj*z_E+YI;Qgh^v})v9wh^)QxMO>3aq-} zjLF$mt?Lyh!Qa9os^~Q2;1gtM4;FNFJh2dpPIxzjwTPffkWq}l617ie(el3wqmJ8Q_-P_0&8rCkkDVZ1 z#qYpNljuJH8u=>3@M4H_$!|@@g9MinMvl1?12+$+Phh&;0Yr)WrM8xWz~SvOUX!*0 z55dKVd%n$hEaQfTw|*?;LV8u7T5^)3`eh(#Qz~v71a5 zz-aeCjnPUOy4sQ;d>{ub%f%huK`vP}oGKQu3S54YY{4UPahhgK1bhM&f`Ix=@U)$E9C#OqqX9C=f&92iM zoan80&*uur9A*#4xQv@LPHi8T_Mj}>FDQuB2B8r3U2eI9uE zva!fohrdGgUr!h*Anu?Yito@j##Y?ED3O%7?}On$E^KL6ZSBNO5oo@mw8^3wj%t*w z^m<-1^=c^t*z;cfVOhY*P#I%M1hLU}$}K9ez|n8o;NgsZ5SJOK&!4qd84Z*pnsvvy zOiSb%j)Zt8SefXJzK;3o&ysFUaJz+SUMVBz4%TwUP4 z#}k^H1YYLayd|ujib?5brW$*CZ51QsE5zR-4|_)k;XPupQ~cX4S3Bi)j*-@MU5V1^ z@;kA)lN@`dHK~7MWD}}2A#GdD{z%mk6Z@oP{bGH(M3Y6H4PInW$FmcepN~ZvzT^)x$ZL`rvD{&nSHALXoz8Qrb_+9?XY|e(49CJSK11d$45i z6xHdfxX+FbiuYcrR;F9+u{2YgB_>AM8TtxGce>WW&*B_Msa5#A?oZL2?%e&HZ8j>B z3~!$(TK!vWt{eB!eR@u{@r284PA!k@$lVtS1Y$F!I$ejstlZ9fqhyG8M~)LN&F)UZCACV27m5$fMSPy zU~+j;_gXZ)gI`bMa_oy9h3aUEY&c>+q*J&5ekf1d49;Zka$eIAD-{~01 z)54!aS)&^b=*fT1 zst2boW@Y>(oR3)G>eOLjH^d?#l4<%vj5nemvrJjy=jgu#u2WA#Fcokj_~kMOEQ^;l zS*4%}MoLe+yTl>oy~i*@GJ1JAeknE4q^W^R?J{UpFywX;(+pr=%%4Az*>H1bEmCeI zbP~#6KqHrz5l>E+GWnPGp;9>QR7fFmhKK;)HPO_l5+kL%agp;!rOh5KONdf!boDA& zVusC5YFb}vdQk#UgV&HFg8={sXn4oc?BQy{+6-LbTlQko;XmtXOk$38?H8o}nGutd zOge5PD~9PCb&Nn`)c2!E)WzN}#2&Ey^VI9u6%W)*=0c2e!rvaMBI{3p&6d3aO=F2c zhfxq*5_V*O>v9wR*9wpt+in#?^b)v?eztNrGkF^S1XwI~NS`MtkvL@-NvB**U;V({ zwX9@0%&R8P+8W@*?3rJrt5+f9IA20V(C9_y%%pY+L}%MDK32B`O`1Eb6s8}L)QB{3 zKZS0OcMDxc>%FH8#)_Q!)B+?nn@Cb!sNV7vQh2+HgfBP9N2p~5SJeQtgjCkUJ+_S4 zw6k3*1GWkAHqZB7qVl`pq5@e!AsOAYQ;(@5_Ey3#eo{ZvWaAX#=Yx5WLIxPjvV>qy z9VqRC>WNz5jvG9n)xsV$JKg6eh*!1pJE-EW#EbVwnC+A-?ROI>8<=x4ii%z<%js}0 z@5JviXZz;t3lA)&g;7}(4<-zpP+4oX9@Hh9Xizq%1@&WCHi#QSZX!J%VU?Y`vgd=F zEkn8v}38xe=DP$l-^fT(&kJrGJ$$mv`!JCe(gBqlhMdHzfR30rP3TY{#&zfm>D!jf>| zr`YYuUJq0)kHl}M%G?fi>XYB{?a|78KlVVxv8wY^a42p=_E4&VRY$^*B`Rq~g;Uy% zapOe;qWny96tiX;)qsg#{LKi_p%~MSQL*{~)oDj}4@lUzep6>WY&yo=wc$VV1=ZpI zhAR9XDt_rNeqj&4rnqA|S(WnE=Ug{_OG`UQIpB~47oWH#sJRp%*3JNWpUJ3T)l$uG zLfLFIo$W*PnLP**o0#p3L({OHY-|6+KudCGOnn!uIHED&W3wyij$?2QKi%!3$8yyd zXStiuTFZfUUguBU7JumubhWS5{d;+zk8>PZyMMqHEoR5b`yDYx4t=2QN8j9X4KKf8 zQrgE#k2YaOk3M92A$v1jzGFy%T5Gyf9nO2nl+&Y2VjTA@cht$Y>^gU4JaKLp;Ml?( zxefj&+pfT|1)wPGXxx`7z-`ySjbXl<<=Pluq#+9%%J!+@@TvNbqMm8VqW3|;>2n^A zf|_=P)_q^IN!8y0SqJjz{g*?8@)*H(WXk3E7SqlHe!spxReHVa)iHc8sh5R1<2DbK z)Z>cThnxkrDlbCxheL#pULQ3e1pujhuqDEFzZBO8IW84-G_YyfE#8Y<)Cp}9mU62g z*PBXZN>~K)5aHjNlR!pFbmWJ`qC?^&?2?=eG7AjX;vfGZhi!3Px%J>nmj7AR5^Q6Q zgXWG1p^Nr*w~gV}N1KOQqsyc{;0;>><_Z#VgD&#z0>J2;aNFV1j6}dp{%x=O7E16; zk3T@_il1{gIm6T|Eks*mRu4II9I7n7UE%^1_wBk(qK`~#w2)@B{i9_@{S1h5sm7g{N2B;>H5UVjmj^Y@M;It@4?CH3agR zECDJUa@cH|X9R21;vFMG*Hl6v-Ft^VQ^Q}u5z98KblbP}JtMlFNw!p&{4w-^KKb7z zq_|}QjjOI1R|T{8Z?h{MX4g(k(ya>p{Y!LH35~OPYFDQ1Gwy3Sj~UoSW*@0oMFKDM zq~Z>*cB+X-xBE9_czpUfDHT~3Ni99>U_6?{T9RZ+)AX1^ib7kak*H>x zo^1Uysx6Bmd2Qr1@-CsUYb`x2>9JXPWS7z|YEvsoY19AQnP%?X+jVEA+|Oq;_l|qM z=X-wVcYcriyT5a0EX!&`OS>0)gmp)wr%!52EAuw~z3RNqrhFu;MJ&8qZK-f=BtKBH zzma_;WOa3cY^2-}>AQp5wliGS8N=-34j0nC4`meSg>%eT80g;|7BOH)LPG4LCBED1 zGsEBUXOA-4XlL-#M5>dEc3$VMZ@N9I+P;0GS!3|$7_)+(Vf(>(XBVyTIFlFs&H36Z z>8m!icpQGR|Lo~K5$S~mS{Ba)`-f-mxw<-U)r_Uh#?F;OK9|ignq6x$qoA>1npp)`U8K7gQSm zd&k`E2cw@{HrS`xaqe!@HK$bfvE#g23>vj(dvOxiZ;sq&Gxa|8=*F=8vG>Pm>^3~Q zdP+^3;QhqRwXPTDA0By9Kcv9$eOcAIBjvR0W!6U=>@3tYbPZECUT}Rs!XW#c%hM-6 z{IQI+%{pULS9>^K|Gqi0o5HNP`a13Ak5o1N?zjAvOQ(%AIW+Wb{c-Ps z(_H2_uQl=2Z^&x%y=U~Q@J7y};YsyPH!5eLGykl#G;b4^fL&jKk*(pg5I$`CB@8o1 zSEhLwUl14)V9pZ+&?R423;cq)Q9Qvq`YIkTobDG9&f|zTm5LB>=?plNY%vufNuf&* z4CeD-T;p6`QFW)ZyyAD~sWg_0tE(BkoL%bd;#S5kn^GAzmB!cD(os-6#@V^$z?(OB zr~mG}WwBg#nEk<7-lr%FJ!gX}a3OUflEqD?VXz<66LStPm>#$ewgyA~F@yXTW`5%Q z$Y#N^1j*)n_&?FXL1muKsnyel&5OU-ZTkI&prAFDOKASQU6XSgoMKNbt<&{QHa^cT zIMoo>{P4EAbAF>*;7`MoO4~2|!ZR}3`Lv0<>z?m{-`4INy0pP*Ko8Q-|_(VPp~)HTOP z-!<9uV?sl~7vFyVK=8gufBtt~3+Kgr*0QV0>dmpKmv=7+$}6cqI*~r(pW?L8)ch%z z_ElBCXe}~etjyjLdS|Ke$$?iA2Nj;J&FqL^Xcr%3OfKcP9z3Jz*LtEc-STD0UJHY| zG5haO-GelT?|9)YD5kC`a+p7Vcg0wsJSNEWO#}?;aTje2u&S# z?)fm^5jq0l>$8bEwPW2TSXx`ZUj0xodg1u54^kdv)zz#|ZgcKvK7LrJS#m-%$!Baz zV)Q#JUmee_;n_9;+`|F3+4`ee%JO2joZk?<-7j`mR1Q_od}`>;XYF3zjn|lu&Af`X zw7S)s%^iF~H!1n8uif9BOPi}a(n~J{aUOoLeengS^w8ZtQ?fG7Jak_?C5pjJy3Wj* z95ZKoHJct@nc$M$VEA13d=Oo`Vc3uwj&Baz?wyIJH@&q@z5dHX`j=7)Q#}$dS&h-q zdehySr1c=~%)l#k)$=Rq`A;iuTjf5k-4-``%^s7BA8@%@hD4?0Fu@O5@L}}bA7N9w zo~_vQN^T64w_q>lQzF>sVYAEqSrDIrgtgw`UJitIgd-mOJ)x&BloC z`6mw)J&&wtKDX^Z8&+z2LsrC{@%k)CEv}|MasZ@vfND}4pXCjj$qpUaw_%i5h|Xvw zlH4{DZqpXu)-}+UFNFVa1U_(8c8G)%;k&Hvu^Fz8OndhwbT*R=7`7AXIS}A#_zu-o z1y%p+xkFsR$$-X6aVQATm(Y43K;qjVBuFBHTtFZbMZ<{lQ6vgtV7P!61X;pKd6{CQ ziWEup59g7JLkdH3AbjhT5f>ofMes?5noDJhjYxx-OKLgdLkqU7Q)mvcOl7QrHMP46vXw9f6{GkeMZ%%8 z85q8v)D)935}zq4QL)EO!pNNr;eyn}J(?;kIc)6+RVX%^!{v*&7bS}eSgYnM656vF zGnqteq-j?qQEnSl<)zMp4S7gyinc?f9)Q&~L6KCsJ)+2T9givh5=By_D^JKoVgv1v zfePq{!JtcCToJD69EQ=*1;okPz@8qm{N4D5cPQrW4f1zOdaqsp(;BpPLBMcD$Up!WX(MnIdO^kR%O}D!m`chmIJVoK> zDkCn2wnib~?(A_pz@AL#!v$g}UIo&m6nnSCVv3T@QW^gKun`e21h##r5?{uolE+&< z#L#z*DR_-P_%gC(tMm{F?-_j}wTKIVpGR#i1$$^g_HLdO75<8ZJ`grkv$I#xzfMFWJ^Sv%lRwG2qtBeyTyt`*c=TiZL{jZ^0pu9Cp$}BwP!x9xHA0o(>dJ z?&9iz(3U?TC7m4SwqPzq1?DJ8dRA12uKE4bftd5-lxuG%0_QNuT;neVgTEr-KF5CG zF?j+cBw?td*GMg3`SKmh4lIxe7627whe&7(6`{|ifT9x{;=R^C{%zp&2cYm*$v_c9 zG=eYm1s0nTL+k?BOQdFq>-V0L8yeMBQbExg8L39 zuKA3xFdiom5~WBQN7Muazml4yuKKL@IS7S6LvL{rM#rSkPpTuaiMkt-Ts*-<8=yf5 z!oX)ms|t@chlppONk8S7MKa0MmvlJmL>I54`Sl2P0vH4fp`Tt z12#m&rl<-i=?zF}W6nrPfB4&?WG|4`f%Pcu(DR*??~O;(4HiI19z062`z@-#g3SIXKumYvt(|&)P{Q$0!Vqy~ zhe-H5tIud?Vg+fZ03nXKN@@b9nVEZ8P~^r?|hkk=?v z4p0C-EKVMRIJ1~A@`aRTVZ2B64X9a1V9-4a16o_z2T)>W?7@1kksxgb#R}a;*&!0X zd)x;Qv;bus(MzOk>9#Wit+il$F&rPMUq0=ZBE-DyqI^y_0NbrFcZBT^B)m`rC!3_j zr#7;e{=x|3Lz*aJ53d z@IFgppnD%awz7goYVg0Wlm=c9!4C@Lz(C!ZyIuxMjA#A2<)k*amIky(ZWugXv(k9> z0s)K=xsoQ4ia8^7r{TGe?l56&z=ToS91QqhEqwzgCYh+mVVnemP6eWN7@SS*O5=!o z`L4WhCNCnyUx8IOT)xtn13<`P9vckc*7r&Svckjp$PhCk4DxVA2Ks-@WdYyEQ`Su$}$YO%q|6ZJx@8%QG?j1=&(U9dpH{&#Bv3W z!TccNGQA&G1#gK_D4#=2#CBYp)zrvG_`S41$m5kjt|`(1pDA5x447qrOm(EQ401Y% zZ6L=SdQ^&l@fnIy;8%l`2SzB8<}1ce?&8ynqOiw@Di13+Z6ZOJyCCCETA zzd9DhS-nyb4#`?sJRSUcQWPcwR`-wwb>!)=a;r<_L5bE?qM+KoYQ3Hz_ji@0JUY>u zNfiB*Ji5v&DCKdGXWjU{hCLsaCmCGynuTjxI*s?G9wwBRQ-H5uh_Z%+bR9eI zg4Gf|D&LcDzpR;gzHJlFFdmmvg^D^ruNbO@XrY7Job03xJu1oK!)Ua!Go|;yeyUWm zlJg&I|L4*{{AJtN-u9n@{pW~($o~(7rM11?e*we)-(iLh4u;0Yrq0f`hIWSLrnaVb zF8>87>3>IRYUgU}{6D&Z+kedg(q9h#*E_Z~{EPlCo`(H@g8%A=;lI%j&woMn4^sNS zI-~y&rP2ROYxJi7;QT*i|JQdHfAnlv1`YyJ_YDMu<^P}ZB%SPC9aKCWOc{)A44s{m zRemdMm?8V>CF~Be69YB1v2C(bTM$hh*Vg|KMa7pSnZY$xXp*U14Mck4Zj!s1@JcPQ zS$>UthGP^dRj)73{3$HivhJiK-4i8QOYMBVZtpyq{@v;K`GG5humMYfonljK%_Hbt zGv>{2w?P8kv3X=Whhb*{+q#1=3Ea7OcGG(hLxi_P0LZb(Y4J8^OJwKI<9#cjVQ#>2 zLKSWA?bO|{S}eW_fI?6

4LBBIKllxo85$ZEVPmMI%2&b&?OMQ!&0*eThbp+hCxBQ24a9hh*{DG@ zivvOV%nCtbR*t#XU;7{3JynJis|>K1bqgu_6zt1kTti?`#SnQwTor zFBJIc>P?XpDh=vja#Pn@xA|u#w3Z$IG+d*K9m@(}8R$RtDIVEG3aah@MZY$SDmqTp z+EB*y(tAogbV1u8wwUUY>R#*?k(CA}lI%uPK@wRJMOA@{Ar9IXd7ZNY^N?KX)n#NN z`y}>trmi_+i!kw$MX{M!Jck&&+w4Q|1NNFJX@;OBnAT^6gVUJW+(O)S_GSA%qsIF^ z$+qLH&8Tx{3+)qe=OXTCd-TH?_%na?!DidiaVI_x#!0Jzawg;k0IN;Hck^V)cZde7 zuZB&)MYfm_#5h#1T)+SN9y3v%opsctOYroAXQEXcyV_+Efj-%h!5&?D`!{}Lr5oki z`OeJc=eb9At!gMs4sTR_emLC3#e0j#t`yIGsX2xw>%e7V4=#`HoD*0mbZvVL*4^x_ zj?o-;1??%!hNndEl2l~GLH=qfnbrU~xsehCY{o-*tXX^u^=H;{>e)he{s~;siuqAA zY}}-DxTYr-NHDi2X+llh9|pUG=hUJzvLgllfH&CJ*0j$+wvgIWen7VL7wroUTKpG& z!h8kh+P<}p7aYYO%FmN8gzn~5INGuVonp#?y1Pu5Vr%$vXq$8snGm||48gw330A2! zP%_9Ji7lz3O^9XKU+xc8lEktqMhMRdDaVN^^O71|8IyWNSZ94DLRJ?p(6E z^2R5a!|4-MKN-wE!8U;S#HLrMF-8dYsY5?#m=V3Rg0_4`6^9g*C}(5iBa##r;tRSY z&alsMu{$X>=zO1GkC`#`ate+~$DPth53L6sc!&+bkx1IZL#3~w#(o!4&wlQGvmt)| z=PdNEai4RvfqwpXJ|@Kj0TKCc$NfL&ynl{+Q72PF7gH1Qf3%Q^xLVqnm^%H(JW!o# z?V_TNG4gd{rU#RXOt2R%BWubc3P4>)PGdWihRz0=3QB?~+n(H%V@RKrGrxu?)2ddj zOj&lvAf#8NZBZ*u3aW9dUba_zFGt#F_Njgo?yZpReG%V0$?^WZx!Dd1uUmKBeKNWI zetEy~e%W}x@zwJ|^OIq6SwsYgECBF@z`m9`Dm7kL5x`Q0g(Oc_k}b9*FEv@TWG@|A z1bkjH9!~`46jYpAb;QmvK_v3Oze9DlFjWB$BLPZkN{Lo->D0%@(r+1R`#$+`QCf@4 z5Ku^uPvlZw*2ymAc_mFS^cb=kgxwJ}gBL``mdKARDf#~SM;%(CRy6u@?y1c-TJ&zT zX zvx_zzgLT}SE;jyuY}ZCisZgU=iHu1(6n9xR4}~)Fi5->F6^%@FCx&D20H@K;UjlRo zq^pxe*2O5~mBnX@6iK{TBo;M9a;C{T6mAwDMH%x4K;zBLYL=E=4k-N$CZ&e~psE{- zl{`IayYDSWVK2rWQHF^avgxWvb#u7b7&c4QGm|}32V$$SH!?GTcXra@0>PsXS*Fq| zpHiP|V7A@?R@J`SizX}^{_)<^S-^eVVu&H6Sb{0BqKC24gsMa!;tU&U!w%r>v1&yv ze0P*35O>^o#d5vh=vw>{W}^}S0|3aO#x?QeCpC7! z6dmy#^Cw=Ai6&}SMiK;Sm5b%Gv%SlgE(X*bISZQr)YPiDeDe(KZW~y|(o2DrEhhLS zio5Uax#xbXdviA?%ziR}8LgulGEvF&KEde;Oi|qI*`Xx<^#ketFzOG z!-YXdO_7Q6Zxag#R*q@Bg9;)7#U_$T1;Zo9MGCo#r(Lde7Kx1X5$cK~hBNtshv`vF3&no*;LM81HirpfcJvy|4o_4}i+YJ4kj-gj>{8*K z1uZJC*ZWv~z#3g^2h69Gw78+sW76wz{FUgoixP)AG)$)zUU>#^LOk{Qp1{g9X!Pg; z2`nar0#(lbfaYvDP6|F5@6BxS<0avwL@kQa(<2i4hc}Y9^`{}##F+Et&W<$3bq>`q zlO7$p@^>~pA$9dJn-enZ<#eo#Ftz!zMYkg-Pu;z)vO&GVv6Gi*iTI7eA(3xO2|a@P z1-+4n{&-W*Cdo?D>!p@Wxa<#*bm2N+ok6=8be?_40-_4rQ9rLr1Sg($L2)KT z&~txLBBYzXp!1Kxzhn7?Tw0KMK~9i5Yp5=uc1Jxj?unithtCeu8#y5o9^E^yKG8N! z8u3qUE2166W)JA}k1Vb0SP3XsPbpa+SP9e|qgnaZV7iyT0-M{4F;D(hjhj^ud zSlM%Q7B77WSsl)?d3M^6API+*N>oEUuXERY%ff_zwa;sA`iZ#jE#B~5(dgR^Qzx!M z14NGTw_6t8pq=`G7dYJhUd;sd2E&&0=sGhuM%lW;2m49rYbz8X*0zre;WwifHUu?d z2aKz@0E?n8A#3Z4Z8e_|-&yVxyU^-3{f3y zRXW(&xo|x)I8p6vRczRqxllbaPEtO<4B^wqTzCk(~TE1tnHrRHO##EMv_qb8a0I&#pdLk4TJLbu}Z< zlEz}25L=^C4P4%-r-pBM#J`(Fx25Yps?Q=6&hI&;gJrU%`n2}GE<@af~KFu zJAENu$h=1tc|VS|;B!Z?#Ci;p+@#?QbO+@Uxi_)Gd6e>v93YD^R|_@zrwjb~L)b5G z$0h2f*P(y#i@3&UUJDpi{ax6MJ2vF@H#76<`=?KI5e4@gxGZ=-$bHsSezRGd{Rq<3 zTjuJnD&6VJDM+3XHB;cNTH079cr;l#HhZq3>}-UqyI;G!6x}m>CaLd~yEF^m+Kg`W zp3Kayjo7Npxg>ZtqwIPxc(&Ghbv1g%RdCb4HNkRk^j=8ZQpYklXYKVo8oZ7j zyjB>zp5dInw%)${P`&&-9=pESz6?qwxcro-{R&+D^OuD428iT_Z|C-PYw}Fbw>QRM z(AWr99GR^WNS=U%kU(f%^ef=9WAn1-YKmdkjB?4l;XQ_vch8ia*An4lUTbuoN5SpH z#ysoNYpcfQ$>dqrXU4>R)1;M|q$V0+IM`9&B=DfY;UKa=Z#^V={z`+<)_r%w;$TB+ z@NMg*=XW%tMsV#C+76P9Pp6zubI2Q?lSCrbmH78_7wq!pXuj}LzA}V%7Wwtx(pP*r zPm^tN*^bM$n!z?F%E)VM_|-5{b@iG_Xy`7L5=-Ex#;OREUX@ zTOmGLerc%Su@lc4!axLpxQdSykfa9*{f4ZH(uj_;Y8D(R49JNCG(-gj!MpNO7GR;x zt)SK#cqM(hjP{yc-qCjDQDV5igJ8ECzJZ zXZQ2YTXxZA_jxB+IFX1k1aaON7dCr_UJ3^0&aQYT70&Di2!H%YPM}Rn8U}hbF_bPf&V%H_EZNt#lW6j-O%GjO*(a55+GPKQflr$3+8Vs#mp|pURijwBME98-ADS10BRn0sZ3C3G1y7RZEe;hWV0qb(G< z4Vh5HlL`aUnp&b`r7LY%P?&=A?fA%aF4<5Pm;>|M0)tu>WU!8;fQX|g#ggF=18Rk; z^TkJcDn=<`YiXi`(GeA=wAdzoh_1C&<1i$8#ytq@KI4;}2KU|?E2wvO>p;Cp@#deN zB=UV9^)+kr?EcBon4;CaKSJ54AdM5&adrL{@#a!jGDIs1AT!-BoSZ94LsceLI)nx- zZ%{l{rYYPftEWuQ#St)JxdN@NQ3m!CY1$IS$O@*E5(d#BUCg=5z^vg3Xb*C0NF*ZU zToiGQWv2KGR#Boir{3g-x*xp0@Z5&Rrd$q#Zg?EOu*meFjea!&Jn! zWOWfkxmSW=iJ;0wNpZ8r46w_8X7rC;M!m8awl2IW3J^aDO&V1OPhlA@PgMj4(SF1->Oe)Va_#N08Yr#S$HbcUIxLshxFkX<547K{!U$qE;C~ zc8HS_eG3}iu?&n21>A#kpr1Kdem$hS!EU4wYC=7%*^|@v!aa{pA;!-IKVABi!N!4A_%Z{aH|a`#!d~JAJOD0r}>jfVj~40UTC6? z*s&8xh7+~(_UJ}BHoo@j0(J8-ajdWORu+Y;C!P|Z+P{3H1`*ogIW9olsbS~r+R5}G zhdA+)aR|+z4;84!aB_qt-t;a{6uDz!!(X`UO03i)BsL_gSXmPH7B^uTNtM%^*FXtk z>`gV;+pXeQD+fVA-I*q*7?Z%ig2Fm)q-lU8!#(4$UI^_}^I*fM+k*7_tS>ek7cMsG z(AKmpux*)ESIlYwNjubSR7y69?IsNb$x2u(Nu`yjh1WD*2k~glqLJQ=CF3+z4;5q# z!ibBkH3L!ygG#3nN5+^Y!K>2HT1;B)i`cu$4BX+il*Igk)(b6(2D-xB4dfK$i6yx4 zJMZ^)t}?dt!@@-kx{61xfVW|3mT>VHfG!VKEcn*pkIK#U zlQS7p<7)zU{^S^U>4kN6*xF38^<@**2?uf*?(!k1_RU~pRN44^(dG9hswKjt=+XK! zHphW4@H;XUn)CHh&~!vK-)ChG?xyWh}THTmX==x^~AlNV`Da@R>cm8^(8)-8k}Q#U<U}~C^U3zN6V*bgI z7Umf6?4-hCir<=j*CNP|gAc5D8mz*%;J>jT`7MhnFKS6g4w+&~>J~QT?Y($_S2vWHfo+ zqiE{5RnVfPvA{AXnEW2fg9fvr7IuXZumwV4c{&jH?iWA7gbJVYBEBBO)}3E>q@vuZ zyB_}N9lWQO>C3B}eWsql7}U?zv~J5*J#%ZAb*UQ^-`Yt;_Ay2=WPS>q{}$@q5|sKg zQ9p7`*k4Ze#S}9;`iG4rcKbtr&#*4=!Hi3$cWC$&K7;$GVS&>mdKT+UT^k{31nsR5 zgLryk!FGX192G&oBRV$vNn*{*%J@Oqr9f0U1dRhcD-w>fWZ2Ar`l&iw>AvAj?+U+& z0!kqw-8ALtec?++uqk!->jSC?A+|(v;!y>B3i%5ULE$qemm7{}7L!1@y%u(=X4bfc z>fqTT+6`B_Zc<+ryuzNg<|JK_0stpHT0Dh3;NciTylH;{iJQxAY*)ji?_hAJCFNP% z3+|!jXwZL1at~<{UtD*0vJe`o0yfsjGOxk{`-DK;IIrS`N-Y}tX3h&V{nz6xkM|hX z`=~O;-3I&E1=0VQ{+3=v3Qd;%sLsC}jg=1N%?kLLnySgFYw)U3wJ6$A(78atrP88szJWpdaq z3Vl<1l77t_zk9=~|@>c)b(>6#jv&4g)#An^ZsZY*%JZ_lq#ip~Fn zg#h;f);qbjwW){))wbd4-W!xkZ?6;2kz3y=*;2ED-5qOzc+9*d!Z zFni}`xgZ($RCwgiV}T)Hu*;4-mWr%_qsPF{@VS zHNLO|iPoq`B?IIsh2ii62qs9w_HtiRF<#ZR!>jh0-oPRWg)W83V0XXQp711jKbe-b z_N&=LZj&w4Z{8gNMQ8nP^krvpWWOI7UhW6fcp(3#|7BKMgsZqWHp!XXQY6zA+`2{9 zJv239fF%WRMY-W@uE z=wayy=a^|a!L1!#0r&LuUf;J;LGaOoEdeoPAW;cX3_<@`g5u11r37guN2XPIQM#F~ zZ5c*&4SQ8p3q_2%wnQg)?UH&^isn*glhHJCdI+$ji3uUW_ZuRC5$Y=FBWKfogT083 z60?mIy$J?}>FhBW1;N@~Lp&0yj`pJE2NuG0cvm0Vlo&{DRiLd(1D0Bi1vzc17UnsD zB2$DU40DXo5sy?!$Ad~!$g)w0`BkIxH_13TqGFfH8a$bF7l|LGIyozSV{*r z|Ed7SUF^Mh@0);G?d7K9rn#=+>PA;)*U;_mq+eWyd5NvN_eB8*9ualQ6pdw?jqJ_+ z+|iEmsp9MMR4)lq+JvbQb9Nferu97KyA!*p3QfRjcFKrfxsw5Qu#u&_bP?innMh#+ zFpg>Hh?7)lLz;-LK$FagOV*=|NWK8>IVuIT0_o0EIM`#y9NF?JU9}DN3F_kd&N8Ip zXF6hx&E%7TF1rk`LK64sE~WX56gxK5HmTLd@}cJuFhe%E8F7iq6?TONLUFoqkDmTQ zhO>K%{B;&RHFYaHbA6?{s1ul5jJZ^!(<0c73x}8|>!1N)MsaXc-eWi{am89TmC7xn zs!(u9Ccx!&A~!>&W#ME)C#;t!?+)fNmKa@7et@EqwXBsa*7LN{WW~9T)=3K>j<;d; zlXdL9n6`Ov5}}fY>5@*%%F{waaHMtac55Ok5IWy4r=z+B%GGx8NsAIsEV zsUKxFXy_v>H8|K3{;MUe(YAk!gScgAuqCaVo}uLkY-4}AC2P~|ob+(8rEL|HP#@V) z!Zb~in`~GAqyEwU_=V7S>4TBtmKt_dD43LkI)IZp;+ZOB=X`A=Uz&C=GL*9C<0jA*+Qg|JGSph_El zUj~~Flh)KNR7;72yYVp-5MBMYU}9D-N!iF|oGEih^%I^69Z2#_dMZY@4=cdOE zxrULx1=gr-;wJk%ZAYJ_TNSw#nSZH=Xm0Ke=&$KdshpHYGJS@v;of^+I|{h038`zO zymHm^#;C2Q&NpceG~6^kU8C+JhnUoVn*>`z3nXGeyuf;Ie~IJVB`6!r|2i@Lv&>IGnfrv>IFe~gs`LX;T)Lv&4N)N1`GN0UPXINzmjGoiop%i~$)z5wa3^NW+k52Yl4^7aj z@1eF2D=VuG5PYpNku(|aTw2uKA92#DDKczyqW1F)Jf9x8tWu#B2e6p3QrS8$>DQjI&gY)SkCRR3nf8<02frA8#5~BaoKSA6yL_&ns7bI@aN4BA z#;Yu%T687B170M|1?lT~0tK0FQiREVoWs>7RoaAW#Up5<5;op+1#4bKqCIFgk1e+6 zr*`Ei8k?p=->4pRJF;b5vF+JJ0KC zI`$Pidm~D8_lBMz<_1G5wrV{T8e0IE#T8fG>S(L{GBd=Gmdg$;qz&NXb%Lcv{xW~d zb_O1Ho^^4xDri=)RfFV%+!NjUn@+y(V%~D7b5W}rY!y#=pm!Mwf#njain5A&uc)2M z4-nxhBOmzju&XHOtbHq)bqThnAKvDjXc8w-vs7cp%-hvPmhKXV=boThu}dcM6b~Ne zWbtF0reroDGZPTgIls0oB_6i46P{B1)yBigc-%rC(`+@4!E%}-!P>AHvABMS;Vy5` zu~x192;m=8>|d74yu(^{E%7c`iNQT4;&%jHmf>WRj@W#zDNlu{LrjHD3Z{2XI!TbB zzKzP}-kUq_ru@M4kB|#}nN6vuxO&JJH5iyg6$M()hq0u5SV&fXG)iYIQagC+u3SpF z1$5!3%C_r**|H{A;&pQWq+cCpI=wjCT%H?P&`Um0mSCN+a4KT7Ta`b3&RYq!1+^JL z^k1hY{|5S%XXj06SG{f-;idpFK$DUbN+0X=JX^wI4A2YrCDg*|Jes`mme{MgI*6f|PNAw5hDM^TOQ|PnrgC@} zJUI4)Ar%O?x`I(-q);B$w7<{=I#9lREV0Zd>@Mp_VVYgL*+XRbgURZoAGN^GzPX#S zM7_2;hWD(ZBY%BS;?O5SNJR`LA~h-MTmrBZ?OD*Fs16SvLJ&<>v2wkcsg$Qgw9^jF zM+QR~?Z9t^fMZDCF{LX{5iRxD^8+CVgpu2e#7!-8%%Z8o(5j$DDzR9}iUFIRVCBgn z9h5sEjYVoaMWBb`Cs*2|jM4lRozrWBX+954U;?DM3XukvDTS3uOjg=^e9~IgH*YWx z`lq|;LU9sZG-OID$mz-Id&~CK>e+XbJFo0tZ|PewMRhWl_j?FnvT(G?zjn}nW!_@? zzZ&L1YtKl*TRSTjq05m&ZX^GSZlhLqIsf>>SfKiJvxm9eR^mZuFlSZ<&~gd2W^q># z(xLdCQ_;!WWTC`ZzU{s2iIvj(z{LpKJ)9@)>In7SMoWGEI2|*~6{xIMjyhjeRyEzR z%x1n5Po}tJ!Wn*?N4Dmgke7y07o6O-$4o0jqmi^;phdDbOopVW+t<~nHGjNmOWO&r zypxqA(rVdRpu^3Gv{J+$E##9y*JyN|0~8%E35+vav28HBMDZ z?X5O$+Yp7K*A!GP?t1t9qu3v+0F#x`@!@KByM4oiI9MI;V(}w5V-x_6+PP|k!So)` zaoNN*wt0ql;rXne1d!=MEps?et7+rY)TAjhsTj8*J-^4B`p6~KxFl;GcNE7vdB{6Y zn84g_SG;p$Ty0E#Uf1$y(~hJz9yjfoY&&;3Hj?VRyooptGrmgCny04|w*fmH@0jM> zAvg_~SJdpcK5U-?*Wtj%RlfQPP*G86i$@P93mEtwkj8QQ})|6$i;snR!Nhn_=s}VOHyy%m1A` zg`bRmi_M$FKIb(wXboKX`r#bEQxhl`9et7@k_*%JD4ybMbBD&{VG74bZ0YE~of&Y9 zU6P8`sMpBA5n6aIThhBCGd%DHC3+lGAq{VpQ~=!*`fUVz&K(;j(6eZWjb6KPi&4GZ zb$-H-K8ss7E=dx?H1jd28omCsMJr{>O);{4iIW+tch{Zm9O- zh28gH!2T$-edpFe-UMj?uQ|kZiM3VhIx z1q1n(x`~CL<2z|~-q-3TT+zpuVSn#1nP=kCH@Qu3g{dJ_gr+2h#PGkeq2;cw@=d5`6 zZjvZZjl*%@8mY|j$Wan^OdYwaeo->sDAMs^2~$#1Bj1(bO48uHRlug+F2N@kSv3OvE^Lh8s@Z(h+9B z+eMD>4bS$5Y=`rLV7ANf5!UoEN1=@tBF^p~4Gj&IZwVd~`M}3kBIwAfjp=wnPfe(q zZ@B-+cu`XDp^o9*PaZwUSx|7eU3iIN`P8eR+HaHv>|~jKa61hIAW+uj7&?Q{F4gUU zq)Zsnik^ZTn|BzKl%(*CT|&JbNQB%0qhd21VeIw*ZA+lKN9RvM?$o)Xb7(Jgic-H{ zzBg?Ceop0Wnan(BJAoMy&mA~%Mhx35qeHry@fOM%#7aV2F8;W{iwQqCa##CJHlqva z^O58XpA?(xG$@dbr7X%((s^(6X5=e}u$FdBIRmad@<8sR84eslA0KuhL!#ic=;?2+ z-3MUAYA@6m7b9bBINs$@g#pz{!_kS=pUewfF$5;?9@zOx`81E9jqdOzy}uM~Mj5ab zcoy~5Iqb;s+B=wD$i|iM?#4b^Z}UQ1`eAy^)6jCrGfw7h^utbW5d;WbEyRf+e|rM_ zR34_NsXFMi=bp<>#c5uIQwqFcsZd`qd#dqzgp11}L{AZGys&FMAbyCC!ooT-jt~8? zjH$iB)Az@^!IzmVXJzDy=#h1(DTtO)JR;U1#;}YPVieJDDGB{fj96+}@xZ1!Km7Y- z;h|tt04KM?;#;-~j1Fgv;hU|Azb8aJbC~0UgH`O<+jLjL;o&;zDt}CI#WCTKtMLtR z6EtT3(U|I^$1Gf-l@a)aE;)i$ zz>u8xgaeA&>}?@*BzRrW;JfGuf?$8F>h7PQnOqvtja$|c5r6%=XXlUYc&*7tZjW$9 z)+oVU1s{rA^N-}2-aWz>tdtL|e>e8$7-QK;{$}e20YE^c{x6JuWfwyiS7%WRLp$^T zJZD#3(*aK%gTI!&aCshQOwDAZMapQTuaOIfKAhegojZYUY+{rJM>8fH*#bMNkMI}Bc1`F{928<0!$p?MX{+EOFC|)vqgPMvOjVa|BCI3L z;ym=|qK021a|voWGuRD^%b~}I`&9|J$4*eptWEYFHU_iV z%8u}>y2V)QAgbcfnP=eG;_}v1t=%=~0-4Zul`J2hkmSv*{ooIGNXi3@r?7kq0(&l> zlgZaM`plgk%(EeDV9~j18;22drK z#_LKF*78b@FxsUs>VI()Ygx= z-(7=BJqPx1iCVyNIjyyu<~>8`KjA&qr5G&JRNh3jVp7(!)FQ|8oeZ_8fp<;V%O%ZK zS-A3XV{D=_E6a3U5Br_*;alyH#|>g0>9}=cLR2; z79PEhek48b@;3B)IU}U3NO*%T%Q-=};<%nfq`hf1L#B=d)+@oh<84wSW{cD}gsI33 zp)RKU&80sf0-~yJd9De_)@;m!+NK=3i-WIo8D=Y*MZw}S7p;MPd_jOOsU!{(RtSw)mPse4?uRdCnG)kh)}-W+zT zh(kAQIrY$`jNv%fgt+@0Gm%_43Lb4$TspGNpl+zqbg`Ifzr56{ssh&|x)Hs2MWaKx z&vKYa1tJ68I&_Ps8&Rg9`2}yuyLP2DT+lx0avG-yn{n01rnBg*yEG+E{p!rA?f_Dk znz5~67gx^ytB-H>-pt6IGmL?{qeIixR)TJ|$ZoZ$ZnY?GwL3g+`q0A+D#2UrLYFy6 z!_(s|Af5NJSG)Z#R(~*K zcRFCW^}-Hb%l55mYC;)2<3@aF_g}mFul`sA4oB+t3MLCe7(HY7EDc}7;C4Q>EnRV> z|G2jBNh}?C-Fs&xxn#63^($_9;ss0W$v!sGYh`TZ<`HCZz9)i|P`Io+KpmV`-i3DB^3HcO2#O6h+5&~F3M(U} zy3JA0q!v9gNtUziq#Yu98;1?VI7Ao>c!2e++e@xw~Os`|Qg$UxfbpN)Nv5 zy0_n&Y&Xsad|La{`JY9e^YUa>6vosKJg~&-#EEro3B_?v=zpWUCjAu{viViY2# zM;sgbMyRE&X$P-#$n|v4)>;!}L_`E^#2r+wPY-O^I!9A*h@?2WXBccm*)A@MIK+;^ z!zQo0IcHgjF6hpVx zbZjzAD-$WWa#9#p^b$24+vELl43%FB3%n~$&u%VH%xuSUv55u=I93Y??Ddr+*RD7y ztQF)CXyU>c72(p7Cx>Y+7941VCCqGcAwiMZ`34j*##9%?`CCP2mfT8-16pE)v!wZT zHZEl;>z9%UG3pLrW@wI)cBjiMP}K~fUf)@pAW&)>b^g$zluI}nCTiES*Bg;Up5?)<{4&=W?E9210U zZ*>y~l&mEvr4YbX>+dWPZ=Sk9M*C<%zILRuRMk)s@{9JN3Y;rsfG;Dm=evsk;exZj z-Lru_+0_X-11#E>02WjNh1bklIm+sjqD|1u-Esmb*b>PX!-`{PzfpwDsMo7A z*{#$K>w4^8nHTL#d%xelPT?t625>Yb=8)=G{RSDhb9Rh>%Ro<|SRPE6yB-hlQ_1uady}yCLh^xon4nvb0{NExIV9RbfaDFk5mpm4(rU z*}^6h!*7eL)#l8Nf8Wx}WQX;tPswL7!XecnkroL*2+wr>Xy1C3zp;!|kJT3@T#n~e z7&Z~GF|hEyXRc|XFCMYbeyJyjd@0PO{p(GuZYieJAlDex){Ja$&(On9l=drUyy3$# z1jt<1*VkI>niE1+1#_#FAV?chVCECO66L znO=@5TrE{lE}R#ThQw5AnZI)};F_s+Np(ceUNBcAcQYtO>O|Lxn4p+lllb*LArFe% z$)Bcl$YW58&~0J*UO?Y!r6Qc{`EjDY4DYwm<>Lexrfq?cG7&L}T^_MPndA1%L6DP3 zg2uh(;Z*cyCN6(hyJ8{)cn4-A1voI1QI<6oC97v`9v@vAMa6>84DlR=y=9s}zWBky z;Q1OV)E{jFA2SnNf(8?g4Sm>37PEFToC$;PgUI0&{B9H41n7tutV7LL)K14piD_p| zfblnXm9}Rp%F*~+|Ap3yYx9DJU=yEe*K6p}hZ=T= z&LyQcmpDzZjndkaZRX)mTZH5abd8z=f`Hgr5l*z5xlKm;n1hlXY_hA>>ex&(U!HG} z;n3nd{d5)7%9{iKz~+Yt_YE$_W>6+IFl<)7xyccKVN7p-}PjZx3#do~O~sq@$om;lM%i zQGcVv@h9yPCujz128}HE1ZB)thXS?|^3hTo{&5}!fT%C%la+#|5PP=w6*GH!(^lk@ zsO~nh(1>bh8HiPftEhHjg#7~Q#iA`U4);KyRsVQwUmDq1k}5s6@mo?h#IW&^vnmT_ z5o`QoyW_7$wyY{6)(#+SAFj&!Ta&L7$^@F$d{neUdn7EX>|CK_W5^`c5tfTl{DAV4 z-#?O9lMpI3%u3XXoyw*=cge9@LtN&KWWcDiT_Wm=kdT-rOR{dT%3mN_*Ly#`P;thH4Iw0t`iz zXDhFd%caA5#Ahgl|0-jtA;}bPc`h4p!cw^n<6>Yu8y|{GPX8`IzRCJjDtc~4`i`i5g7u^!55J;2D*U^Y3asl!muJXA^z{ ziMfWS3N)nZ6TCWMCT@T+c*$Z@NShn}NXS;Qa%VXg2T{eKxX_6_j{-dVFcaktJ_NmE zJ#|asGlUa~p1wKP)U@&{S|Q1nLqX96YjzZUd|KDpW9XC$NkR3ZXH{CRWV*z3$ltti zv-yK{DE@L~8%uWh#FF(?llIagv=yy#%5m&*hyt>1r|6U>FSZ;zls&eHR7{Mr^SU2T z6ce`!I9Dtd+81-dJiQ1uTBBCuH}-;`ft)@swE;`$7vD3(sXCaA>{d+X%=O`Fij0=! zE{)pQJL!_pY!xe2NpThunzu^Y`PnzKwE2%o(Ro?i-;TSUXV>V~mo)yL(#`@njwMUi zvcO_yW@ct)u$U#wVp+@#w#CfM%*-r{nVFfvVushgcXqt%H+$#CPAOVZ6;YXgW_K$q z_2tR))5ySeCe#cQ)C78{5G&p1j^C?8K74halOmjLe>rEw?{0-OQ{#&0SF7OLE08H9 z(7I3Ts?^;A#Hpr-#whq|YDPxn1P3q4Z7I#XvIyif7{I;lW1EfdzVQ&Qp`K6QjR*e7 z$n!!iPJ7)yK=09?w2J*fdb#Rre4*pN>n%q=$K{Yw@G2^w_KIG}A1a;tikB*3_v3pS ziyeB{NCEpB^&)(I!Wzt{T$3aW-f&~M4XbRs(d#CYbgHH=K@>C|oC(=eA0{a%+l5fv ztKfURw|J@%-!z&1lV4vFWi!147|bgYlL`6IpAL%_lo*5E4?Mqm<%M!ZrovC{3pc9i zbH=QBxN&B|M_KJ-v3Gyo`-}-?xkMr4BggbpVk%R69S(JV81}H zozw6HD5*+z2qt*nr#4cjKt2yv>Hy*M5`$7pVVUiCg6yRD)LIEc2%r-sEL!AAtZnHG ziiA8FMSZp%r$H+t^9Z}YK)V}L%sMGmB-)aOONL19TC{tP*f>^v5G&$o8ggi0HPC2I z;AsBRZM#XMxtGt%Yl`2?p0|2Nu%PY7dUb|$L>us8QUWwH`NLt8&zIW;{^)ip=NrG! zbJev@>Bf)vHiLtM3}*~#K|beBVU`w-;T|+FKa?XzA$8{snv-1E))4J8#cyXW*xwAc zSY2QukcY^9spDtkV`J~7rgW|ndV5$!LlUk;L-^R-?|YCvN-frrjx5ePK+ zb}f>ur#GC>KboePNP>QvX{;SZOR&W1^#|iRm`AtZ@NS4+KJA2Bv{>+|F=DO-7hK~R zzU}5s9Cz2V>*G!2TeEw@nFf<^-QZ$cy{TolBKTk}LT)95!EQj!=>gLKd5X3~fP1<% z<l1^yUNJza=a`W_}@=BHEBpOw@Gu@TE-hF3(OYq4ofzkSI#bw7@6V5nfJ^yvj%tl}BIP!EvD>|#jrz@`zG*w zw1zaV-JnDC`@DoS&6PwiIhKmO-dYcyd?=*b?4DYAnSu!>|C^V9%1KYAH_?&TI?$?k zCv^NYR1cImQ>fQ`pFK{n>NDwY zK$UD?4$9Ic(gPbjL70x-ABH{Jl)_#&UKX%)?dZ#A-SUjud$eYPDw7Wydu2`|T48Df z_cV6`Uqm6?P`^Zat4a#8KIz#A20bw-hK5;5rWMj@CXp8PMJfBtpEoDu&fi~dM#vtW zBRl}VwHU)B#H^MlUX1y;+)*rG5Y2e5Q^@5~jOmD`!Q=FR_cN%GsRf*GD%>*-&JlVz zpu|lN;eB^}>5V2>`P9|*k|$dc>c;mNS94C`X3^}^sE498eX1pWBh~* zA~g|tb1G_$qT8q5A$3kFb+8gcmBg#xVoRdynsPb-v7;)eKtN)D@8291dm}qRLqj7& zW$Qn7_x;NR5l{BmfCLd8{W_BMHMTh9vijt;AC8cCrBIg3wnf6RAEJ87Qhf*5NWhlr zYNObrocx@2>ruLL1hgn%59JJ}obH3h91;mnzk-~?82R_ZGjuZ;Vr;N$uDywLH$6q> z%{E_9jJTYwxjT+E?R%YZ?(4kWb~}5)5rqA4%7#5flwcBqK<={>qb&N!be*e6N8OZa zmP{(D24yBWTbA2Qv;?M9mV4#O%5R-oh%tK^nn)^Atwe6JH|68|5i>_o7evZR;{z2n zDsj@Tj-+HzFPEW1b_hZ`H!p9D-r>uKDPxUMQ}kMGremjkRB1^^!M;6+W+Mwhc)j~@ zO_SMFg+V#hI(?lo8LIrDkZ|*6;|~aAImZu;g4X&WT^Tx?BWzt+#`exm{q>UpxQHjQ zRnRZK24z$D4x^WF^qd76HQ@7FLJf)w5Bzox^FqwVq-ae0?ZXRlQ?x}P2@ZmiSh|MQ z;OAzyVyY<@9S+fhQ4G$!#zJKlMkjJobB%3^WQ#@Sin&|}=E;@@BrQW-|2i6{YEE;? zCTV-A#hW@4*}C|!XUx3pSmlsmZe*Py5zM}*) zUZ$h_0M%5MrRvheFlf8AG;)hkRF%A``{C=4phl}xA49i%m7HC4=inETmIUf~)v>Ep zmr7)KSg-?1HP}z;9goSlG~7GObywJrA4~Ud*cYYND734T`~+kuCzZ|T%CK5H+hqhM zHy%zWzh?LF8P<81tItBwUk9M!fozxc?}}Wd3i#A!xwTZ=A-?*9@oBlAx4l;V5fTqqjQj5E zhl>V5YhpX(l(lNVj2%^NTY`)5Q|~T=MZ{htyZRBdohHDO(U2a-13_-3XYQV=z5$-x zEA(5&R=Rm$zpH)*b5n3c$b$;cJv7W4CS?>!1qu)l8pnGRX{y zI4#MHB41r(N&MxEq7dLhC|py$@WcH~SNW1}0UO~=mk=!v6a7K$vO{=gigP24BuXn?E1x0K*>s>! zS%&7&dh@-4h>43UY&;-TMf!Lxie@-Yu4{64V!hS2)qyA97hpd~n;(#SV&Odwid|1( z-B4!ui+dJFHP^oPSSr|jmth4;$66I`OVYctT^WX5>VTZK4KiOwL->f-_)6nwYk21k|$c zx{IE;8uINV9m+7_vZe)V;Ox+G!O!f(%=OU3Ic>3R=tRfBslqySmAUgo=);K@!oV4H z=Lrry$ihpYT6^co8kFIk1wjiWe@g~f_0tyDNf)b=j-Q$SowV^Cweg*~@m)$-&66TS ziw$ziI(T&p&dAsW)7RAu*WC_=mX7z;+izz$=GVM;R!y&TOJl1&7G#^s(dGw8sOPZP zJ#FTs25M&xU6SbHx+BPuX23C!X6Cpv87UVYRK zI@tU%egDFn`i44X zAW0zxaW^2^wu5)EYwXwgw6PUmVk@rJ_{t1TcL$t`e@wRSv1e)n#(UG5F{meJDQFR&VkqJ)gcz|M2l;l@|nt zmUEa~l4cOb>Bv8MVRk>%Ei@2w7Rfs(I}=HzC%47KOQxAMAPBynk!3u!d`wO6Kz6RO z%u$n(Rw(Wt-StTmODX=(g@R@99mez!o#CYo5~%bWQBR7#OoG!G|W@%k{&0&&hn*pmeu*|ohrcc2oNDn z%FYro_J(~B_Q**_0j-P|OqwBUFo!hPjtIzx>F3;vuE&FhgY$3pqfaZ!^sBfDvo(Pe zeOS?e8r!p%rT`tu)#I+&r{G8!k0+%B7E-_;GvVMZ6Br0I<9>>9dizX1DN>f6hDd95 zoL?0xbP5cHo*lNCE9oe7%oG-AW<7gqd!$iswt&`s*(aaR+2tg}-Zy}=uZP>vE9xP7 z<}SWIPu+-t3xkR{ok-*;o0_7a%#FL27IB^6IBLqX}F*;q>x7p4rqmTQla8_mxN-7J8ACNY$cE(PY_W&O#T;qT>W-Gh ztR$+&Ml5T;zuN$=67kA>NaV~HpIJaN;YymxxoL4`Z_zfK)8YVO7j32yI|?(TQC-)@ zD6zzBP3__OM6>L4mDZ>#2poGOwe4Ylkb5;0{{W|S*6eU3!w7m=AXD;ff8cr{f@Itt zWFc?EZAAbbpB3x$1F=knAqVSS_Ye9R{b@K;qZ z>+Vq)X<`)idNyj$+TCmkND2~#_K%(1=VObdN(#*gb4>mB=XA|Zs4kS5$Qd|NY6imL zL$&TOCyM?F45BSs?tS5tu*s%-0&|+)X(`^GD7#pwq~Zm5M@@ zq#Wy4(tS_Rc8ulKA@P1bN%Pbpd7|R-Y}PL};(ZEx-pCf~*a*d`@ob*P_mu+?>;9+Z5rQGIsM8_Bj^BnIoYB!@jW~DrZD?&M| zb+!W;Mou>B%Wqtn1q;dxoh(?~Hjb5b;ffxZJQQghJrnZG?n7|9sDR#b5!_IYnVNx2Rt^po#>#{${+6svlLdWw+p3qK zY{!oX0N7~zEz>+gw_l$BPKvw*eflP4v!^doTtSYEB4w*z9|WEXeq%+zv*zf?i1LTD zR&>0^;&Ax*B0gQIGK4*qf7qB&?0eNdfh>01A}uo5G7Vv?3qf1!-1fM$C)iUi4IU;3 zcDj}06{OhBcmst2JZOTveBQB}BObJowc14eM|Ge=lsL0-S*ZqpDWmxz4^gHj=_*R? zdG~jm;PgP#sj53gJV6RkR*gj@$E>(G$3%<|Nn`kIF+qX#g8Q}_+eK2)CPJ0q1Ee>S zmJ$sP!CP?M43@J_?Y%pAgjVklGou>krx`Ix7g1AKs8Kl`@Enu#KiouMIm3~a;B@3I zMhfcXh#xz=P8OAgt0ZjRc|E_Qzdt8>o4FSE_jfos>Wk&f8l)O{c&rr+n<%Oa*$f}y zlB9DG`IwD0nP|*~prJlI*&DwYXz!O7K#q!T3 zBQ7>8cHXVcb4uyR+Mabw!_?WM*gNQs((QZPqklw(s`i7gU?@#?rzEsR+h#$@dI!@W zltuMp)dl`$9eU#AsWSSDbAcD^TQ$uR;9>K$-17uK(TJpScJFfyuUmG|FmP+Jm`=Tf z^-4JL@r@Ac&Y*_-l_9L6kM-=HxRBJfVH+;_fnqdOhW0J)1bkVVwma>b2DyfOVo1;< zw6I$Bv05#iu<1)G1<}0-ov0|AXh`loiGl}IhFDc*W28m*y6SkQn+tzDQsH+(nsw^< z{Gd+(;}c4@@mn>GAxkZXpN2jI4L;akKVB^mSJf&GCnO+0eitkqF?O|mKWyjm?oQsF zzF(I44zZ7Za~NscHChSGR5VqV*E`$7IKhaaYT-k%5S6@MtQfnfdbf=PkcbazT~62Xu0OYT8+Kp6Jyli2p>PjHpw?HRwAJ! ze_N9C+z@}c{t)}Zb?$YIR7*`+W6OJl!%>b$JSE%e4El+1AwX0le)i!|jq+MckwnHx zB=NN5UQ-t6!g8c~DJ}iowIdH5Yz?20JtEJc?nTIAOW@uakJA?+(16+}Wbf0M^u**E z#?}3xL+rJmXS@O|;86Y7ALL{@Eo9)`_1%WBl^C$6w?(c*HWS--gDCsAJGO%km)83_b8Lc$6SqOy5A$P8RF}8Ae3~F3tEtg@6`;0$Ym3Wc4`d`VBa+} zDv&qMvTF9&2ao17rp)+)#*cY-cj+9lZ{*m9*C zGYAN~C$Do*q>-B1tO}l_3Wl}%;dEgaY)Y?7!EN@LD#!ABr}&5LKAzhIEmIq9ZZbLV z7;KuBIzzy3(M}&o-&iO0)q9p}%_6H#C}@9xD(``6R+&{C(-y_H<)yhrvNC)leC9_s ze&B4%*beN-y;W1ZuzJ?~JaW$c_~!o{Vo#g(K=ho{`Wg63=X&9XtsnQ`b#El#5A3S1 zzeO~#h($4U15lqI0QE`z{dv5ik)^ehk)fEKwdG&pzS*C+Z?4;kEquF2@+9{g==6bL z&cgftpwPf)DHywG&3eKt+S0tR)}UOKI%<%-5BRlUno?L^W@NP8atz%L`QJ>_(2T!g ze*Til{F0RfcdnK7UV2|$ zx67VuZM(=y>by963z4x>3P#tu(%z{R>H*s--2h)%2Si}|g8Y0X8qZ8YO?pbqo7Ci> zywkB*i-8L|i3J>y24C6(LYQ?$bDhD@yC))|qb6~ezNOTy2aTG_VW4_MGb8=5Zpb=F zuh&o}^@won$t{2^4PksI5c&na9}mc7>X5z(F0=f&OfBB2;nMp=@oW?02{#6T87_hE zB)#B6kC^MNsIEHn7_6B*isYuazpKKj$~fa;VQcF|MVH$4q3d*^zq+`cWPg^19d(au z3Z|ef)QE~6-M&g`ct0)_5k3QT?<|rbkQ=g{hIv;R!VmjoCpKHrIJCd4A`J>00g8x* z(3?VU+@x%j!@*tx;i89 z@SDFv^EiuQ2=4YBH5Qo;W{gR&$5F=zzby@1MT8U=J@Mv@0Y~QZpl?iFux$K<6Alh>N=QAq zPmX!!__V@YfI+Q!TdN%p9o(509BE;xVc#TTPKMzs z%eZ$GY+_AuLYG04-_nZ**leOX9G~oRuU58QXCyjzjJ|v25?{$0qqbxBLQk$KGnc&E zf-z`YLUtigfmY+xqHeG9*Qr-i&N4^MaMXJmumGH7!8{ppBGGeDnzs^qP=6v;Si@( zWruCw{3~MRWZKJTL!CKCzcA3#G_VUEy?{H`Zt-3ix?9_ac!7H^4-fZ?n7~himRoMD z9d}FX273(=?jB85*Tg(r-cD!lQiv*ibi~iO*xHPt_=n0Gp#--^m%);=+g_lLKT3F+UzoLP3^si9|in!=^ur~SAhdi*Z+`##N33!*@*1}7b z90f+WiEL&-$C^>bwpSPi$(kX5rD5ik^)s8QWnE(q8am)&uVDsQh!&7db-@f$oR;wC z1w%E#L2Zgdc=k`^=k*8jBm4vTp`40@I|&xN;}LDSAUf?VsYSP*u)N1!4UaJGkhBjF z9m%J3gSvy*Z(N67{{TRKfqx>usBKsNsz^VtUa^e&$#wMz-MBAPD@$px&oMX8p2r8| z+E{RpL2lRWjz=+cumO*TypHQ!=adQlARfhdjTPS<6PX#k-vw{sHHT>68_qErdqRj} z^@(D2qBdjGPg0am>OCj*ovU$ac0Y>6-N5!0x>XrhWo2b)&iP(7>Sn}aeCb6z7v~75 zP#KpLkWsAO3%x&$gK$MD71)INA?h-TU$tH1e<)E)_Wt<&BI%qbPzpuw8^f3$d0OeB z*cV6a7mCXyvi{ZVrfmP{(=&t+Xlw61DB=z$&Q|4Zo64hec7^)ch{d`rZlUmm(>fie zs~?%-F1zA{QQ8J&EoL9?4B7XL3*4%ilPj-O7FB8{M`cZ%-q(~cw9JOpl(^Jfu~xPm z3|h^mr0wQ`w-mVUnk25)0J520{Y+lkax!>!K?X=t>NIPAXzU!f_!7PN61>>fXzL^g zD9T>xz8JIG(7LFh<5u|uTj3G5*ak>uDk%Gc0~>^Yt)OB+th4Jv3giZUE&gsev(!i$X#)zZ@~!BgPWk$D zCPkg2+d3?-;RE;=|9#t~XPv%QPZN>*7vM*3t^)(#L*x~?x9?z&e!x8%5qa zjUMTBGT)Lgh*}rno-x*0t^K7f?%ePB?sNpm@4R${n$3if?)qX5ng=Hx&S1Cp$Z8z= zo_9MouhAJjWBx>b*CGg4yprKlO0byi{>lb?f;(WlNHZ?!WMx1Yyrqm=s%n){44B-1S|>Di4m|6T=gA? z)+u?5Iw%mg!0AMH1!Zn(Nr&bX>U4-?0!0(5EeqXms%0WyKr1?t1k^qkd}1no%16;{ zeIlh^zWr69ea!u-Haahk*g$Q)z_Y(S>0z|h^~(4*NDa>gLx5XH$NQh*kJw$tG=*}> zV)9}Avo`8ArHN*R+nO@WCz))$89wpx2lM)Sv1p623p;f{s*r@4*Yvm6jX7+kr`M6zr}pb3HXTKVc@@$M;LH48l4c0MOs`acFZ` zCFbNm(O-!>0R6E5&>uMi%jh5IPnT2Hkm8s$i#Hd*;fqwYp^pvRI5-HnKLXI-gF;vg zN@{4FNUI=vp=d1{Sh=~a2*BmWRH@KYc3}a&qTPD z-fYTPl{vy3N0@JTAw>l`6ru%DT7AaZ!k#T8_<92)B@+^625Bx75kLe(&hZod!Tv;l zzVvB%nMnZjXAeMs_bZD~W1IHU2N;Qx-A=~iDmHi-w9-?Q5TYK9UpGT*feDGTPtT;6 zJPmL~kgJ-V1L_*fQu>&gj84== za>%bo&E)KGc{%9OezDlx5QfR}Pw(BJ=4po3;+)6xzxA_?+gr}hgkK&6bGi+1a=4rB zEFZ1H;iSXuH?%MjYVb?AGx#2W3-z9{r?NhiIM?blTDE~Vr!J%=*nkIsfsOJe|w(rs(-LQMH@^y@~3O(24~!Uz865!(OXOv z1hF0kO)&+3=$be<%>GGE)Ea6Ae_MPql!He7U+fR%5B4W>Nhnn?$PG7dt%i(tcPCj& z8!)(VGe5KFzNPum{G*UaeseyTaM*>d4tuOLjsDntlsLP6gw^f&f$;~V&_hiY{n@&3 z?HK(G%;V4BK)S#Tf?Ncz6zsL(OD1v09GHs4k8aN_?V1KC?vF4V38#%16-`KTCY$rS z)K7;tc0rdO^cU+Ae)PpbA!SmiW9?&$uxF@Uk2p8k-Q{V04knD`_tm`NG0yMzB5@r# z?#BaD+s2aeosq~T4`XPH-mG02<|k(3p1;+>+gaFh#u$cbeyOy>k4N3#u!C&n}_ujWdv_mfozVhd$j`?+rHey$%A{ zd|wKK4fH;GIHG1gscYnF zR=Akyo&|g{r#ZU+J&z=s;G(xezSVcvOl_X^l2}{9IC7Z1KG1PsllEfTV@66G_#%|| zpW%1K;>lTtLuGB7%%K74GIP~x$VVVnUmaAUwx>VX4+A0&i4s+-Mjb{)NhN%oH^suO zEw(&viR;`al06^he6pADTFH zUn=rln7AjcuQ>$Q*54mQZ_Y3wpepefpv9U}sH77e=RBtTIbj~Ojk6a_$k>;Uw4iLR79W}_%Puq_OflxY$CDedO@t1Hm{`=d0K5PE4>y`|{d zks+OW9+NMPm5PKTMKo;OkkqiHq2Gk8mz0ty{(=6Yv=rB+?q2+z;%Hbf>se?uIhYni6+$0yg+)FGTPDYGsW@0WCIZl343;w;!#~iUxKzZ<(KE5CIc*7D z_m7u*ko2of*Vn_N2$-8g`!Z~$y3B)>4Rw9Mb;vbBo zgNCiN4LHN%10m!QyTq>ilE&2s$~lwo>>%5-2z^F~kod!7He+|>`{+cW7(|uHz_#p(}MU-C%5>ZMP$=m0zNTi4QkIt>hahWepwVf z52A!@qLge6MUQ9-K0mn}b$M-x`c3N+6M0?_1Zha+4G7f}bm{4yicXV*A`a;bjTOPu zv}<}JmajX{oNh0!Co$@pg}cMUke(Y1szx=f6h20r?O$68+fob)lH4J-6V8o-E<6T{ zylaVM3vh)M*lNl!N2qM*Z^!k?qSmNs?3m^T(;yUwA*Cd@nc)m=TS_X$nU!{?bB^cs8zcs>E2FZFncK3qTqZJ0$!C|Qg$ zi3)IV;06dxGde_Kp9+VZu$^{uEyA94Q&ulm!%Lf_9DFs;Va=tac$`&y){?vU0UYdg z>cZ~^v6P3h*oapLhocsOXiC1u?O%a#lCuRse~idzp-~)%ZWyH%e?Rt^B09I zBYm->y_=HwXdQ`dKA+D<4DR}SHY1(B$W(f+AS)@c<-7ARdUj*~JbMbIMWS0jJqz+&VZYjv6ZCR^6?Qznf>%Ng}TyX6U}<3U>15bAbJe))~Y?X5{t!d0r2lBK&jD;{2fj5&a9ZyG z6TLfP+({nHm1@&oS=Y3oN4)zLFD)pq55BZuN?zuX&q6O)k$4uWfk}Pt8(@oEG-1(F zoN}1S1v0(l_~mK0+$#5NV&f78*{E*x37VEMj#z4W0p|7eMEV{kxL*wkY&loxDziFm zO(e0)6^qAV=?+ABnwaQ=aHCbDdO1D@ovnMGg>K^r?!&@&7B(*5fQx$5>-Uj?Y zBnX($|7KhFPba#6?kFs*a3v~y%Mdv zJb0AL%tA79hopDnjZdn2H{uq70Ai$H{8E8PG%lV#a(Oqe-1niKOTDDtcjg3?$S8Oh zTq2Kd@N6FBA-a6}#*8t;_3T#PWhY~N|Jq|aDP#T^_TkCqEij8!x{)D12*)FJQ)_$E zJ&AcZuQ7XLig83dHiQy5(M3P_ma3bnHXcm*ivV_Mq$@rt@kkWPG(qW8>ZIbZ*b7ay z_8cX@l%QmQ3;T3Df6Yp^Ww1eZUTrLlfE-s{6MNQL5j|@T7L~;vD7P`ZMsoDIk~(Ze zbad3RDREn)o-H}8o)js~cxPg+v3Hz2G4nf~_vZPE$RZ$meoi3H3bxFCdp#be4PmR@x?2+gI z5D(#K!1$F5lodbmTPf(fWDSW>3l=)WwY+}fve?pKS50ncYh1RSPzh24y3stBJ)@k( z!t+q9k|v4_9aO`J*O=&cEE}$p&f43|bT`zutL=w}c%*3B9f&#h9+b8`-S6axAGNEi zimT>#-So&$EU_jV9`rsn9>p-@5s=YI@l&Mfbu~KH)FnPS+D%oz{m&Q`V*7G00Z>BV}kHO08;sGyva^x-{T)U;Ohx{~cV9|>0E>SIi~{n%n`HtT z4LA^hPJjM+{%Zf9#eSK&{caxm^X8vN?l*G4?|*jtzgda?mGDm=&p(f!!fSxjpOzkf zRpO_w=by(PO?~&@OhEps*iWC&U&YA(d$E7z9r9OI{q+6(Rh9m~tLnd8K>zo5|9@7P z^KUEs!y)glTKLl!^j8aa02Ti8bNMfq(Eq(PKYc=f6-ES%*}oP3=UDw$P59}~@~al{ zzo_NkkNAJ;{Q3(1?j!nNO1a-M06Kr|3G;^~>mSQVzg$Isum5+y!e8|#0G?idUH{*4 zFZ^BacUPNVdYcIUH@!cR*Y7&Nr)mDB~PgMVPAAjFE@k^~1@Cf=Fef%36DSq$a z@3EM_H0S02@0$O*f4{F6|I*6P{@YrAWA*s=KK>4$f9Vbx{%5-Xe?R}#-1wJXip~E% v`u_WI^B*(i-@EtwROOePyZwJE_iN%JFAWA5EP;T~0YBCdKtR+EKd=5DuQl$g literal 0 HcmV?d00001 diff --git a/backend/lib/ikon-app-core-1.0.0.jar b/backend/lib/ikon-app-core-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..a5d66350602916819b6bc542e7e3a82fffbb3ee6 GIT binary patch literal 6277 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 literal 0 HcmV?d00001 diff --git a/backend/lib/ikon-autoconfigure-1.0.0.jar b/backend/lib/ikon-autoconfigure-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..064d62a3c026a763615268c10826dab50542e3b3 GIT binary patch literal 3757 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 G1oD6D@+NO^+;e;F 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 literal 0 HcmV?d00001 diff --git a/backend/lib/ikon-core-1.0.0.jar b/backend/lib/ikon-core-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..351ecc6bb4ad23ee8f89e5443c5c3f5d5d292dfa GIT binary patch literal 73198 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 AF8}}l literal 0 HcmV?d00001 diff --git a/backend/lib/ikon-platform-1.0.0.jar b/backend/lib/ikon-platform-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..2ad2c832dab7a6301cc6006593e7770bca5920cb GIT binary patch literal 43784 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%0D(jW>)9 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�b)0CrguLQfkwIfD*WBRT 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 literal 0 HcmV?d00001 diff --git a/backend/lib/ikon-processmanagement-1.0.0.jar b/backend/lib/ikon-processmanagement-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..cfbbb14365dc6b89e70f66a504a50cf9eb843e5d GIT binary patch literal 39041 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 literal 0 HcmV?d00001 diff --git a/backend/lib/ikon-sdk-1.0.0.jar b/backend/lib/ikon-sdk-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..c834c903fa7b61e5cf261accf9aee3cd7909e27b GIT binary patch literal 14552 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 literal 0 HcmV?d00001 diff --git a/backend/lib/ikon-web-context-manager-1.0.0.jar b/backend/lib/ikon-web-context-manager-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..369fc437e55e1bdfcceaf1366414573ce184040a GIT binary patch literal 7274 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 literal 0 HcmV?d00001 diff --git a/backend/lib/ikon-web-security-1.0.0.jar b/backend/lib/ikon-web-security-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..529d8c49530c616c20231bdbd9ce1737fd753b41 GIT binary patch literal 16206 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

OV)Mi9|)IAt19@FajixZ%TC;z%41Lz(*}A zB}8j)V`pk*OlxgtO!LoMBRgG7LuYF{a~eHsYX=%#fCu_NuIY|;hBW`}k8WydV{PYP zFFrIpIq-34c$`vNl0u4_Vn9M_67Ze)fW-7M7<52BDY(GPXX4^tQ`?bp1%pTuFI|Bi z<|8=IM77(En5+uGa*_tnMSmlC`%yqkT_-~;T77Fv8dHG&nfBX1)IZHpHh@34SXvCm zjhcO;L-8+@-{gE#sV-{U#HY+u6|w-Urc_JsR6G-$ts3{1n3G)ppp{6~DYafw9hw9| zVu<}dvQ?xlcVuppm&^Xxk|g%lq1LIil`uz-S~+2oO5OgQB%f8=Ld3a?H@b2D^Qw%N zIW_uC)?~Ov4Y2h~y~v2qtkb+1HF_dsI|=P`W+3*GXccv$Q1UWkhZ=6WL;WzvWU>vOe-UJ6)L_4N6oSc4zA{fUYV63G2#(@G?*GVEp_k}8 zvq8e3#wjNB0pDzOMwC_CopOE&t`)ak1k;BVgyfHlwkFjFACmzmP>iBsTAEg<_ z@%g?m^&558f$BO5bT_2Rof>D#cr??uesJf8>OY++d|mg& zwKCw)jrfpRhrGA$siH(hhx_U#B=s;B(fq#Uy6RjbrD#a(cf}K&LM#I(X!&&bPOfBRo=HzlV{VhU*tnIw zSreAPz|AUJ$38k`LAt`!I?fU<9I~~$d^4V=Rdf-rvTas40Q#~;hdH)I-gJYX^cb}6--lsIokd@y|jNE{m<^S>Nx3RMZ1d}?L8rq9fQGAdPm!LV4 zs2Kb<7O8)X#r1VD+J0JUATi=EU$(u8T^su4LV_8Ok1gO%VNYOP8UTY47z70r;QI=2 zD(mviQv;OY#|8D{9RkoE-?tAx2IoJ?9s*s81GhNc0skQ$a09;mapibF2fY80Op;GZ zR7g->fksm3Zy5vJasR!(Wjq0R510l3p*8<&QP2KO@t=v~Z^-~`^Z#DoGI|D(Y`kowf(b0 zc?^ye2m#s(C=&%>TBG=m40z4)UI2{wU%r--v2O4Q%*LtqcHy*YAt{yZ{QP2(S)ZgaH8&e#Zv9=6JUNdf}I1 zKZ5@~-s5wmzC-4C=ZpUd?~y;n#k4T|H_+p8c^^~9KcK^_{sH~>MDmY;AG01m z0GDX}0r=aa^?MHF$Ka324e-<$fGM^pG2p-|ut# zOE}SE@W(#?58%x~zX$&>2jjm)06fm^u>W;`HI@&+AO*h%ei+05{W$(kDe{1L zRQ!{S_5Vpl@^gKDr}22mJ?h<0xj&Nd9?NF`>OX!4|0a7r-cUY(N0j})fj?|7WyHY& U_A4MDD!>mhfH@bh{M)Dh1EFJg1poj5 literal 0 HcmV?d00001 diff --git a/backend/lib/kafka-utils-1.0.0.jar b/backend/lib/kafka-utils-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..2e257a010db1a6b76146051590e148437b0222e6 GIT binary patch literal 7077 zcmb7I1z40_(_W-|Sy~Y3t_7qdq#FTQ5oAGP>7@}=Kw3aSx24&XQR$YFmJ%cc z;a^^V<$d|o_xldlxp;PW=AM~z=FBta)=)u3!vO%W0DxNGOg+Hg1~&3pO-@^iOG#ax zM*}HFf)vC0OH9f~KEn<9b0l&izdaXIlTufbm%F9SttJoaEyii)1$xbjhq+dfSKWJc zOK{B;LCe1Jq`E6yfU8$-Ykf$~{`9cXyX2WZiCrC8eCd-mc%Dd}Y8Ogv>=W;lB*gTK z*{D?+KAWkx<-^Vpt=AH=b)4?|?*)gcvzWG9b(JLf>w=m0fR@kvAWYGXA4k4*4cDQZ zdHU;s(2$;**unpb<<}BtA)iTDTHD$FLF_E#pJLWVX4Xb7&XzV#f6$=*jfNA<@xG-A z><^lRNX?(S05`f1`;%i7|0#_0llx!7Vf=&EU(s=$hj*R>{zGq)!jPI3$jO47zgiGE zq`S_lmQKzvTbLuaiH(ty6GTlMnHCfthC}kW!EUHR&>l)^XAm{o{vBf_Vq&F!nzv1; zZmeJwOpk8g{iBDHDS(P>3Y_MW`$7d}rTR}_kwLYYx1c<5v20*Qbc&H;TxBZxB-X^% zd`7ejV~;e+NupK-9p3FVexu8&wWrxboh}VAk6?^O+m&^lX-ssGaLx2IBIS=VF(M-K zc_yF#N|*DX0#Qo6I*`H8p#T7^e+o*&#n{Hu$>K*;F!fs7<{Q8y7vt-|Kzce)+GtBh z50G4{7dsZ?-Q6dpuV;0fC64A<4*(K44sDPv<+QQ(PZn=u=doXt@JLWM-_swE$*5ARtvnHe4z zq{mQF4Kp<@v?adB9paA7>{s3LVXay5EnH4p+ns_EeKpctiCbbX$4EQ%o~Ei-pcQ+` zR&oe+v!9vhWD?U|)fHa8TQfgxSl+FfOuL$z^WdZP*P8oE;JropqJ31z@?(gX3v6-9nL69r!q=EkKznY z((F~1zbg>Zlgihajm34pZE-jv^K;K~()yj?ReeyN!$8p#P9=^+BwdbmMGL;|7#{TS z8cT;(1u>!VD?d12g$ZU$3MfoYflG=_aDg>YMD&hu<_r_i+lqh_9#oRRMjYvTDY)k zv^92ZRQYzWR&VZxr%=Q0TmqR4UVh@U$7u-@k%Gifdub|xELP?m<(_wqtP&p8zUF;DoX*4a>3)rT zavHX1Td*1A)(8aNgdoz{6Kth^(O4d@Hhw(Mr9l@hjIh<3&unf|df5fr_&AcnNMmDR zr5S>kH8LQmI}Qz4vDo2o8K;yhXP7qjF|TilQ~#i4!YSq3pChBUBGs0-c1!shYv}=P zI68rYq*3!oonj+B!&83shefO}4uUSu?E+vRC^rlz9M+?4bp%0X6dukH%UbPu1BE(G_EHuen z!OF>-NFBWkW~xex1?&G zak6psOES>rGnWK{f+>08+k*jp=T~EkpKQuBd-9J=zA{g2Ua?vX;;?D-P zxxA^U=9+cY=AcS$9&Davr%dSp8KfPSuqiUuHN77&h|=pM52ZnNcWa5kn?lMrTcD%<^}EA;&&8{h2FnV8WHy_fHUI*BKK9!xWvg4aD=iGs zx>I68Z+J3=HOg(sZ*k^V%3APSPz46k#yk%%c|K1ph4v08#~S9}t)SBL74Uj>wiJy{DNBCPBIV3{Yh2{ppDJyE&&a z5P>Qt0po_TSHJ7WLd13z=25t4OVE4!OYi1)yp6^pRnP)Zo!$-j&-$w+itIJUJqV9F zFk@a(4-5iL)&@%je7Ps#!&uKag-4os$)p>f#Apt8Hv|OpX)tV!y@Z?Q?H{K&YQ2^! z49yZAP8TL)-5c0~X`PT-NL{H@(a}6K_aBE)o5zV(1S?Q{xpS54!@DgZ(=0jd_U8@0 z?Ou>)_h>9W1Wg_8t)@X0Z=G4tdD^hfL}t8@};LvY~(;biwM?8!lo(ep{Wy5AU4e|zK z6Zh%W7~rIxnh6Bk%}$hA8GAfwsI{a%aGOqb$5yF#1wVjKpR9K@dau;7Y7zCGQ0nMx z69rt?7~$LYV)4YDSPm(8QXqs{sU%0C#nV8g8vWs3ZXPVBvY|0;m;%g;`(HHo&Rk>Vrg9A9n<5` z%ddAlj$hZF03~tUPej4FEud&lJeybUaE zKYNga3IHr2+voqOP0(<(Gj%b!&?aO+*0m<&NyM#fw5f>ng%E0zAVnoBRJn9`0!b}! zPFfM{H%N10HvHL`q+737nLe^o*?ioYS@J6&S>jffE0>9?s=y7;(O30Lo=Hc=wWr7X zdv<^|w-^~56O4XlJ__@W#u!uWi!YRZBe9uT#j&$Aq^1PFRu;cIu zZN|!zLU;2BB$u~XohM)8_=!5&808E3YB*e<9Dbh?k>5dhGOlTX7gZGpiY^I3WYz_WIX3cUqECYuY z)Zg`XWFuSo*b#58pp4B^mK#wQ6ea{Mrt}X7EnJG;%?+}SGwZOQb~OY~auOt7l}))K zs$I}~g1N9wSwM9#*-Cy8G5hvV8f@AkGn?NIrXeSmNlI+=ro!u1;u5co9;+GHbL+95 zmxkv(8*c1lEsUYuAmb4v%Z=HYxi!q+77~ThTe~XNv!%8HzagIKkWOjY`w>( zxNQ}iY-B9rF}}@lI(j&sQGfd@ddFtqmPW;1)mw3r;A~rH9`hzg0r!xf1mHS7mRsVe zne@u_ih_Yabl*Pl+Z@kQ@M}mrSXxT?)j=prSL%&&kNPdYu;2TtIpE^c62eeoluaTz zW1$sFf4}thv4(*T^aH%&U{V8nDTb1U*@Y$0-7xokZe*_=ec&X@KJm2kP%cfBJ7vmj z@a%((Vm`f;Ax+IWedb=10&WJ_Q#FO>`!@Y(JS#5+UO!LAE04K)(=n|5GSq%^bFRq3 zih51tp*2nX0nz?W)lHueYQgQ%*D*mX2hp>`LDBP9Izx-B>f1DgJ#S2=r`9^8UavcH z6@EC)YF7ECK8C}mIw2~#gNLO7Hw*6zqLG^7iE0H`NGfEb#)V~&A1<*ihREe6yhKDX zYE

u!|=Ks|wFk9-!dJGS4Ao<8_y7^zq!ctXH}T#o<>RaK$L4XyJ+wP>M;tCUiR2G#QPE*6W1z+ zO&)khwJ8IF$=-8{Vq&z7&pbUxJcBRcA^wt2oh-dCjhEP(kd>q;(C+8}#QFKLbS5ut zS}`obl5dP8-V3eWZzGekp=IAAuIhx>Yh%IbVM=G?VvXXf&?w`=N6WR7Jrr+Hk7ccE zHcikMKIk>Q^GG&ieF71aC7r031`ifJ71uw#`p+Veut6m$hrBfjTmk?D|K+am`#XY% z=7jnsFff_E=#qg(Yj+|K^TFI#PQO+P52CbATX&u*6kHXRaqd3DohHJqv}Xh8JWVQ* zX5&s~Zk(XMm385CSQtSi^0t^jP zjjP*~gtrO;X5o+hn!(wld3OHc9;WuAs|(l$T-2t@!bGr-GQY@~MTiBuk zF-=zN`7-_it@I+=ldyo+&=bKk@=q@ua}Otfm} zVv`+%#5M$m@$t$rdta-HM!+Ss6L~>4Z42_3%G&F8R`|n8Fy9Ti;6y*0Cc$K~PW-JG z)um{f>-q@n+6R-5F#owRPD`AxFpwM5jhz40#{9A>hiG)Gx9|cd@yifgg&dDHxa0V9 z*y+*@ED)?jt|PiW6Ricu%k2&`s0Z0NiCEqign0tvUn~^(KRjQbxDJ?X*2TeYE`N_7 z$&o)A+?ZG8T2j#yF{UW>NkYphO@*i9BUgMgUGrgto$#yb+|hYsrDi%j&KyVi;m^T9 znt*{9(UX)pxi(*QqM#Mp0x)Tg*$}#g(PZ1SYfo=AA4@g(}kG7aCkrC`R8!1yP`t4Smj~lso04Aa^)*ua4*JuLIo`lZs7@F zgao<1u-)P)lV2NJc+>18WZp}E>MV*Fh&FG~FT8d9#q4M-U|7INnu^_V%OL??=4uC1 z$B&$&M2`(cTun`KAxa8jp|>vNyBjcA0ysgBsvzZiP9(N1q9sF$HBUpHuKjt`owG!L zI1r)*oO~pv8g29_feP7kDMv*G%!Cg_j&r+SUM-i&LDzh}?r?Wh)2Rd4yf-qcwMT=U za!;LtCMtwO$Jwy&qXost&YbM~%b94K)phpwP`K>J?ubjNmep6&=5=UC8f2{ut?l++ zYsy;&yqF(8S!r?1%FdMQS-UqO-`0-UR9=$W17Q=~qh;@;8{ByIiNK4jCiuD_fFRwC^8IFi=*_K#SV2V@6PNB|EbCF64!oguSj!T^Tu;LpZ*VZ1WKB$V- z6j^&EzGlteN8ZXTJ(#X<$HPK_`%TK#bv#<;rEhN2CfyShB9`5n+itYA9Hd-QX%1~g z{AkyWHN=N_OMJU{W$^ZW zDBMlLarSr%jc1N~^WOZ=sRZUFN^dgMzTjz8+Tf4+hH;*dXYB1^Kbfv5G7&|Plka~> zNP9;+dzhoMCCo{Mlf6?_MU{J7wYXPZwOf6Vi>tGTZE-=Fr;CRRfWy4BvC%^$?zHD`+b}l?n6GFv6O$(IAegnk28%OpCbhzk$x`Q5B~V~Zk#d5=gOu3sr<95{mF$h zM)@3N5=}7j0Z@P|j@( z5d9Z6{xyzYy{gY`a1sB<`S_XQe^1W;e{o-Q{$j~J2W}w!?}5(?u!agcvYP+^h>(8@ M=m3Bs+1aQ615ra`zW@LL literal 0 HcmV?d00001 diff --git a/backend/pom.xml b/backend/pom.xml new file mode 100644 index 0000000..fc6c3f3 --- /dev/null +++ b/backend/pom.xml @@ -0,0 +1,95 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.4 + + + com.ikon.projectmanagement + projectmanagement + 1.0.0 + pom + + projectmanagement + + + + + + + + + + + + + + + 21 + 21 + 2024.0.0 + 24.1.1 + 1.12.0 + 7.8.0 + 1.0.0 + 1.0.0 + + + + + maven-central + Maven Central Repository + https://ikon-vpm.keross.com/nexus/repository/maven-central + + true + + + false + + + + ikon-nexus + Ikon Repository + https://ikon-vpm.keross.com/nexus/repository/maven-releases + + true + + + false + + + + + + + + ikon-apps-lib-dist + Ikon App Lib Repository + https://ikon-vpm.keross.com/nexus/repository/ikon-apps-lib-dist/ + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + projectmanagement-client + projectmanagement-server + + diff --git a/backend/projectmanagement-client/pom.xml b/backend/projectmanagement-client/pom.xml new file mode 100644 index 0000000..efb8d12 --- /dev/null +++ b/backend/projectmanagement-client/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + com.ikon.projectmanagement + projectmanagement + 1.0.0 + + projectmanagement-client + + + com.ikon + ikon-core + ${ikon.sdk.version} + + + org.springframework.boot + spring-boot-starter-web + + + org.springdoc + springdoc-openapi-ui + 1.8.0 + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-validation + + + org.projectlombok + lombok + true + + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/DashboardApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/DashboardApi.java new file mode 100644 index 0000000..6d62111 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/DashboardApi.java @@ -0,0 +1,36 @@ +package com.ikon.projectmanagement.api; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import com.ikon.projectmanagement.dto.response.DashboardWidgetsResponseDto; +import com.ikon.projectmanagement.dto.response.StatusWiseProjectResponseData; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Dashboard", description = "APIs for managing dashboard") +@RequestMapping("/api/v1/dashboard") +public interface DashboardApi { + @Operation(summary = "Get dashboard widgets data", description = "Retrieves the data for the dashboard widgets.", responses = { + @ApiResponse(responseCode = "200", description = "Widgets data retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/widgets") + ResponseEntity getWidgetsData( + @RequestHeader("Authorization") String accessToken); + + @Operation(summary = "Get status-wise project data", description = "Retrieves the project data based on their status.", responses = { + @ApiResponse(responseCode = "200", description = "Project data retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/status-wise-projects") + ResponseEntity> getStatusWiseProjectData( + @RequestHeader("Authorization") String accessToken); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/EmployeeApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/EmployeeApi.java new file mode 100644 index 0000000..90e3d5d --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/EmployeeApi.java @@ -0,0 +1,44 @@ +package com.ikon.projectmanagement.api; + +import com.ikon.projectmanagement.dto.request.EmployeeRequestDto; +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; +import java.util.List; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Employee APIs", description = "APIs for managing local employees") +@RequestMapping("/api/v1/employees") +public interface EmployeeApi { + + @Operation(summary = "Get all employees") + @GetMapping + ResponseEntity> getAllEmployees(); + + @Operation(summary = "Get employee by ID") + @GetMapping("/{id}") + ResponseEntity getEmployeeById(@PathVariable String id); + + @Operation(summary = "Create a new employee") + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + ResponseEntity createEmployee(@RequestBody EmployeeRequestDto dto); + + @Operation(summary = "Update an existing employee") + @PutMapping("/{id}") + ResponseEntity updateEmployee(@PathVariable String id, @RequestBody EmployeeRequestDto dto); + + @Operation(summary = "Delete an employee") + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + ResponseEntity deleteEmployee(@PathVariable String id); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/FxRateApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/FxRateApi.java new file mode 100644 index 0000000..c2d3f6f --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/FxRateApi.java @@ -0,0 +1,40 @@ +package com.ikon.projectmanagement.api; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +import com.ikon.projectmanagement.dto.response.FxRateResponseDto; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.*; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "FX Rate APIs", description = "FX Rate configuration APIs") +@RequestMapping("/api/v1/fx-rate") +public interface FxRateApi { + + @Operation(summary = "Get all FX rate configurations", description = "Fetches all FX rate configurations.", responses = { + @ApiResponse(responseCode = "200", description = "FX rate list fetched successfully"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping + ResponseEntity> getAllFxRates( + @RequestHeader("Authorization") String accessToken, + Pageable pageable); + + @Operation(summary = "Get FX rate by year", description = "Fetches FX rate configuration by year.", parameters = { + @Parameter(name = "year", description = "Identifier of the year") + }, responses = { + @ApiResponse(responseCode = "200", description = "FX rate fetched successfully"), + @ApiResponse(responseCode = "404", description = "FX rate not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/year={year}") + ResponseEntity getFxRateByYear( + @RequestHeader("Authorization") String accessToken, + @PathVariable String year); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/GradeApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/GradeApi.java new file mode 100644 index 0000000..6925c4a --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/GradeApi.java @@ -0,0 +1,45 @@ +package com.ikon.projectmanagement.api; + +import com.ikon.projectmanagement.dto.request.GradeRequestDto; +import com.ikon.projectmanagement.dto.response.GradeResponseDto; +import java.util.List; +import java.util.UUID; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Grade APIs", description = "APIs for managing local grades") +@RequestMapping("/api/v1/grades") +public interface GradeApi { + + @Operation(summary = "Get all grades") + @GetMapping + ResponseEntity> getAllGrades(); + + @Operation(summary = "Get grade by ID") + @GetMapping("/{id}") + ResponseEntity getGradeById(@PathVariable UUID id); + + @Operation(summary = "Create a new grade") + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + ResponseEntity createGrade(@RequestBody GradeRequestDto dto); + + @Operation(summary = "Update an existing grade") + @PutMapping("/{id}") + ResponseEntity updateGrade(@PathVariable UUID id, @RequestBody GradeRequestDto dto); + + @Operation(summary = "Delete a grade") + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + ResponseEntity deleteGrade(@PathVariable UUID id); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportEmployeeApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportEmployeeApi.java new file mode 100644 index 0000000..beec5f3 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportEmployeeApi.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.api; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Import Employee API", description = "API for importing Employee master data from Sales CRM") +@RequestMapping("/import-data/employees") +public interface ImportEmployeeApi { + + @Operation(summary = "Fetch all employees from Sales CRM and persist locally") + @GetMapping + ResponseEntity> fetchAllEmployees(@RequestHeader("Authorization") String accessToken); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportFxRateApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportFxRateApi.java new file mode 100644 index 0000000..a5d95e4 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportFxRateApi.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.api; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.ikon.projectmanagement.dto.response.FxRateDto; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Import FX Rate API", description = "API for importing FX Rate master data from Sales CRM") +@RequestMapping("/import-data/fx-rates") +public interface ImportFxRateApi { + + @Operation(summary = "Fetch all FX rates from Sales CRM and persist locally") + @GetMapping + ResponseEntity> fetchAllFxRates(@RequestHeader("Authorization") String accessToken); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportGradeApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportGradeApi.java new file mode 100644 index 0000000..a46be61 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportGradeApi.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.api; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.ikon.projectmanagement.dto.response.GradeResponseDto; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Import Grade API", description = "API for importing Grade master data from Sales CRM") +@RequestMapping("/import-data/grades") +public interface ImportGradeApi { + + @Operation(summary = "Fetch all grades from Sales CRM and persist locally") + @GetMapping + ResponseEntity> fetchAllGrades(@RequestHeader("Authorization") String accessToken); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportRoleApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportRoleApi.java new file mode 100644 index 0000000..364624a --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportRoleApi.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.api; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.ikon.projectmanagement.dto.response.RoleResponseDto; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Import Role API", description = "API for importing Role master data from Sales CRM") +@RequestMapping("/import-data/roles") +public interface ImportRoleApi { + + @Operation(summary = "Fetch all roles from Sales CRM and persist locally") + @GetMapping + ResponseEntity> fetchAllRoles(@RequestHeader("Authorization") String accessToken); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportWorkingDayApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportWorkingDayApi.java new file mode 100644 index 0000000..1f98aec --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ImportWorkingDayApi.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.api; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.ikon.projectmanagement.dto.response.WorkingDayDto; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Import Working Day API", description = "API for importing Working Day master data from Sales CRM") +@RequestMapping("/import-data/working-days") +public interface ImportWorkingDayApi { + + @Operation(summary = "Fetch all working days from Sales CRM and persist locally") + @GetMapping + ResponseEntity> fetchAllWorkingDays(@RequestHeader("Authorization") String accessToken); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/IssueApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/IssueApi.java new file mode 100644 index 0000000..e857a28 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/IssueApi.java @@ -0,0 +1,76 @@ +package com.ikon.projectmanagement.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +import java.util.List; +import java.util.UUID; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import com.ikon.projectmanagement.dto.request.IssueCreateRequestDto; +import com.ikon.projectmanagement.dto.response.IssueResponseDto; + +@Tag(name = "Issue APIs", description = "Issue Management related APIs") +@RequestMapping("/api/v1/issues") +public interface IssueApi { + + // ================= CREATE ================= + + @Operation(summary = "Create a new issue", description = "Creates a new issue and returns the created issue details.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Issue details", required = true, content = @Content(schema = @Schema(implementation = IssueCreateRequestDto.class))), responses = { + @ApiResponse(responseCode = "201", description = "Issue created successfully"), + @ApiResponse(responseCode = "400", description = "Invalid issue data"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PostMapping + ResponseEntity createIssue( + @RequestHeader("Authorization") String accessToken, + @RequestBody IssueCreateRequestDto issueCreateRequestDto); + + // ================= READ ALL ================= + + @Operation(summary = "Get all issues", description = "Retrieves a list of all existing issues.", responses = { + @ApiResponse(responseCode = "200", description = "Issues retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/project/{projectIdentifier}") + ResponseEntity> getAllIssues( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier); + + + // ================= READ BY ID ================= + + @Operation(summary = "Get issue by ID", description = "Retrieves an issue by its unique issue ID.", responses = { + @ApiResponse(responseCode = "200", description = "Issue retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Issue not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{issueId}") + ResponseEntity getIssueById( + @RequestHeader("Authorization") String accessToken, + @PathVariable("issueId") UUID issueId); + + // ================= UPDATE ================= + + @Operation(summary = "Update an existing issue", description = "Updates the details of an existing issue identified by its ID.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Updated issue details", required = true, content = @Content(schema = @Schema(implementation = IssueCreateRequestDto.class))), responses = { + @ApiResponse(responseCode = "200", description = "Issue updated successfully"), + @ApiResponse(responseCode = "400", description = "Invalid issue data or ID provided"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Issue not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PutMapping("/{issueId}") + ResponseEntity updateIssue( + @RequestHeader("Authorization") String accessToken, + @PathVariable("issueId") UUID issueId, + @RequestBody IssueCreateRequestDto issueCreateRequestDto); + +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/MeetingApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/MeetingApi.java new file mode 100644 index 0000000..b207b66 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/MeetingApi.java @@ -0,0 +1,91 @@ +package com.ikon.projectmanagement.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +import java.util.List; +import java.util.UUID; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import com.ikon.projectmanagement.dto.request.MeetingRequestDTO; +import com.ikon.projectmanagement.dto.response.MeetingResponseDTO; + +@Tag(name = "Meeting APIs", description = "Meeting Management related APIs") +@RequestMapping("/api/v1/meetings") +public interface MeetingApi { + + // ================= CREATE ================= + + @Operation(summary = "Create a new meeting", description = "Creates a new meeting and returns the created meeting details.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Meeting details", required = true, content = @Content(schema = @Schema(implementation = MeetingRequestDTO.class))), responses = { + @ApiResponse(responseCode = "201", description = "Meeting created successfully"), + @ApiResponse(responseCode = "400", description = "Invalid meeting data"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PostMapping + ResponseEntity createMeeting( + @RequestHeader("Authorization") String accessToken, + @RequestBody MeetingRequestDTO meetingRequestDTO); + + // ================= READ ALL BY PROJECT ID ================= + + @Operation(summary = "Get all meetings by project ID", description = "Retrieves a list of all meetings for a given project using project UUID.", responses = { + @ApiResponse(responseCode = "200", description = "Meetings retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/project/{projectIdentifier}") + ResponseEntity> getAllMeetings( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier); + + // ================= READ ALL BY PROJECT IDENTIFIER ================= + + + + // ================= READ BY ID ================= + + @Operation(summary = "Get meeting by ID", description = "Retrieves a meeting by its unique meeting ID.", responses = { + @ApiResponse(responseCode = "200", description = "Meeting retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Meeting not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{meetingId}") + ResponseEntity getMeetingById( + @RequestHeader("Authorization") String accessToken, + @PathVariable("meetingId") UUID meetingId); + + // ================= UPDATE ================= + + @Operation(summary = "Update an existing meeting", description = "Updates the details of an existing meeting identified by its ID.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Updated meeting details", required = true, content = @Content(schema = @Schema(implementation = MeetingRequestDTO.class))), responses = { + @ApiResponse(responseCode = "200", description = "Meeting updated successfully"), + @ApiResponse(responseCode = "400", description = "Invalid meeting data or ID provided"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Meeting not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PutMapping("/{meetingId}") + ResponseEntity updateMeeting( + @RequestHeader("Authorization") String accessToken, + @PathVariable("meetingId") UUID meetingId, + @RequestBody MeetingRequestDTO meetingRequestDTO); + + // ================= DELETE ================= + + @Operation(summary = "Delete a meeting", description = "Deletes a meeting identified by its unique meeting ID.", responses = { + @ApiResponse(responseCode = "204", description = "Meeting deleted successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Meeting not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @DeleteMapping("/{meetingId}") + ResponseEntity deleteMeeting( + @RequestHeader("Authorization") String accessToken, + @PathVariable("meetingId") UUID meetingId); +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProductOfProjectApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProductOfProjectApi.java new file mode 100644 index 0000000..4ff0f59 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProductOfProjectApi.java @@ -0,0 +1,74 @@ +package com.ikon.projectmanagement.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +import java.util.List; +import java.util.UUID; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import com.ikon.projectmanagement.dto.request.ProductOfProjectRequestDto; +import com.ikon.projectmanagement.dto.request.WorkflowTransitionRequestDto; +import com.ikon.projectmanagement.dto.response.ProductOfProjectResponseDto; + +@Tag(name = "Product APIs", description = "Product Of Project Management related APIs") +@RequestMapping("/api/v1/projects") +public interface ProductOfProjectApi { + + @Operation(summary = "Get all products", description = "Retrieves a list of all existing products.", responses = { + @ApiResponse(responseCode = "200", description = "Products retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{projectIdentifier}/products") + ResponseEntity> getAllProductsByProject( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier); + + @Operation(summary = "Get product by product identifier", description = "Retrieves a single product under a project (account + project scoped).", responses = { + @ApiResponse(responseCode = "200", description = "Product retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Product not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{projectIdentifier}/products/{productIdentifier}") + ResponseEntity getProductById( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier, + @PathVariable("productIdentifier") UUID productIdentifier); + + // ================= UPDATE PRODUCT ================= + @Operation(summary = "Update an existing product", description = "Updates a product under a specific project (secure multi-tenant update).", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Updated product details", required = true, content = @Content(schema = @Schema(implementation = ProductOfProjectRequestDto.class))), responses = { + @ApiResponse(responseCode = "200", description = "Product updated successfully"), + @ApiResponse(responseCode = "400", description = "Invalid product data"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Product not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PutMapping("/{projectIdentifier}/products/{productIdentifier}") + ResponseEntity updateProduct( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier, + @PathVariable("productIdentifier") UUID productIdentifier, + @RequestBody ProductOfProjectRequestDto productDto); + + // ================= WORKFLOW STAGE TRANSITION ================= + @Operation(summary = "Transition product workflow stage", description = "Transitions the product to a new workflow stage with validation. The Schedule → Resources & Expenses transition requires schedule data to exist.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Transition request with target status", required = true, content = @Content(schema = @Schema(implementation = WorkflowTransitionRequestDto.class))), responses = { + @ApiResponse(responseCode = "200", description = "Transition successful"), + @ApiResponse(responseCode = "400", description = "Transition not allowed or preconditions not met"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Product not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PostMapping("/{projectIdentifier}/products/{productIdentifier}/transition") + ResponseEntity transitionProductStatus( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier, + @PathVariable("productIdentifier") UUID productIdentifier, + @RequestBody WorkflowTransitionRequestDto transitionDto); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProductResourceAllocationApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProductResourceAllocationApi.java new file mode 100644 index 0000000..ed01c1a --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProductResourceAllocationApi.java @@ -0,0 +1,81 @@ +package com.ikon.projectmanagement.api; + +import com.ikon.projectmanagement.dto.request.ProductPSResourceAllocationRequestDto; +import com.ikon.projectmanagement.dto.response.ProductPSResourceAllocationResponseDto; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@Tag(name = "Product Resource Allocation APIs", description = "Product resource allocation management APIs") +@RequestMapping("/api/v1/products") +public interface ProductResourceAllocationApi { + + @Operation(summary = "Get product resource allocations", description = "Retrieves all resource allocations for a product.", responses = { + @ApiResponse(responseCode = "200", description = "Allocations retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Product not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{productIdentifier}/resource-allocations") + ResponseEntity> getResourceAllocations( + @RequestHeader("Authorization") String accessToken, + @PathVariable("productIdentifier") UUID productIdentifier); + + @Operation(summary = "Get resource allocation", description = "Retrieves a single resource allocation by its ID.", responses = { + @ApiResponse(responseCode = "200", description = "Allocation retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Allocation not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{productIdentifier}/resource-allocations/{allocationIdentifier}") + ResponseEntity getResourceAllocation( + @RequestHeader("Authorization") String accessToken, + @PathVariable("productIdentifier") UUID productIdentifier, + @PathVariable("allocationIdentifier") UUID allocationIdentifier); + + @Operation(summary = "Create resource allocation", description = "Creates a new resource allocation for a product.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "New allocation details", required = true, content = @Content(schema = @Schema(implementation = ProductPSResourceAllocationRequestDto.class))), responses = { + @ApiResponse(responseCode = "201", description = "Allocation created successfully"), + @ApiResponse(responseCode = "400", description = "Invalid allocation data"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Product not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PostMapping("/{productIdentifier}/resource-allocations") + ResponseEntity createResourceAllocation( + @RequestHeader("Authorization") String accessToken, + @PathVariable("productIdentifier") UUID productIdentifier, + @RequestBody ProductPSResourceAllocationRequestDto allocationRequestDto); + + @Operation(summary = "Update resource allocation", description = "Updates an existing resource allocation for a product.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Updated allocation details", required = true, content = @Content(schema = @Schema(implementation = ProductPSResourceAllocationRequestDto.class))), responses = { + @ApiResponse(responseCode = "200", description = "Allocation updated successfully"), + @ApiResponse(responseCode = "400", description = "Invalid allocation data"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Allocation not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PutMapping("/{productIdentifier}/resource-allocations/{allocationIdentifier}") + ResponseEntity updateResourceAllocation( + @RequestHeader("Authorization") String accessToken, + @PathVariable("productIdentifier") UUID productIdentifier, + @PathVariable("allocationIdentifier") UUID allocationIdentifier, + @RequestBody ProductPSResourceAllocationRequestDto allocationRequestDto); + + @Operation(summary = "Delete resource allocation", description = "Deletes a resource allocation from a product.", responses = { + @ApiResponse(responseCode = "204", description = "Allocation deleted successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Allocation not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @DeleteMapping("/{productIdentifier}/resource-allocations/{allocationIdentifier}") + ResponseEntity deleteResourceAllocation( + @RequestHeader("Authorization") String accessToken, + @PathVariable("productIdentifier") UUID productIdentifier, + @PathVariable("allocationIdentifier") UUID allocationIdentifier); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProjectApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProjectApi.java new file mode 100644 index 0000000..c7bfbd9 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ProjectApi.java @@ -0,0 +1,82 @@ +package com.ikon.projectmanagement.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +import java.util.List; +import java.util.UUID; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.ikon.projectmanagement.dto.request.ProjectRequestDto; +import com.ikon.projectmanagement.dto.response.ProjectResponseDto; +import com.ikon.projectmanagement.dto.response.ProjectTimelineResponseDto; + +@Tag(name = "Project APIs", description = "Project Management related APIs") +@RequestMapping("/api/v1/projects") +public interface ProjectApi { + + @Operation(summary = "Create a new project", description = "Creates a new project and returns the created project details.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Project details", required = true, content = @Content(schema = @Schema(implementation = ProjectRequestDto.class))), responses = { + @ApiResponse(responseCode = "201", description = "Project created successfully"), + @ApiResponse(responseCode = "400", description = "Invalid project data"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PostMapping + ResponseEntity createProject( + @RequestHeader("Authorization") String accessToken, + @RequestBody ProjectRequestDto projectDto); + + @Operation(summary = "Get all projects", description = "Retrieves a list of all existing projects.", responses = { + @ApiResponse(responseCode = "200", description = "Projects retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping + public ResponseEntity> getAllProjects( + @RequestHeader("Authorization") String accessToken); + + @Operation(summary = "Get project by Id", description = "Retrieves a project by its unique project ID.", responses = { + @ApiResponse(responseCode = "200", description = "Project retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Project not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{projectIdentifier}") + public ResponseEntity getProjectByProjectIdentifier( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier); + + @Operation(summary = "Update an existing project", description = "Updates the details of an existing project identified by its ID.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Updated project details", required = true, content = @Content(schema = @Schema(implementation = ProjectRequestDto.class))), responses = { + @ApiResponse(responseCode = "200", description = "Project updated successfully"), + @ApiResponse(responseCode = "400", description = "Invalid project data or ID provided"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Project not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PutMapping("/{projectIdentifier}") + ResponseEntity updateProject( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier, + @RequestBody ProjectRequestDto projectDto); + + @Operation(summary = "Get all active projects start and end dates", description = "Retrieves a list of all active projects with their start and end dates.", responses = { + @ApiResponse(responseCode = "200", description = "Projects retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/active-projects-timeline") + public ResponseEntity> getAllActiveProjectsTimeline( + @RequestHeader("Authorization") String accessToken); + +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/RiskApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/RiskApi.java new file mode 100644 index 0000000..b66b383 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/RiskApi.java @@ -0,0 +1,84 @@ +package com.ikon.projectmanagement.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +import java.util.List; +import java.util.UUID; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.ikon.projectmanagement.dto.request.RiskCreateRequestDto; +import com.ikon.projectmanagement.dto.response.RiskResponseDto; + +@Tag(name = "Risk APIs", description = "Risk Management related APIs") +@RequestMapping("/api/v1/risks") +public interface RiskApi { + + @Operation(summary = "Create a new risk", description = "Creates a new risk and returns the created risk details.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Risk details", required = true, content = @Content(schema = @Schema(implementation = RiskCreateRequestDto.class))), responses = { + @ApiResponse(responseCode = "201", description = "Risk created successfully"), + @ApiResponse(responseCode = "400", description = "Invalid risk data"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PostMapping + ResponseEntity createRisk( + @RequestHeader("Authorization") String accessToken, + @RequestBody RiskCreateRequestDto riskCreateRequestDto); + + @Operation(summary = "Get all risks", description = "Retrieves a list of all existing risks.", responses = { + @ApiResponse(responseCode = "200", description = "Risks retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping + ResponseEntity> getAllRisks( + @RequestHeader("Authorization") String accessToken); + + @Operation(summary = "Get risk by Id", description = "Retrieves a risk by its unique risk ID.", responses = { + @ApiResponse(responseCode = "200", description = "Risk retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Risk not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{riskId}") + ResponseEntity getRiskById( + @RequestHeader("Authorization") String accessToken, + @PathVariable("riskId") UUID riskId); + + @Operation(summary = "Update an existing risk", description = "Updates the details of an existing risk identified by its ID.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Updated risk details", required = true, content = @Content(schema = @Schema(implementation = RiskCreateRequestDto.class))), responses = { + @ApiResponse(responseCode = "200", description = "Risk updated successfully"), + @ApiResponse(responseCode = "400", description = "Invalid risk data or ID provided"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Risk not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PutMapping("/{riskId}") + ResponseEntity updateRisk( + @RequestHeader("Authorization") String accessToken, + @PathVariable("riskId") UUID riskId, + @RequestBody RiskCreateRequestDto riskCreateRequestDto); + + @Operation(summary = "Get all risks by project", description = "Retrieves a list of all risks associated with a specific project.", responses = { + @ApiResponse(responseCode = "200", description = "Risks retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Project not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/project/{projectIdentifier}") + ResponseEntity> getRisksByProject( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") String projectIdentifier); + +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/RoleApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/RoleApi.java new file mode 100644 index 0000000..865a295 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/RoleApi.java @@ -0,0 +1,45 @@ +package com.ikon.projectmanagement.api; + +import com.ikon.projectmanagement.dto.request.RoleRequestDto; +import com.ikon.projectmanagement.dto.response.RoleResponseDto; +import java.util.List; +import java.util.UUID; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Role APIs", description = "APIs for managing local roles") +@RequestMapping("/api/v1/roles") +public interface RoleApi { + + @Operation(summary = "Get all roles") + @GetMapping + ResponseEntity> getAllRoles(); + + @Operation(summary = "Get role by ID") + @GetMapping("/{id}") + ResponseEntity getRoleById(@PathVariable UUID id); + + @Operation(summary = "Create a new role") + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + ResponseEntity createRole(@RequestBody RoleRequestDto dto); + + @Operation(summary = "Update an existing role") + @PutMapping("/{id}") + ResponseEntity updateRole(@PathVariable UUID id, @RequestBody RoleRequestDto dto); + + @Operation(summary = "Delete a role") + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + ResponseEntity deleteRole(@PathVariable UUID id); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ScheduleApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ScheduleApi.java new file mode 100644 index 0000000..07dfd7f --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/ScheduleApi.java @@ -0,0 +1,49 @@ +package com.ikon.projectmanagement.api; + +import com.ikon.projectmanagement.dto.request.ScheduleRequestDto; +import com.ikon.projectmanagement.dto.response.ScheduleResponseDto; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@Tag(name = "Schedule APIs", description = "Schedule management APIs for a project") +@RequestMapping("/api/v1/projects") +public interface ScheduleApi { + + @Operation(summary = "Save schedule", description = "Replaces the full schedule (tasks + dependencies) for a project. Removed tasks are automatically deleted.", responses = { + @ApiResponse(responseCode = "200", description = "Schedule saved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Project not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PutMapping("/{projectIdentifier}/schedules") + ResponseEntity saveSchedule( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier, + @RequestBody ScheduleRequestDto scheduleRequestDto); + + @Operation(summary = "Get schedule", description = "Retrieves the current schedule (tasks + dependencies) for a project.", responses = { + @ApiResponse(responseCode = "200", description = "Schedule retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Project not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{projectIdentifier}/schedules") + ResponseEntity getSchedule( + @RequestHeader("Authorization") String accessToken, + @PathVariable("projectIdentifier") UUID projectIdentifier); + + @Operation(summary = "Get all schedules", description = "Retrieves schedules for all projects under the current account.", responses = { + @ApiResponse(responseCode = "200", description = "Schedules retrieved successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/schedules") + ResponseEntity> getAllSchedules( + @RequestHeader("Authorization") String accessToken); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/WorkingDayApi.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/WorkingDayApi.java new file mode 100644 index 0000000..7939be8 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/api/WorkingDayApi.java @@ -0,0 +1,37 @@ +package com.ikon.projectmanagement.api; + +import com.ikon.projectmanagement.dto.response.WorkingDaysResponseDto; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "Working Day APIs", description = "APIs for managing local working days") +@RequestMapping("/api/v1/working-days") +public interface WorkingDayApi { + + @Operation(summary = "Get all working days configurations", description = "Fetches all working days configurations.", responses = { + @ApiResponse(responseCode = "200", description = "Working days list fetched successfully"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping + ResponseEntity> getAllWorkingDays( + @RequestHeader("Authorization") String accessToken, + Pageable pageable); + + @Operation(summary = "Get working days by year", description = "Fetches working days configuration by year.", responses = { + @ApiResponse(responseCode = "200", description = "Working days fetched successfully"), + @ApiResponse(responseCode = "404", description = "Working days not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{year}") + ResponseEntity getWorkingDaysByYear( + @RequestHeader("Authorization") String accessToken, + @PathVariable String year); +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ActionItemDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ActionItemDTO.java new file mode 100644 index 0000000..1e0c396 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ActionItemDTO.java @@ -0,0 +1,17 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ActionItemDTO { + + private String item; + + private String responsible; + + private String dueDate; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ActionsWrapperDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ActionsWrapperDTO.java new file mode 100644 index 0000000..16db358 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ActionsWrapperDTO.java @@ -0,0 +1,15 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ActionsWrapperDTO { + + private List actions; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AgendaItemDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AgendaItemDTO.java new file mode 100644 index 0000000..c28baf8 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AgendaItemDTO.java @@ -0,0 +1,15 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AgendaItemDTO { + + private String item; + + private String owner; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AgendaWrapperDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AgendaWrapperDTO.java new file mode 100644 index 0000000..f1da920 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AgendaWrapperDTO.java @@ -0,0 +1,15 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AgendaWrapperDTO { + + private List agenda; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AttendeeDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AttendeeDTO.java new file mode 100644 index 0000000..3135f89 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AttendeeDTO.java @@ -0,0 +1,17 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AttendeeDTO { + + private String name; + + private String role; + + private String contact; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AttendeesWrapperDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AttendeesWrapperDTO.java new file mode 100644 index 0000000..0b047b2 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/AttendeesWrapperDTO.java @@ -0,0 +1,15 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AttendeesWrapperDTO { + + private List attendees; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/DecisionsWrapperDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/DecisionsWrapperDTO.java new file mode 100644 index 0000000..90c84ce --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/DecisionsWrapperDTO.java @@ -0,0 +1,15 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DecisionsWrapperDTO { + + private List decisions; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/EmployeeRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/EmployeeRequestDto.java new file mode 100644 index 0000000..37073bf --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/EmployeeRequestDto.java @@ -0,0 +1,20 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class EmployeeRequestDto { + private String empId; + private String name; + private String email; + private String organizationEmail; + private String role; + private String grade; + private Boolean active; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/FxRateDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/FxRateDto.java new file mode 100644 index 0000000..dc0601d --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/FxRateDto.java @@ -0,0 +1,19 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FxRateDto { + private String fromCurrency; + private String toCurrency; + private BigDecimal rate; + private String effectiveDate; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/GradeRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/GradeRequestDto.java new file mode 100644 index 0000000..bd6a2b1 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/GradeRequestDto.java @@ -0,0 +1,18 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class GradeRequestDto { + private UUID id; + private UUID accountId; + private String grade; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ImportDataRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ImportDataRequestDto.java new file mode 100644 index 0000000..1f87bc2 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ImportDataRequestDto.java @@ -0,0 +1,17 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ImportDataRequestDto { + private Integer page; + private Integer size; + private String filterBy; + private String filterValue; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/IssueCreateRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/IssueCreateRequestDto.java new file mode 100644 index 0000000..8b64219 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/IssueCreateRequestDto.java @@ -0,0 +1,47 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class IssueCreateRequestDto { + + private String issueTitle; + + private Integer issueProbability; + + private BigDecimal grossIssueValue; + + private BigDecimal probableIssueValue; + + private BigDecimal probableIssueValueInUSD; + + private String issueImpact; + + private String issueOwner; + + private String issueDescription; + + private String mitigationAction; + + private UUID projectIdentifier; + + private Boolean financialIssue; + + private LocalDateTime issueCreatedDate; + + private String issueOptionsSelectId; + + private String issueStatus; + + private Integer issueAge; + + private String effectedSprintId; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/MeetingDetailsDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/MeetingDetailsDTO.java new file mode 100644 index 0000000..7886ea6 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/MeetingDetailsDTO.java @@ -0,0 +1,27 @@ +package com.ikon.projectmanagement.dto.request; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class MeetingDetailsDTO { + + private String title; + + private String projectName; + + private String place; + + private String date; + + private String time; + + private String duration; + + private String calledBy; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/MeetingRequestDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/MeetingRequestDTO.java new file mode 100644 index 0000000..cb35278 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/MeetingRequestDTO.java @@ -0,0 +1,30 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +import lombok.AllArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MeetingRequestDTO { + + private MeetingDetailsDTO meeting; + + private AttendeesWrapperDTO attendees; + + private AgendaWrapperDTO agenda; + + private DecisionsWrapperDTO decisions; + + private ActionsWrapperDTO actions; + + private OthersDTO others; + + private UUID projectIdentifier; + + private String status; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/OthersDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/OthersDTO.java new file mode 100644 index 0000000..4dc9abc --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/OthersDTO.java @@ -0,0 +1,13 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OthersDTO { + + private String notes; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductExpenseRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductExpenseRequestDto.java new file mode 100644 index 0000000..67afcd5 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductExpenseRequestDto.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductExpenseRequestDto { + + private String expenseName; + private String location; + private String currency; + private Double cost; + private Integer quantity; + private Double totalCost; + private String remarks; + +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductOfProjectRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductOfProjectRequestDto.java new file mode 100644 index 0000000..0328cfe --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductOfProjectRequestDto.java @@ -0,0 +1,35 @@ +package com.ikon.projectmanagement.dto.request; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import com.ikon.projectmanagement.dto.response.ProductExpenseResponseDto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductOfProjectRequestDto { + + private UUID projectIdentifier; + private String projectName; + private UUID projectManager; + + private UUID accountId; + private UUID leadIdentifier; + + private String productStatus; + private String projectStatus; + private String productType; + private String productDescription; + private Double discountPercent; + + private Map expenseDetails; + private List resourceDataWithAllocation; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductPSResourceAllocationRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductPSResourceAllocationRequestDto.java new file mode 100644 index 0000000..817785c --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProductPSResourceAllocationRequestDto.java @@ -0,0 +1,25 @@ +package com.ikon.projectmanagement.dto.request; + +import java.util.Map; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductPSResourceAllocationRequestDto { + + private String resourceType; + private String role; + private Integer gradeId; + private String employeeName; + private String taskName; + private String resourceId; + private Long taskId; + private Map allocation; + private Map> detailedAllocation; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProjectRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProjectRequestDto.java new file mode 100644 index 0000000..c3ea76d --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ProjectRequestDto.java @@ -0,0 +1,51 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.*; +import java.time.LocalDate; +import java.util.*; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProjectRequestDto { + + private UUID projectManager; + private String projectName; + private String projectStatus; + private String projectNumber; + private String parentProjectNo; + private String contractNumber; + private String projectClient; + private String projectCity; + private String projectCountry; + private String currency; + private String projectImage; + private String contractUpload; + private String source; + private String productType; + private String expenses; + private String formattedActualRevenueIncludingVAT_deal; + private Boolean isCompleted; + private Boolean groupNotExist; + private Boolean isDebtRevenue_deal; + private String projectDescription; + + private UUID updatedBy; + + private UUID projectManagerDelegates; + + private LocalDate projectStartDate; + private LocalDate contractedStartDate; + private LocalDate contractedEndDate; + + private List projectTeam; + private List projectTeamUnderProjectManager; + private List projectTeamUnderProjectManagerDelegates; + + private String groupAssigneesEditStr; + private String groupAssigneesViewStr; + + private Map participants; + private Map contractedProductIdentifierWiseDataObj; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/RiskCreateRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/RiskCreateRequestDto.java new file mode 100644 index 0000000..9ad0e30 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/RiskCreateRequestDto.java @@ -0,0 +1,45 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RiskCreateRequestDto { + + private String riskTitle; + + private Integer riskProbability; + + private BigDecimal grossRiskValue; + + private BigDecimal probableRiskValue; + + private BigDecimal probableRiskValueInUSD; + + private String riskImpact; + + private String riskOwner; + + private String riskDescription; + + private UUID projectIdentifier; + + private Boolean financialRisk; + + private LocalDateTime riskCreatedDate; + + private String riskOptionsSelectId; + + private String riskStatus; + + private Integer riskAge; + + private String effectedSprintId; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/RoleRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/RoleRequestDto.java new file mode 100644 index 0000000..9685c8c --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/RoleRequestDto.java @@ -0,0 +1,17 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class RoleRequestDto { + private UUID id; + private String role; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleDependencyDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleDependencyDto.java new file mode 100644 index 0000000..b3c892f --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleDependencyDto.java @@ -0,0 +1,14 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ScheduleDependencyDto { + private Long id; + private Long predecessorId; + private Integer dependencyType; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleGroupDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleGroupDto.java new file mode 100644 index 0000000..3bdff35 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleGroupDto.java @@ -0,0 +1,18 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ScheduleGroupDto { + private String id; + private String groupName; + private List taskIds = new ArrayList<>(); + private String color; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleRequestDto.java new file mode 100644 index 0000000..fd1f51f --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleRequestDto.java @@ -0,0 +1,17 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ScheduleRequestDto { + private List task; + private List dependency; + private Map group; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleTaskDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleTaskDto.java new file mode 100644 index 0000000..9e3207c --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/ScheduleTaskDto.java @@ -0,0 +1,23 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ScheduleTaskDto { + private Long id; + private Long parentId; + private String taskName; + private Double taskDuration; + private String taskPredecessor; + private Integer dependencyType; + private String taskColour; + private Double delayDuration; + private String taskDescription; + private String taskStart; + private String taskEnd; + private Boolean milestoneTask; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/WorkflowTransitionRequestDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/WorkflowTransitionRequestDto.java new file mode 100644 index 0000000..e22966d --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/WorkflowTransitionRequestDto.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WorkflowTransitionRequestDto { + + /** + * The target productStatus string to transition to. + * e.g. "Schedule Submitted From Product", + * "Submitted Resources and Expenses For Product", + * "Closed", + * "Recall Product Created from Schedule", etc. + */ + private String targetStatus; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/WorkingDayDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/WorkingDayDto.java new file mode 100644 index 0000000..ec8b849 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/request/WorkingDayDto.java @@ -0,0 +1,16 @@ +package com.ikon.projectmanagement.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class WorkingDayDto { + private String year; + private String month; + private String workingDays; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/DashboardWidgetsResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/DashboardWidgetsResponseDto.java new file mode 100644 index 0000000..400335b --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/DashboardWidgetsResponseDto.java @@ -0,0 +1,16 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class DashboardWidgetsResponseDto { + private Long totalProjects; + private Long totalIssues; + private Long totalRisksCount; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/EmployeeResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/EmployeeResponseDto.java new file mode 100644 index 0000000..fb52983 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/EmployeeResponseDto.java @@ -0,0 +1,26 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class EmployeeResponseDto { + private String empId; + private UUID accountId; + private String name; + private String email; + private String organizationEmail; + private String role; + private String grade; + private Boolean active; + private String highestQualification; + private String joiningDate; + private String confirmationDate; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateDetailsDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateDetailsDto.java new file mode 100644 index 0000000..f1c2c33 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateDetailsDto.java @@ -0,0 +1,12 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.Data; + +@Data +public class FxRateDetailsDto { + private String id; + private String currency; + private Double fxRate; + private Boolean activeStatus; + private String year; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateDto.java new file mode 100644 index 0000000..f945662 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateDto.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.UUID; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FxRateDto { + private UUID id; + private UUID accountId; + private String fromCurrency; + private String toCurrency; + private BigDecimal rate; + private String effectiveDate; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateResponseDto.java new file mode 100644 index 0000000..9f147c6 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/FxRateResponseDto.java @@ -0,0 +1,13 @@ +package com.ikon.projectmanagement.dto.response; + +import java.util.Map; +import java.util.UUID; + +import lombok.Data; + +@Data +public class FxRateResponseDto { + private UUID fxRateId; + private UUID accountIdentifier; + private Map> fxRateDetails; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/GradeResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/GradeResponseDto.java new file mode 100644 index 0000000..da20156 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/GradeResponseDto.java @@ -0,0 +1,18 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class GradeResponseDto { + private UUID id; + private UUID accountId; + private String grade; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/IssueResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/IssueResponseDto.java new file mode 100644 index 0000000..2ca4686 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/IssueResponseDto.java @@ -0,0 +1,49 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class IssueResponseDto { + + private UUID issueId; + + private String issueTitle; + + private Integer issueProbability; + + private BigDecimal grossIssueValue; + + private BigDecimal probableIssueValue; + + private BigDecimal probableIssueValueInUSD; + + private String issueImpact; + + private String issueOwner; + + private String issueDescription; + + private String mitigationAction; + + private UUID projectIdentifier; + + private Boolean financialIssue; + + private LocalDateTime issueCreatedDate; + + private String issueOptionsSelectId; + + private String issueStatus; + + private Integer issueAge; + + private String effectedSprintId; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/MeetingResponseDTO.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/MeetingResponseDTO.java new file mode 100644 index 0000000..d4ff1af --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/MeetingResponseDTO.java @@ -0,0 +1,37 @@ +package com.ikon.projectmanagement.dto.response; + +import com.ikon.projectmanagement.dto.request.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MeetingResponseDTO { + + private UUID id; + + private MeetingDetailsDTO meeting; + + private AttendeesWrapperDTO attendees; + + private AgendaWrapperDTO agenda; + + private DecisionsWrapperDTO decisions; + + private ActionsWrapperDTO actions; + + private OthersDTO others; + + private UUID projectIdentifier; + + private String status; + + private LocalDateTime createdAt; + + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductExpenseResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductExpenseResponseDto.java new file mode 100644 index 0000000..2c02592 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductExpenseResponseDto.java @@ -0,0 +1,25 @@ +package com.ikon.projectmanagement.dto.response; + +import java.util.UUID; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data + +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductExpenseResponseDto { + private UUID expenseIdentifier; + private String expenseName; + private String location; + private String currency; + private Double cost; + private Integer quantity; + private Double totalCost; + private String remarks; + +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductOfProjectResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductOfProjectResponseDto.java new file mode 100644 index 0000000..899e475 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductOfProjectResponseDto.java @@ -0,0 +1,40 @@ +package com.ikon.projectmanagement.dto.response; + +import java.util.Map; +import java.util.UUID; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductOfProjectResponseDto { + + private UUID productIdentifier; + + private UUID projectIdentifier; + private String projectName; + private UUID projectManager; + + private UUID accountId; + private UUID leadIdentifier; + + private String productStatus; + private String projectStatus; + private String productType; + private String productDescription; + private Double discountPercent; + + private String createdOn; + private UUID createdBy; + private UUID updatedBy; + private String updatedOn; + + private Map expenseDetails; + + private ScheduleResponseDto scheduleData; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductPSResourceAllocationResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductPSResourceAllocationResponseDto.java new file mode 100644 index 0000000..f333e54 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProductPSResourceAllocationResponseDto.java @@ -0,0 +1,27 @@ +package com.ikon.projectmanagement.dto.response; + +import java.util.Map; +import java.util.UUID; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductPSResourceAllocationResponseDto { + + private UUID id; + private String resourceType; + private String role; + private Integer gradeId; + private String employeeName; + private String taskName; + private String resourceId; + private Long taskId; + private Map allocation; + private Map> detailedAllocation; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProjectResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProjectResponseDto.java new file mode 100644 index 0000000..b252d9f --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProjectResponseDto.java @@ -0,0 +1,63 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProjectResponseDto { + + private UUID projectIdentifier; + + private UUID projectManager; + private String projectName; + private String projectStatus; + private String projectNumber; + private String parentProjectNo; + private String contractNumber; + private String projectClient; + private String projectCity; + private String projectCountry; + private String currency; + private String projectImage; + private String contractUpload; + private String source; + private String productType; + private String expenses; + private String formattedActualRevenueIncludingVAT_deal; + private Boolean isCompleted; + private Boolean groupNotExist; + private Boolean isDebtRevenue_deal; + private String projectDescription; + + private UUID createdById; + private UUID updatedBy; + private UUID projectManagerDelegates; + + private LocalDate projectStartDate; + private LocalDate contractedStartDate; + private LocalDate contractedEndDate; + private LocalDate createdOn; + private LocalDate updatedOn; + + private List projectTeam; + private List projectTeamUnderProjectManager; + private List projectTeamUnderProjectManagerDelegates; + + private String groupAssigneesEditStr; + private String groupAssigneesViewStr; + + private Map participants; + private Map contractedProductIdentifierWiseDataObj; + + private UUID productIdentifier; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProjectTimelineResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProjectTimelineResponseDto.java new file mode 100644 index 0000000..cea69f9 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ProjectTimelineResponseDto.java @@ -0,0 +1,19 @@ +package com.ikon.projectmanagement.dto.response; + +import java.util.UUID; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProjectTimelineResponseDto { + private UUID projectIdentifier; + private String projectName; + private String startDate; + private String endDate; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/RiskResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/RiskResponseDto.java new file mode 100644 index 0000000..0cd43b3 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/RiskResponseDto.java @@ -0,0 +1,46 @@ +package com.ikon.projectmanagement.dto.response; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.UUID; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RiskResponseDto { + private UUID riskIdentifier; + + private String riskTitle; + + private Integer riskProbability; + + private BigDecimal grossRiskValue; + + private BigDecimal probableRiskValue; + + private BigDecimal probableRiskValueInUSD; + + private String riskImpact; + + private String riskOwner; + + private String riskDescription; + + private UUID projectIdentifier; + + private Boolean financialRisk; + + private LocalDateTime riskCreatedDate; + + private String riskOptionsSelectId; + + private String riskStatus; + + private Integer riskAge; + + private String effectedSprintId; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/RoleResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/RoleResponseDto.java new file mode 100644 index 0000000..9ac7edd --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/RoleResponseDto.java @@ -0,0 +1,18 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class RoleResponseDto { + private UUID id; + private UUID accountId; + private String role; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ScheduleResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ScheduleResponseDto.java new file mode 100644 index 0000000..c58dea8 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/ScheduleResponseDto.java @@ -0,0 +1,23 @@ +package com.ikon.projectmanagement.dto.response; + +import com.ikon.projectmanagement.dto.request.ScheduleDependencyDto; +import com.ikon.projectmanagement.dto.request.ScheduleGroupDto; +import com.ikon.projectmanagement.dto.request.ScheduleTaskDto; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ScheduleResponseDto { + private UUID projectIdentifier; + private UUID productIdentifier; + private List task; + private List dependency; + private Map group; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/StatusWiseProjectResponseData.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/StatusWiseProjectResponseData.java new file mode 100644 index 0000000..6a0355a --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/StatusWiseProjectResponseData.java @@ -0,0 +1,15 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class StatusWiseProjectResponseData { + private String status; + private Long projectCount; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDayDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDayDto.java new file mode 100644 index 0000000..5f408ba --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDayDto.java @@ -0,0 +1,20 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class WorkingDayDto { + private UUID id; + private UUID accountId; + private String year; + private String month; + private String workingDays; +} diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDaysMonthDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDaysMonthDto.java new file mode 100644 index 0000000..f3f4702 --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDaysMonthDto.java @@ -0,0 +1,12 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.Data; + +@Data +public class WorkingDaysMonthDto { + + private String year; + private String month; + private Integer workingDays; + +} \ No newline at end of file diff --git a/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDaysResponseDto.java b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDaysResponseDto.java new file mode 100644 index 0000000..6431acc --- /dev/null +++ b/backend/projectmanagement-client/src/main/java/com/ikon/projectmanagement/dto/response/WorkingDaysResponseDto.java @@ -0,0 +1,12 @@ +package com.ikon.projectmanagement.dto.response; + +import lombok.Data; +import java.util.Map; +import java.util.UUID; + +@Data +public class WorkingDaysResponseDto { + private UUID workingId; + private UUID accountIdentifier; + private Map> workingDaysDetails; +} \ No newline at end of file diff --git a/backend/projectmanagement-server/ikoncloud-dev.keross.com.crt b/backend/projectmanagement-server/ikoncloud-dev.keross.com.crt new file mode 100644 index 0000000000000000000000000000000000000000..dab588394642a62b6f4ff901f23642c25b9bf781 GIT binary patch literal 1762 zcmb7EX;4#F6n^hz1Hv8*s4QU@2+2(Vfnc;Ki))|)ik7GtULX(%CJ&If!4nct<3_0# ztrOd-U!`xKwIUD5zM}(TYm}ZGxiy(CPHYow?`CcfPZIa{x~60ywEf zOF&=*F@^L;n(ld%&xZpGvZ=3Xrs{i%>bHU@698FhdASB+F#W(QKJQg309hY)&BH8iNQlzYpAT zs3=E{GG-XUC1Qyv8ABQ2Iar!ZF2V8{{)}iYaJIML268yuU=Rwp0U?VGW)O$V4Si<< zcaAG?dCTh{$&h7#i_ei;lCV zhs@r&E^NA#AC_Hqn$kV{ki$-!VZ7z?ARb%c;vA|zNB4N8xHW5osZ+ZAp^zIt;l z$N)~r0Op2qI?-VG4G{qla57q+L^`k|oA{Ao5{W{9-~W(NSvgr5!9)T=(gMB_?n0al z4C~ecElb55lZagU34tiYl2opO;~yLXSR%O;h>YP3ViH&k1Z3(m)l675k_A)jVKB`= z{jLB6rgO$vKPcxv^ao7HW#f){ zd3mhQ>V9;0mP9(yE}q`*nDAhR>B_Ac{DHc9sm6v9ZIJ(3vYBD0MEH6>LPUr-oMm|F za2k{c***~jo{p2xEh3L^-ZD)|dwH*Jxw>R`CLk64)u-~}K@eOf{k?uY1Q7|)Ob~^* zLjRbmCsjl=D&qb2mu#gpRg{$qE1ys|@9XH})ArNPMHnEbl})~06Y~Pv&hRg_@~GQq zoE7U5eiL_{611`3s1MG7a-cPfoNc>T`mSmx8Z>ohlAqs}KI+UzS2a!Zpj@bJ$SS>fg(>>Fd{@uxdNQyW|hZ~xls<41_SG=cx^swW;4Q9`9>W3V8uU1`4k z6lP_y*@td*366E{=)vx2Q%ez@Id!lloX}cbec|c=_V|&|?eK7Ez+#t4yLdRbe`s^9 rjV-Hoa{Jlmg4g#=tB;<&kt3d)UqjQFC6)$ndU`u@u29 + + 4.0.0 + + com.ikon.projectmanagement + projectmanagement + 1.0.0 + + projectmanagement-server + + + confluent + https://packages.confluent.io/maven/ + + + + + com.ikon + ikon-sdk + ${ikon.sdk.version} + + + com.ikon.projectmanagement + projectmanagement-client + ${projectmanagement.version} + + + com.ikon + ikon-client + ${ikon.sdk.version} + + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.modelmapper + modelmapper + 3.2.2 + + + + com.mysql + mysql-connector-j + runtime + + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + + org.springframework.kafka + spring-kafka + + + io.confluent + kafka-avro-serializer + ${avro-serializer.version} + + + + com.ikon + ikon-connector + 1.0.0 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/ProjectManagementApplication.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/ProjectManagementApplication.java new file mode 100644 index 0000000..260d828 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/ProjectManagementApplication.java @@ -0,0 +1,42 @@ + +package com.ikon.projectmanagement; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.actuate.autoconfigure.cassandra.CassandraHealthContributorAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +import com.ikon.autoconfigure.annotation.EnableIkonSdk; +import com.ikon.sdk.config.IkonSdkConfig; + +@EntityScan(basePackages = { + "com.ikon.projectmanagement.entity", + +}) +@EnableJpaRepositories(basePackages = { + "com.ikon.projectmanagement.repository", + +}) +@EnableFeignClients(basePackages = { + "com.ikon.client", + +}) +@SpringBootApplication(scanBasePackages = { + "com.ikon.projectmanagement", + +}, exclude = { + CassandraAutoConfiguration.class, + CassandraHealthContributorAutoConfiguration.class +}) +@EnableJpaAuditing +@EnableIkonSdk(configuration = IkonSdkConfig.class) +public class ProjectManagementApplication { + + public static void main(String[] args) { + SpringApplication.run(ProjectManagementApplication.class, args); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/ModelMapperConfig.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/ModelMapperConfig.java new file mode 100644 index 0000000..1135d7e --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/ModelMapperConfig.java @@ -0,0 +1,15 @@ +package com.ikon.projectmanagement.config; + +import org.modelmapper.ModelMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ModelMapperConfig { + + @Bean + ModelMapper modelMapper() { + return new ModelMapper(); + } + +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/RestTemplateConfigs.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/RestTemplateConfigs.java new file mode 100644 index 0000000..9cfa566 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/RestTemplateConfigs.java @@ -0,0 +1,13 @@ +package com.ikon.projectmanagement.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfigs { + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/SecurityConfig.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/SecurityConfig.java new file mode 100644 index 0000000..481272d --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/config/SecurityConfig.java @@ -0,0 +1,67 @@ +package com.ikon.projectmanagement.config; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import com.ikon.webservice.security.IkonJwtTokenConverter; + +@Configuration +@EnableWebSecurity +@EnableMethodSecurity +public class SecurityConfig { + + private Converter ikonJwtTokenConverter = new IkonJwtTokenConverter( + new JwtGrantedAuthoritiesConverter()); + + @Bean + SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .cors(cors -> cors.configurationSource(corsConfigurationSource())) // Enable CORS + .csrf(AbstractHttpConfigurer::disable) + .httpBasic(AbstractHttpConfigurer::disable) + .authorizeHttpRequests((authorize) -> { + authorize + + .requestMatchers("/actuator/health", "/actuator/health/**").permitAll() + + .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() + .anyRequest().authenticated(); + }) + .oauth2ResourceServer((oauth2) -> { + oauth2.jwt((jwt) -> jwt.jwtAuthenticationConverter(ikonJwtTokenConverter)); + }); + + return http.build(); + } + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOrigins(List.of("http://localhost:3000")); + configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); + configuration.setAllowedHeaders(List.of("*")); + configuration.setAllowCredentials(true); + configuration.setMaxAge(3600L); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } + +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/DashboardController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/DashboardController.java new file mode 100644 index 0000000..4dde71d --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/DashboardController.java @@ -0,0 +1,31 @@ +package com.ikon.projectmanagement.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; +import com.ikon.projectmanagement.api.DashboardApi; +import com.ikon.projectmanagement.dto.response.DashboardWidgetsResponseDto; +import com.ikon.projectmanagement.dto.response.StatusWiseProjectResponseData; +import com.ikon.projectmanagement.service.DashboardService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@RequiredArgsConstructor +@Slf4j +public class DashboardController implements DashboardApi { + private final DashboardService dashboardService; + + @Override + public ResponseEntity getWidgetsData(String accessToken) { + DashboardWidgetsResponseDto widgetsData = dashboardService.getDashboardWidgetsData(); + return ResponseEntity.ok(widgetsData); + } + + @Override + public ResponseEntity> getStatusWiseProjectData(String accessToken) { + List statusWiseData = dashboardService.getStatusWiseProjectData(); + return ResponseEntity.ok(statusWiseData); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/EmployeeController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/EmployeeController.java new file mode 100644 index 0000000..d696320 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/EmployeeController.java @@ -0,0 +1,63 @@ +package com.ikon.projectmanagement.controller; + +import com.ikon.projectmanagement.api.EmployeeApi; +import com.ikon.projectmanagement.dto.request.EmployeeRequestDto; +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; +import com.ikon.projectmanagement.service.EmployeeService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class EmployeeController implements EmployeeApi { + + private final EmployeeService employeeService; + + @Override + public ResponseEntity> getAllEmployees() { + return ResponseEntity.ok(employeeService.getAllEmployees()); + } + + @Override + public ResponseEntity getEmployeeById(String id) { + try { + EmployeeResponseDto employee = employeeService.getEmployeeById(id); + return ResponseEntity.ok(employee); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } + + @Override + public ResponseEntity createEmployee(EmployeeRequestDto dto) { + try { + EmployeeResponseDto createdEmployee = employeeService.createEmployee(dto); + return ResponseEntity.status(HttpStatus.CREATED).body(createdEmployee); + } catch (RuntimeException e) { + return ResponseEntity.badRequest().build(); + } + } + + @Override + public ResponseEntity updateEmployee(String id, EmployeeRequestDto dto) { + try { + EmployeeResponseDto updatedEmployee = employeeService.updateEmployee(id, dto); + return ResponseEntity.ok(updatedEmployee); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } + + @Override + public ResponseEntity deleteEmployee(String id) { + try { + employeeService.deleteEmployee(id); + return ResponseEntity.noContent().build(); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/FxRateController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/FxRateController.java new file mode 100644 index 0000000..b1db4c2 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/FxRateController.java @@ -0,0 +1,32 @@ +package com.ikon.projectmanagement.controller; + +import lombok.RequiredArgsConstructor; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import com.ikon.projectmanagement.api.FxRateApi; +import com.ikon.projectmanagement.dto.response.FxRateResponseDto; +import com.ikon.projectmanagement.service.FxRateService; + +@RestController +@RequiredArgsConstructor +public class FxRateController implements FxRateApi { + + private final FxRateService fxRateService; + + @Override + public ResponseEntity> getAllFxRates( + @RequestHeader("Authorization") String accessToken, + Pageable pageable) { + return ResponseEntity.ok(fxRateService.getAllFxRates(pageable)); + } + + public ResponseEntity getFxRateByYear( + @RequestHeader("Authorization") String accessToken, + @PathVariable String year) { + return ResponseEntity.ok(fxRateService.getFxRateByYear(year)); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/GradeController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/GradeController.java new file mode 100644 index 0000000..ef659c1 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/GradeController.java @@ -0,0 +1,64 @@ +package com.ikon.projectmanagement.controller; + +import com.ikon.projectmanagement.api.GradeApi; +import com.ikon.projectmanagement.dto.request.GradeRequestDto; +import com.ikon.projectmanagement.dto.response.GradeResponseDto; +import com.ikon.projectmanagement.service.GradeService; +import java.util.List; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class GradeController implements GradeApi { + + private final GradeService gradeService; + + @Override + public ResponseEntity> getAllGrades() { + return ResponseEntity.ok(gradeService.getAllGrades()); + } + + @Override + public ResponseEntity getGradeById(UUID id) { + try { + GradeResponseDto grade = gradeService.getGradeById(id); + return ResponseEntity.ok(grade); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } + + @Override + public ResponseEntity createGrade(GradeRequestDto dto) { + try { + GradeResponseDto createdGrade = gradeService.createGrade(dto); + return ResponseEntity.status(HttpStatus.CREATED).body(createdGrade); + } catch (RuntimeException e) { + return ResponseEntity.badRequest().build(); + } + } + + @Override + public ResponseEntity updateGrade(UUID id, GradeRequestDto dto) { + try { + GradeResponseDto updatedGrade = gradeService.updateGrade(id, dto); + return ResponseEntity.ok(updatedGrade); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } + + @Override + public ResponseEntity deleteGrade(UUID id) { + try { + gradeService.deleteGrade(id); + return ResponseEntity.noContent().build(); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportEmployeeController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportEmployeeController.java new file mode 100644 index 0000000..d65be2c --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportEmployeeController.java @@ -0,0 +1,26 @@ +package com.ikon.projectmanagement.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import com.ikon.projectmanagement.api.ImportEmployeeApi; +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; +import com.ikon.projectmanagement.service.ImportEmployeeService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@RequiredArgsConstructor +@Slf4j +public class ImportEmployeeController implements ImportEmployeeApi { + + private final ImportEmployeeService importEmployeeService; + + @Override + public ResponseEntity> fetchAllEmployees(String accessToken) { + return ResponseEntity.ok(importEmployeeService.importEmployees(accessToken)); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportFxRateController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportFxRateController.java new file mode 100644 index 0000000..b4b2883 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportFxRateController.java @@ -0,0 +1,26 @@ +package com.ikon.projectmanagement.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import com.ikon.projectmanagement.api.ImportFxRateApi; +import com.ikon.projectmanagement.dto.response.FxRateDto; +import com.ikon.projectmanagement.service.ImportFxRateService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@RequiredArgsConstructor +@Slf4j +public class ImportFxRateController implements ImportFxRateApi { + + private final ImportFxRateService importFxRateService; + + @Override + public ResponseEntity> fetchAllFxRates(String accessToken) { + return ResponseEntity.ok(importFxRateService.importFxRates(accessToken)); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportGradeController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportGradeController.java new file mode 100644 index 0000000..47d431d --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportGradeController.java @@ -0,0 +1,26 @@ +package com.ikon.projectmanagement.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import com.ikon.projectmanagement.api.ImportGradeApi; +import com.ikon.projectmanagement.dto.response.GradeResponseDto; +import com.ikon.projectmanagement.service.ImportGradeService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@RequiredArgsConstructor +@Slf4j +public class ImportGradeController implements ImportGradeApi { + + private final ImportGradeService importGradeService; + + @Override + public ResponseEntity> fetchAllGrades(String accessToken) { + return ResponseEntity.ok(importGradeService.importGrades(accessToken)); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportRoleController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportRoleController.java new file mode 100644 index 0000000..8078538 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportRoleController.java @@ -0,0 +1,26 @@ +package com.ikon.projectmanagement.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import com.ikon.projectmanagement.api.ImportRoleApi; +import com.ikon.projectmanagement.dto.response.RoleResponseDto; +import com.ikon.projectmanagement.service.ImportRoleService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@RequiredArgsConstructor +@Slf4j +public class ImportRoleController implements ImportRoleApi { + + private final ImportRoleService importRoleService; + + @Override + public ResponseEntity> fetchAllRoles(String accessToken) { + return ResponseEntity.ok(importRoleService.importRoles(accessToken)); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportWorkingDayController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportWorkingDayController.java new file mode 100644 index 0000000..13658c2 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ImportWorkingDayController.java @@ -0,0 +1,26 @@ +package com.ikon.projectmanagement.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import com.ikon.projectmanagement.api.ImportWorkingDayApi; +import com.ikon.projectmanagement.dto.response.WorkingDayDto; +import com.ikon.projectmanagement.service.ImportWorkingDayService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@RequiredArgsConstructor +@Slf4j +public class ImportWorkingDayController implements ImportWorkingDayApi { + + private final ImportWorkingDayService importWorkingDayService; + + @Override + public ResponseEntity> fetchAllWorkingDays(String accessToken) { + return ResponseEntity.ok(importWorkingDayService.importWorkingDays(accessToken)); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/IssueController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/IssueController.java new file mode 100644 index 0000000..388912b --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/IssueController.java @@ -0,0 +1,78 @@ +package com.ikon.projectmanagement.controller; + +import com.ikon.projectmanagement.api.IssueApi; +import com.ikon.projectmanagement.dto.request.IssueCreateRequestDto; +import com.ikon.projectmanagement.dto.response.IssueResponseDto; +import com.ikon.projectmanagement.service.IssueService; + +import java.util.List; +import java.util.UUID; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class IssueController implements IssueApi { + + private final IssueService issueService; + + @Override + public ResponseEntity createIssue( + String accessToken, + IssueCreateRequestDto issueCreateRequestDto) { + + IssueResponseDto createdIssue = issueService.createIssue(issueCreateRequestDto); + + return ResponseEntity + .status(HttpStatus.CREATED) + .body(createdIssue); + } + + @Override + public ResponseEntity> getAllIssues( + String accessToken,UUID projectIdentifier) { + + return ResponseEntity.ok( + issueService.getAllIssues(projectIdentifier)); + } + + @Override + public ResponseEntity getIssueById( + String accessToken, + UUID issueId) { + + return ResponseEntity.ok( + issueService.getIssueById(issueId)); + } + + @Override + public ResponseEntity updateIssue( + String accessToken, + UUID issueId, + IssueCreateRequestDto issueCreateRequestDto) { + + return ResponseEntity.ok( + issueService.updateIssue(issueId, issueCreateRequestDto)); + } + + // @Override + // public ResponseEntity deleteIssue( + // String accessToken, + // UUID issueId) { + + // issueService.deleteIssue(issueId); + // return ResponseEntity.noContent().build(); + // } + + // @Override + // public ResponseEntity> getIssuesByProject( + // String accessToken, + // UUID projectIdentifier) { + + // return ResponseEntity.ok( + // issueService.getIssuesByProject(projectIdentifier)); + // } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/MeetingController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/MeetingController.java new file mode 100644 index 0000000..22cb8b0 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/MeetingController.java @@ -0,0 +1,72 @@ +package com.ikon.projectmanagement.controller; + +import com.ikon.projectmanagement.api.MeetingApi; +import com.ikon.projectmanagement.dto.request.MeetingRequestDTO; +import com.ikon.projectmanagement.dto.response.MeetingResponseDTO; +import com.ikon.projectmanagement.service.MeetingService; + +import java.util.List; +import java.util.UUID; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class MeetingController implements MeetingApi { + + private final MeetingService meetingService; + + @Override + public ResponseEntity createMeeting( + String accessToken, + MeetingRequestDTO meetingRequestDTO) { + + MeetingResponseDTO createdMeeting = meetingService.createMeeting(meetingRequestDTO); + + return ResponseEntity + .status(HttpStatus.CREATED) + .body(createdMeeting); + } + + @Override + public ResponseEntity> getAllMeetings( + String accessToken, + UUID projectIdentifier) { + + return ResponseEntity.ok( + meetingService.getAllMeetings(projectIdentifier)); + } + + + + @Override + public ResponseEntity getMeetingById( + String accessToken, + UUID meetingId) { + + return ResponseEntity.ok( + meetingService.getMeetingById(meetingId)); + } + + @Override + public ResponseEntity updateMeeting( + String accessToken, + UUID meetingId, + MeetingRequestDTO meetingRequestDTO) { + + return ResponseEntity.ok( + meetingService.updateMeeting(meetingId, meetingRequestDTO)); + } + + @Override + public ResponseEntity deleteMeeting( + String accessToken, + UUID meetingId) { + + meetingService.deleteMeeting(meetingId); + return ResponseEntity.noContent().build(); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProductOfProjectController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProductOfProjectController.java new file mode 100644 index 0000000..6fd1c80 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProductOfProjectController.java @@ -0,0 +1,67 @@ +package com.ikon.projectmanagement.controller; + +import java.util.List; +import java.util.UUID; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import com.ikon.projectmanagement.api.ProductOfProjectApi; +import com.ikon.projectmanagement.dto.request.ProductOfProjectRequestDto; +import com.ikon.projectmanagement.dto.request.WorkflowTransitionRequestDto; +import com.ikon.projectmanagement.dto.response.ProductOfProjectResponseDto; +import com.ikon.projectmanagement.service.ProductOfProjectService; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class ProductOfProjectController implements ProductOfProjectApi { + + private final ProductOfProjectService productOfProjectService; + + @Override + public ResponseEntity> getAllProductsByProject( + String accessToken, + UUID projectIdentifier) { + + return ResponseEntity.ok( + productOfProjectService.getProductsByProject(projectIdentifier)); + } + + @Override + public ResponseEntity getProductById( + String accessToken, + UUID projectIdentifier, + UUID productIdentifier) { + + return ResponseEntity.ok( + productOfProjectService.getProduct(projectIdentifier, productIdentifier)); + } + + @Override + public ResponseEntity updateProduct( + String accessToken, + UUID projectIdentifier, + UUID productIdentifier, + ProductOfProjectRequestDto productDto) { + + return ResponseEntity.ok( + productOfProjectService.updateProduct(projectIdentifier, productIdentifier, + productDto)); + } + + @Override + public ResponseEntity transitionProductStatus( + String accessToken, + UUID projectIdentifier, + UUID productIdentifier, + WorkflowTransitionRequestDto transitionDto) { + + return ResponseEntity.ok( + productOfProjectService.transitionStatus( + projectIdentifier, + productIdentifier, + transitionDto.getTargetStatus())); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProductResourceAllocationController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProductResourceAllocationController.java new file mode 100644 index 0000000..07b2b12 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProductResourceAllocationController.java @@ -0,0 +1,62 @@ +package com.ikon.projectmanagement.controller; + +import java.util.List; +import java.util.UUID; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import com.ikon.projectmanagement.api.ProductResourceAllocationApi; +import com.ikon.projectmanagement.dto.request.ProductPSResourceAllocationRequestDto; +import com.ikon.projectmanagement.dto.response.ProductPSResourceAllocationResponseDto; +import com.ikon.projectmanagement.service.ProductResourceAllocationService; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class ProductResourceAllocationController implements ProductResourceAllocationApi { + + private final ProductResourceAllocationService allocationService; + + @Override + public ResponseEntity> getResourceAllocations( + String accessToken, + UUID productIdentifier) { + return ResponseEntity.ok(allocationService.getResourceAllocations(productIdentifier)); + } + + @Override + public ResponseEntity getResourceAllocation( + String accessToken, + UUID productIdentifier, + UUID allocationIdentifier) { + return ResponseEntity.ok(allocationService.getResourceAllocation(productIdentifier, allocationIdentifier)); + } + + @Override + public ResponseEntity createResourceAllocation( + String accessToken, + UUID productIdentifier, + ProductPSResourceAllocationRequestDto allocationRequestDto) { + return ResponseEntity.status(201).body(allocationService.createResourceAllocation(productIdentifier, allocationRequestDto)); + } + + @Override + public ResponseEntity updateResourceAllocation( + String accessToken, + UUID productIdentifier, + UUID allocationIdentifier, + ProductPSResourceAllocationRequestDto allocationRequestDto) { + return ResponseEntity.ok(allocationService.updateResourceAllocation(productIdentifier, allocationIdentifier, allocationRequestDto)); + } + + @Override + public ResponseEntity deleteResourceAllocation( + String accessToken, + UUID productIdentifier, + UUID allocationIdentifier) { + allocationService.deleteResourceAllocation(productIdentifier, allocationIdentifier); + return ResponseEntity.noContent().build(); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProjectController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProjectController.java new file mode 100644 index 0000000..44bec08 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ProjectController.java @@ -0,0 +1,66 @@ +package com.ikon.projectmanagement.controller; + +import com.ikon.projectmanagement.api.ProjectApi; +import com.ikon.projectmanagement.dto.request.ProjectRequestDto; +import com.ikon.projectmanagement.dto.response.ProjectResponseDto; +import com.ikon.projectmanagement.dto.response.ProjectTimelineResponseDto; +import com.ikon.projectmanagement.service.ProjectService; + +import java.util.List; +import java.util.UUID; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class ProjectController implements ProjectApi { + + private final ProjectService projectService; + + @Override + public ResponseEntity createProject( + String accessToken, + ProjectRequestDto projectRequestDto) { + + ProjectResponseDto createdProject = projectService.createProject(projectRequestDto); + + return ResponseEntity + .status(HttpStatus.CREATED) + .body(createdProject); + } + + @Override + public ResponseEntity> getAllProjects( + String accessToken) { + + return ResponseEntity.ok( + projectService.getAllProjects()); + } + + @Override + public ResponseEntity getProjectByProjectIdentifier(String accessToken, + UUID projectIdentifier) { + + return ResponseEntity.ok(projectService.getProjectByProjectIdentifier(projectIdentifier)); + } + + @Override + public ResponseEntity updateProject( + String accessToken, + UUID projectIdentifier, + ProjectRequestDto projectDto) { + + return ResponseEntity.ok( + projectService.updateProject(projectIdentifier, projectDto)); + } + + @Override + public ResponseEntity> getAllActiveProjectsTimeline( + String accessToken) { + + return ResponseEntity.ok(projectService.getAllActiveProjectsTimeline()); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/RiskController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/RiskController.java new file mode 100644 index 0000000..d60f659 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/RiskController.java @@ -0,0 +1,71 @@ +package com.ikon.projectmanagement.controller; + +import com.ikon.projectmanagement.api.RiskApi; +import com.ikon.projectmanagement.dto.request.RiskCreateRequestDto; +import com.ikon.projectmanagement.dto.response.RiskResponseDto; +import com.ikon.projectmanagement.service.RiskService; + +import java.util.List; +import java.util.UUID; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class RiskController implements RiskApi { + + private final RiskService riskService; + + @Override + public ResponseEntity createRisk( + String accessToken, + RiskCreateRequestDto riskCreateRequestDto) { + + RiskResponseDto createdRisk = riskService.createRisk(riskCreateRequestDto); + + return ResponseEntity + .status(HttpStatus.CREATED) + .body(createdRisk); + } + + @Override + public ResponseEntity> getAllRisks( + String accessToken) { + + return ResponseEntity.ok( + riskService.getAllRisks()); + } + + @Override + public ResponseEntity getRiskById( + String accessToken, + UUID riskId) { + + return ResponseEntity.ok( + riskService.getRiskById(riskId)); + } + + @Override + public ResponseEntity updateRisk( + String accessToken, + UUID riskId, + RiskCreateRequestDto riskCreateRequestDto) { + + return ResponseEntity.ok( + riskService.updateRisk(riskId, riskCreateRequestDto)); + } + + @Override + public ResponseEntity> getRisksByProject( + String accessToken, + String projectIdentifier) { + + return ResponseEntity.ok( + riskService.getRisksByProject(projectIdentifier)); + } + + +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/RoleController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/RoleController.java new file mode 100644 index 0000000..f9c2b1a --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/RoleController.java @@ -0,0 +1,64 @@ +package com.ikon.projectmanagement.controller; + +import com.ikon.projectmanagement.api.RoleApi; +import com.ikon.projectmanagement.dto.request.RoleRequestDto; +import com.ikon.projectmanagement.dto.response.RoleResponseDto; +import com.ikon.projectmanagement.service.RoleService; +import java.util.List; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class RoleController implements RoleApi { + + private final RoleService roleService; + + @Override + public ResponseEntity> getAllRoles() { + return ResponseEntity.ok(roleService.getAllRoles()); + } + + @Override + public ResponseEntity getRoleById(UUID id) { + try { + RoleResponseDto role = roleService.getRoleById(id); + return ResponseEntity.ok(role); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } + + @Override + public ResponseEntity createRole(RoleRequestDto dto) { + try { + RoleResponseDto createdRole = roleService.createRole(dto); + return ResponseEntity.status(HttpStatus.CREATED).body(createdRole); + } catch (RuntimeException e) { + return ResponseEntity.badRequest().build(); + } + } + + @Override + public ResponseEntity updateRole(UUID id, RoleRequestDto dto) { + try { + RoleResponseDto updatedRole = roleService.updateRole(id, dto); + return ResponseEntity.ok(updatedRole); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } + + @Override + public ResponseEntity deleteRole(UUID id) { + try { + roleService.deleteRole(id); + return ResponseEntity.noContent().build(); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ScheduleController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ScheduleController.java new file mode 100644 index 0000000..282f004 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/ScheduleController.java @@ -0,0 +1,39 @@ +package com.ikon.projectmanagement.controller; + +import com.ikon.projectmanagement.api.ScheduleApi; +import com.ikon.projectmanagement.dto.request.ScheduleRequestDto; +import com.ikon.projectmanagement.dto.response.ScheduleResponseDto; +import com.ikon.projectmanagement.service.ScheduleService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.UUID; + +@RestController +@RequiredArgsConstructor +public class ScheduleController implements ScheduleApi { + + private final ScheduleService scheduleService; + + @Override + public ResponseEntity saveSchedule( + String accessToken, + UUID projectIdentifier, + ScheduleRequestDto scheduleRequestDto) { + return ResponseEntity.ok(scheduleService.saveSchedule(projectIdentifier, scheduleRequestDto, accessToken)); + } + + @Override + public ResponseEntity getSchedule( + String accessToken, + UUID projectIdentifier) { + return ResponseEntity.ok(scheduleService.getSchedule(projectIdentifier, accessToken)); + } + + @Override + public ResponseEntity> getAllSchedules(String accessToken) { + return ResponseEntity.ok(scheduleService.getAllSchedules()); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/WorkingDayController.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/WorkingDayController.java new file mode 100644 index 0000000..a899d63 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/controller/WorkingDayController.java @@ -0,0 +1,36 @@ +package com.ikon.projectmanagement.controller; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +import com.ikon.projectmanagement.api.WorkingDayApi; +import com.ikon.projectmanagement.dto.response.WorkingDaysResponseDto; +import com.ikon.projectmanagement.service.WorkingDayService; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class WorkingDayController implements WorkingDayApi { + + private final WorkingDayService workingDayService; + + @Override + public ResponseEntity> getAllWorkingDays( + @RequestHeader("Authorization") String accessToken, Pageable pageable) { + + Page workingDaysList = workingDayService.getAllWorkingDays(pageable); + return ResponseEntity.ok(workingDaysList); + } + + @Override + public ResponseEntity getWorkingDaysByYear( + @RequestHeader("Authorization") String accessToken, @PathVariable String year) { + WorkingDaysResponseDto workingDays = workingDayService.getWorkingDaysByYear(year); + return ResponseEntity.ok(workingDays); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Employee.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Employee.java new file mode 100644 index 0000000..08685ab --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Employee.java @@ -0,0 +1,43 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +@Entity +@Table(name = "employees") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Employee { + + @Id + @Column(unique = true) + private String empId; + + @JdbcTypeCode(SqlTypes.UUID) + private UUID accountId; + + private String name; + private String email; + private String organizationEmail; + + @Column(name = "\"role\"") + private String role; + + private String grade; + private Boolean active; + + private String highestQualification; + private String joiningDate; + private String confirmationDate; +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/FxRateDetailsEntity.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/FxRateDetailsEntity.java new file mode 100644 index 0000000..8206c7c --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/FxRateDetailsEntity.java @@ -0,0 +1,41 @@ +package com.ikon.projectmanagement.entity; + +import java.util.UUID; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name = "fx_rate_details_v2") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FxRateDetailsEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "id") + private UUID id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "fx_rate_id", nullable = false) + @ToString.Exclude + @EqualsAndHashCode.Exclude + private FxRateEntity fxRateEntity; + + @Column(name = "currency_id", nullable = false) + private String currencyId; + + @Column(name = "currency") + private String currency; + + @Column(name = "fx_rate") + private Double fxRate; + + @Column(name = "active_status") + private Boolean activeStatus; + + @Column(name = "year") + private String year; +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/FxRateEntity.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/FxRateEntity.java new file mode 100644 index 0000000..9ef4575 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/FxRateEntity.java @@ -0,0 +1,36 @@ +package com.ikon.projectmanagement.entity; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name = "fx_rates_v2") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FxRateEntity { + + @Id + @Column(name = "fx_rate_id") + private UUID fxRateId; + + @Column(name = "account_identifier") + private UUID accountIdentifier; + + @OneToMany(mappedBy = "fxRateEntity", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + @MapKey(name = "currencyId") + @Builder.Default + @ToString.Exclude + @EqualsAndHashCode.Exclude + private Map fxRateDetails = new HashMap<>(); + + public void addFxRateDetail(FxRateDetailsEntity detail) { + detail.setFxRateEntity(this); + this.fxRateDetails.put(detail.getCurrencyId(), detail); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Grade.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Grade.java new file mode 100644 index 0000000..ff023c0 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Grade.java @@ -0,0 +1,32 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +@Entity +@Table(name = "grade") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Grade { + + @Id + @JdbcTypeCode(SqlTypes.UUID) + private UUID id; + + @JdbcTypeCode(SqlTypes.UUID) + private UUID accountId; + + @Column(nullable = false) + private String grade; +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Issue.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Issue.java new file mode 100644 index 0000000..e226f12 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Issue.java @@ -0,0 +1,93 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.UUID; + +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +@Entity +@Table(name = "issues") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Issue { + + @Id + @GeneratedValue + @JdbcTypeCode(SqlTypes.UUID) + @Column(name = "issue_id", nullable = false) + private UUID issueId; + + @Column(name = "issue_title", nullable = false) + private String issueTitle; + + @Column(name = "issue_probability") + private Integer issueProbability; + + @Column(name = "gross_issue_value") + private BigDecimal grossIssueValue; + + @Column(name = "probable_issue_value") + private BigDecimal probableIssueValue; + + @Column(name = "probable_issue_value_usd") + private BigDecimal probableIssueValueInUSD; + + @Column(name = "issue_impact") + private String issueImpact; + + @Column(name = "issue_owner") + private String issueOwner; + + @Column(name = "issue_description", columnDefinition = "TEXT") + private String issueDescription; + + @Column(name = "mitigation_action", columnDefinition = "TEXT") + private String mitigationAction; + + @Column(name = "project_identifier", nullable = false) + private UUID projectIdentifier; + + @Column(name = "financial_issue") + private Boolean financialIssue; + + @Column(name = "issue_created_date") + private LocalDateTime issueCreatedDate; + + @Column(name = "issue_options_select_id") + private String issueOptionsSelectId; + + @Column(name = "issue_status") + private String issueStatus; + + @Column(name = "issue_age") + private Integer issueAge; + + @Column(name = "effected_sprint_id") + private String effectedSprintId; + + @Column(name = "created_at") + private LocalDateTime createdAt; + + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(); + if (this.issueCreatedDate == null) { + this.issueCreatedDate = LocalDateTime.now(); + } + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Meeting.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Meeting.java new file mode 100644 index 0000000..ab07e47 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Meeting.java @@ -0,0 +1,139 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "meetings") +public class Meeting { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "id", updatable = false, nullable = false) + private UUID id; + + @Column(name = "title") + private String title; + + @Column(name = "project_name") + private String projectName; + + @Column(nullable = true) + private UUID createdBy; + + @Column(nullable = true) + private UUID accountId; + + @Column(name = "place") + private String place; + + @Column(name = "date") + private LocalDate date; + + @Column(name = "time") + private String time; + + @Column(name = "duration") + private String duration; + + @Column(name = "called_by") + private String calledBy; + + @ElementCollection + @CollectionTable(name = "meeting_attendees", joinColumns = @JoinColumn(name = "meeting_id")) + private List attendees; + + @ElementCollection + @CollectionTable(name = "meeting_agenda", joinColumns = @JoinColumn(name = "meeting_id")) + private List agenda; + + @ElementCollection + @CollectionTable(name = "meeting_decisions", joinColumns = @JoinColumn(name = "meeting_id")) + @Column(name = "decision", columnDefinition = "TEXT") + private List decisions; + + @ElementCollection + @CollectionTable(name = "meeting_actions", joinColumns = @JoinColumn(name = "meeting_id")) + private List actions; + + @Column(name = "notes", columnDefinition = "TEXT") + private String notes; + + @Column(name = "project_identifier", nullable = false) +private UUID projectIdentifier; + + @Column(name = "status") + private String status; + + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; + + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + @PrePersist + protected void onCreate() { + createdAt = LocalDateTime.now(); + updatedAt = LocalDateTime.now(); + } + + @PreUpdate + protected void onUpdate() { + updatedAt = LocalDateTime.now(); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Embeddable + public static class Attendee { + + @Column(name = "name") + private String name; + + @Column(name = "role") + private String role; + + @Column(name = "contact") + private String contact; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Embeddable + public static class AgendaItem { + + @Column(name = "item", columnDefinition = "TEXT") + private String item; + + @Column(name = "owner") + private String owner; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Embeddable + public static class ActionItem { + + @Column(name = "item", columnDefinition = "TEXT") + private String item; + + @Column(name = "responsible") + private String responsible; + + @Column(name = "due_date") + private LocalDate dueDate; + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductOfProject.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductOfProject.java new file mode 100644 index 0000000..598dbc0 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductOfProject.java @@ -0,0 +1,80 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.*; +import java.util.*; + +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +import com.ikon.projectmanagement.dto.response.ProductExpenseResponseDto; + +@Entity +@Table(name = "product_project") +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProductOfProject { + + @Id + @GeneratedValue + @JdbcTypeCode(SqlTypes.UUID) + @Column(name = "product_identifier") + private UUID productIdentifier; + + @Column(name = "project_identifier", nullable = true) + @JdbcTypeCode(SqlTypes.UUID) + private UUID projectIdentifier; + + @Column(name = "project_name", nullable = true) + private String projectName; + + @Column(name = "project_manager", nullable = true) + @JdbcTypeCode(SqlTypes.UUID) + private UUID projectManager; + + @Column(nullable = true) + private UUID accountId; + + @Column(nullable = true) + private UUID leadIdentifier; + + @Column(nullable = true) + private String productStatus; + + @Column(nullable = true) + private String updatedOn; + + @Column(nullable = true) + private String projectStatus; + + @Column(nullable = true) + private String productType; + + @Column(columnDefinition = "TEXT", nullable = true) + private String productDescription; + + @Column(nullable = true) + private Double discountPercent; + + @Column(nullable = true) + private String createdOn; + + @Column(nullable = true) + private UUID updatedBy; + + @Column(nullable = true) + private UUID createdBy; + + @OneToMany(mappedBy = "productPS", cascade = CascadeType.ALL, orphanRemoval = true) + private List quotation = new ArrayList<>(); + + @OneToMany(mappedBy = "productPS", cascade = CascadeType.ALL, orphanRemoval = true) + private List resourceDataWithAllocation = new ArrayList<>(); + + @OneToMany(mappedBy = "productPS", cascade = CascadeType.ALL, orphanRemoval = true) + @MapKey(name = "id") + private Map expenseDetails = new HashMap<>(); + +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductOfProjectExpenseDetail.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductOfProjectExpenseDetail.java new file mode 100644 index 0000000..aa277a0 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductOfProjectExpenseDetail.java @@ -0,0 +1,33 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.*; +import java.util.UUID; + +@Entity +@Table(name = "product_project_expense_detail") +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProductOfProjectExpenseDetail { + + @Id + @GeneratedValue + private UUID id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "product_prj_id", nullable = false) + private ProductOfProject productPS; + + private String expenseName; + private String location; + private String currency; + + private Double cost; + private Integer quantity; + private Double totalCost; + + @Column(columnDefinition = "TEXT") + private String remarks; +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductPSQuotation.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductPSQuotation.java new file mode 100644 index 0000000..7ce375e --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductPSQuotation.java @@ -0,0 +1,32 @@ +package com.ikon.projectmanagement.entity; + +import java.util.UUID; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name = "product_ps_quotation") +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProductPSQuotation { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; + + private String itemKey; // original map key + + private String role; + private Double totalFTE; + private Double scr; + private Double expenses; + private Double otherCosts; + private Double billingAmount; + + @ManyToOne + @JoinColumn(name = "deal_identifier" ) + private ProductOfProject productPS; +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductPSResourceAllocation.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductPSResourceAllocation.java new file mode 100644 index 0000000..fbc3f7c --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProductPSResourceAllocation.java @@ -0,0 +1,48 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.util.Map; +import java.util.UUID; + +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +@Entity +@Table(name = "product_ps_resource_allocation") +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProductPSResourceAllocation { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; + private String resourceType; + private String role; + private Integer gradeId; + private String employeeName; + private String taskName; + private String resourceId; + private Long taskId; + + // Storing FTE allotments per month: {"Aug_2025": 0.9, "Sep_2025": 0.5} + @ElementCollection + @CollectionTable( + name = "product_ps_resource_allocation_months", + joinColumns = @JoinColumn(name = "allocation_id") + ) + @MapKeyColumn(name = "month") + @Column(name = "fte_value") + private Map allocation; + + @JdbcTypeCode(SqlTypes.JSON) + @Column(columnDefinition = "json", nullable = true) + private Map> detailedAllocation; + + @ManyToOne + @JoinColumn(name = "deal_identifier") + private ProductOfProject productPS; +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Project.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Project.java new file mode 100644 index 0000000..555dde8 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Project.java @@ -0,0 +1,180 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import java.time.LocalDate; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; +import java.util.ArrayList; + +@Entity +@Table(name = "projects", uniqueConstraints = @UniqueConstraint(columnNames = "project_identifier")) +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Project { + + @Id + @JdbcTypeCode(SqlTypes.UUID) + @Column(name = "project_identifier") + private UUID projectIdentifier; + + @JdbcTypeCode(SqlTypes.UUID) + @Column(nullable = false) + private UUID projectManager; + + @Column(nullable = false) + private String projectName; + + @Column(nullable = false) + private UUID accountId; + + @Column(nullable = true) + private String projectStatus; + + @Column(nullable = true) + private String projectNumber; + + @Column(nullable = true) + private String parentProjectNo; + + @Column(nullable = true) + private String contractNumber; + + @Column(nullable = true) + private String projectClient; + + @Column(nullable = true) + private String projectCity; + + @Column(nullable = true) + private String projectCountry; + + @Column(nullable = true) + private String currency; + + @Column(nullable = true) + private String projectImage; + + @Column(nullable = true) + private String contractUpload; + + @Column(nullable = true) + private String source; + + @Column(nullable = true) + private String productType; + + @Column(nullable = true) + private String expenses; + + @Column(nullable = true) + private String formattedActualRevenueIncludingVAT_deal; + + @Column(nullable = true) + private Boolean isCompleted; + + @Column(nullable = true) + private Boolean groupNotExist; + + @Column(nullable = true) + private Boolean isDebtRevenue_deal; + + @Column(length = 2000, nullable = true) + private String projectDescription; + + @JdbcTypeCode(SqlTypes.UUID) + @Column(nullable = true) + private UUID createdById; + + @JdbcTypeCode(SqlTypes.UUID) + @Column(nullable = true) + private UUID updatedBy; + + @JdbcTypeCode(SqlTypes.UUID) + @Column(nullable = true) + private UUID projectManagerDelegates; + + @Column(nullable = true) + private LocalDate projectStartDate; + + @Column(nullable = true) + private LocalDate contractedStartDate; + + @Column(nullable = true) + private LocalDate contractedEndDate; + + @Column(nullable = true) + private LocalDate updatedOn; + + @Column(nullable = true) + private LocalDate createdOn; + + @ElementCollection + @CollectionTable(name = "project_team", joinColumns = @JoinColumn(name = "project_id")) + @Column(name = "user_id", nullable = true) + @JdbcTypeCode(SqlTypes.UUID) + @Builder.Default + private List projectTeam = new ArrayList<>(); + + @ElementCollection + @CollectionTable(name = "project_team_pm", joinColumns = @JoinColumn(name = "project_id")) + @Column(nullable = true) + @JdbcTypeCode(SqlTypes.UUID) + private List projectTeamUnderProjectManager = new ArrayList<>(); + + @ElementCollection + @CollectionTable(name = "project_team_pm_delegates", joinColumns = @JoinColumn(name = "project_id")) + @Column(nullable = true) + @JdbcTypeCode(SqlTypes.UUID) + private List projectTeamUnderProjectManagerDelegates = new ArrayList<>(); + + @Column(length = 2000, nullable = true) + private String groupAssigneesEditStr; + + @Column(length = 2000, nullable = true) + private String groupAssigneesViewStr; + + @JdbcTypeCode(SqlTypes.JSON) + @Column(columnDefinition = "json", nullable = true) + private Map participants; + + @JdbcTypeCode(SqlTypes.JSON) + @Column(columnDefinition = "json", nullable = true) + private Map contractedProductIdentifierWiseDataObj; + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "product_identifier", nullable = true) + private ProductOfProject product; + + +@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) +@JoinColumn(name = "project_identifier") +@Builder.Default +private List risks = new ArrayList<>(); + + +@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) +@JoinColumn(name = "project_identifier") +@Builder.Default +private List meetings = new ArrayList<>(); +} + diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectSchedule.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectSchedule.java new file mode 100644 index 0000000..b565a12 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectSchedule.java @@ -0,0 +1,51 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Entity +@Table(name = "project_schedule", uniqueConstraints = { + @UniqueConstraint(columnNames = "project_identifier") +}) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProjectSchedule { + + @Id + @GeneratedValue + @JdbcTypeCode(SqlTypes.UUID) + @Column(name = "schedule_identifier") + private UUID scheduleIdentifier; + + @Column(name = "project_identifier", nullable = false) + @JdbcTypeCode(SqlTypes.UUID) + private UUID projectIdentifier; + + @Column(name = "product_identifier", nullable = true) + @JdbcTypeCode(SqlTypes.UUID) + private UUID productIdentifier; + + @Column(name = "account_id", nullable = false) + @JdbcTypeCode(SqlTypes.UUID) + private UUID accountId; + + @OneToMany(mappedBy = "schedule", cascade = CascadeType.ALL, orphanRemoval = true) + @Builder.Default + private List tasks = new ArrayList<>(); + + @OneToMany(mappedBy = "schedule", cascade = CascadeType.ALL, orphanRemoval = true) + @Builder.Default + private List dependencies = new ArrayList<>(); + + @OneToMany(mappedBy = "schedule", cascade = CascadeType.ALL, orphanRemoval = true) + @Builder.Default + private List groups = new ArrayList<>(); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleDependency.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleDependency.java new file mode 100644 index 0000000..1fa7341 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleDependency.java @@ -0,0 +1,27 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name = "project_schedule_dependency") +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProjectScheduleDependency { + + @Id + @Column(name = "id") + private Long id; + + @Column(name = "predecessor_id") + private Long predecessorId; + + @Column(name = "dependency_type") + private Integer dependencyType; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "schedule_identifier", nullable = false) + private ProjectSchedule schedule; +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleGroup.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleGroup.java new file mode 100644 index 0000000..15e902e --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleGroup.java @@ -0,0 +1,47 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Entity +@Table(name = "project_schedule_group") +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProjectScheduleGroup { + + @Id + @GeneratedValue + @JdbcTypeCode(SqlTypes.UUID) + @Column(name = "id") + private UUID id; + + @Column(name = "group_key", nullable = false) + private String groupKey; + + @Column(name = "group_name") + private String groupName; + + @Column(name = "color") + private String color; + + @ElementCollection + @CollectionTable( + name = "project_schedule_group_task", + joinColumns = @JoinColumn(name = "group_id") + ) + @Column(name = "task_id") + @Builder.Default + private List taskIds = new ArrayList<>(); + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "schedule_identifier", nullable = false) + private ProjectSchedule schedule; +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleTask.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleTask.java new file mode 100644 index 0000000..b799c66 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/ProjectScheduleTask.java @@ -0,0 +1,54 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name = "project_schedule_task") +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProjectScheduleTask { + + @Id + @Column(name = "id") + private Long id; + + @Column(name = "parent_id") + private Long parentId; + + @Column(name = "task_name") + private String taskName; + + @Column(name = "task_duration") + private Double taskDuration; + + @Column(name = "task_predecessor") + private String taskPredecessor; + + @Column(name = "dependency_type") + private Integer dependencyType; + + @Column(name = "task_colour") + private String taskColour; + + @Column(name = "delay_duration") + private Double delayDuration; + + @Column(name = "task_description", columnDefinition = "TEXT") + private String taskDescription; + + @Column(name = "task_start") + private String taskStart; + + @Column(name = "task_end") + private String taskEnd; + + @Column(name = "milestone_task") + private Boolean milestoneTask; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "schedule_identifier", nullable = false) + private ProjectSchedule schedule; +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Risks.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Risks.java new file mode 100644 index 0000000..224a914 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Risks.java @@ -0,0 +1,91 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "risks") +public class Risks { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "risk_identifier", updatable = false, nullable = false) + private UUID riskIdentifier; + + @Column(name = "risk_title", nullable = false) + private String riskTitle; + + @Column(name = "risk_probability") + private Integer riskProbability; + + @Column(name = "gross_risk_value", precision = 15, scale = 2) + private BigDecimal grossRiskValue; + + @Column(name = "probable_risk_value", precision = 15, scale = 2) + private BigDecimal probableRiskValue; + + @Column(name = "probable_risk_value_in_usd", precision = 15, scale = 2) + private BigDecimal probableRiskValueInUSD; + + @Column(name = "risk_impact") + private String riskImpact; + + @Column(name = "risk_owner") + private String riskOwner; + + @Column(name = "risk_description", columnDefinition = "TEXT") + private String riskDescription; + + @Column(name = "financial_risk") + private Boolean financialRisk; + + @Column(name = "risk_created_date") + private LocalDateTime riskCreatedDate; + + @Column(name = "risk_options_select_id") + private String riskOptionsSelectId; + + @Column(name = "risk_status") + private String riskStatus; + + @Column(name = "risk_age") + private Integer riskAge; + + @Column(name = "effected_sprint_id") + private String effectedSprintId; + + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; + + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + // @Column(name = "project_identifier", insertable = false, updatable = false) + // private UUID projectIdentifier; + + @Column(name = "project_identifier") + private UUID projectIdentifier; + + @PrePersist + protected void onCreate() { + createdAt = LocalDateTime.now(); + updatedAt = LocalDateTime.now(); + if (riskCreatedDate == null) { + riskCreatedDate = LocalDateTime.now(); + } + } + + @PreUpdate + protected void onUpdate() { + updatedAt = LocalDateTime.now(); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Role.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Role.java new file mode 100644 index 0000000..914662c --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/Role.java @@ -0,0 +1,30 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +@Entity +@Table(name = "crm_role") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Role { + + @Id + @JdbcTypeCode(SqlTypes.UUID) + private UUID id; + + @JdbcTypeCode(SqlTypes.UUID) + private UUID accountId; + + private String role; +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/WorkingDaysDetailsEntity.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/WorkingDaysDetailsEntity.java new file mode 100644 index 0000000..8c15caa --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/WorkingDaysDetailsEntity.java @@ -0,0 +1,34 @@ +package com.ikon.projectmanagement.entity; + +import java.util.UUID; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name = "working_days_details") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WorkingDaysDetailsEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "working_id", nullable = false) + @ToString.Exclude + @EqualsAndHashCode.Exclude + private WorkingDaysEntity workingDaysEntity; + + @Column(name = "year") + private String year; + + @Column(name = "month", nullable = false) + private String month; + + @Column(name = "working_days") + private Integer workingDays; +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/WorkingDaysEntity.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/WorkingDaysEntity.java new file mode 100644 index 0000000..4d584d3 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/entity/WorkingDaysEntity.java @@ -0,0 +1,36 @@ +package com.ikon.projectmanagement.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +@Entity +@Table(name = "working_days") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WorkingDaysEntity { + + @Id + @Column(name = "working_id") + private UUID workingId; + + @Column(name = "account_identifier") + private UUID accountIdentifier; + + @OneToMany(mappedBy = "workingDaysEntity", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + @MapKey(name = "month") + @Builder.Default + @ToString.Exclude + @EqualsAndHashCode.Exclude + private Map workingDaysDetails = new HashMap<>(); + + public void addWorkingDaysDetail(WorkingDaysDetailsEntity detail) { + detail.setWorkingDaysEntity(this); + this.workingDaysDetails.put(detail.getMonth(), detail); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/EmployeeMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/EmployeeMapper.java new file mode 100644 index 0000000..99c0dfb --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/EmployeeMapper.java @@ -0,0 +1,79 @@ +package com.ikon.projectmanagement.mapper; + +import com.ikon.projectmanagement.dto.request.EmployeeRequestDto; +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; +import com.ikon.projectmanagement.entity.Employee; +import org.springframework.stereotype.Component; + +/** + * Mapper for converting between Employee entity and DTO objects. + * Handles bidirectional mapping for request and response DTOs. + */ +@Component +public class EmployeeMapper { + + /** + * Convert Employee entity to response DTO + */ + public EmployeeResponseDto toResponseDto(Employee employee) { + if (employee == null) { + return null; + } + return EmployeeResponseDto.builder() + .empId(employee.getEmpId()) + .accountId(employee.getAccountId()) + .name(employee.getName()) + .email(employee.getEmail()) + .organizationEmail(employee.getOrganizationEmail()) + .role(employee.getRole()) + .grade(employee.getGrade()) + .active(employee.getActive()) + .build(); + } + + /** + * Convert request DTO to Employee entity + */ + public Employee toEntity(EmployeeRequestDto dto) { + if (dto == null) { + return null; + } + return Employee.builder() + .empId(dto.getEmpId()) + .name(dto.getName()) + .email(dto.getEmail()) + .organizationEmail(dto.getOrganizationEmail()) + .role(dto.getRole()) + .grade(dto.getGrade()) + .active(dto.getActive()) + .build(); + } + + /** + * Update Employee entity from request DTO + */ + public Employee updateEntity(Employee employee, EmployeeRequestDto dto) { + if (employee == null || dto == null) { + return employee; + } + if (dto.getName() != null) { + employee.setName(dto.getName()); + } + if (dto.getEmail() != null) { + employee.setEmail(dto.getEmail()); + } + if (dto.getOrganizationEmail() != null) { + employee.setOrganizationEmail(dto.getOrganizationEmail()); + } + if (dto.getRole() != null) { + employee.setRole(dto.getRole()); + } + if (dto.getGrade() != null) { + employee.setGrade(dto.getGrade()); + } + if (dto.getActive() != null) { + employee.setActive(dto.getActive()); + } + return employee; + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/GradeMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/GradeMapper.java new file mode 100644 index 0000000..ef32f63 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/GradeMapper.java @@ -0,0 +1,60 @@ +package com.ikon.projectmanagement.mapper; + +import java.util.UUID; + +import com.ikon.projectmanagement.dto.request.GradeRequestDto; +import com.ikon.projectmanagement.dto.response.GradeResponseDto; +import com.ikon.projectmanagement.entity.Grade; +import org.springframework.stereotype.Component; + +/** + * Mapper for converting between Grade entity and DTO objects. + * Handles bidirectional mapping for request and response DTOs. + */ +@Component +public class GradeMapper { + + /** + * Convert Grade entity to response DTO + */ + public GradeResponseDto toResponseDto(Grade grade) { + if (grade == null) { + return null; + } + return GradeResponseDto.builder() + .id(grade.getId()) + .accountId(grade.getAccountId()) + .grade(grade.getGrade()) + .build(); + } + + /** + * Convert request DTO to Grade entity + */ + public Grade toEntity(GradeRequestDto dto) { + if (dto == null) { + return null; + } + // Grade.id has no @GeneratedValue, so the PK must be supplied here or the + // insert fails with a null primary key. Honour a client-supplied id, else + // generate one. accountId is carried through from the request. + return Grade.builder() + .id(dto.getId() != null ? dto.getId() : UUID.randomUUID()) + .accountId(dto.getAccountId()) + .grade(dto.getGrade()) + .build(); + } + + /** + * Update Grade entity from request DTO + */ + public Grade updateEntity(Grade grade, GradeRequestDto dto) { + if (grade == null || dto == null) { + return grade; + } + if (dto.getGrade() != null) { + grade.setGrade(dto.getGrade()); + } + return grade; + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/IssueMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/IssueMapper.java new file mode 100644 index 0000000..6c5130e --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/IssueMapper.java @@ -0,0 +1,112 @@ +package com.ikon.projectmanagement.mapper; + +import org.springframework.stereotype.Component; + +import com.ikon.projectmanagement.dto.request.IssueCreateRequestDto; +import com.ikon.projectmanagement.dto.response.IssueResponseDto; +import com.ikon.projectmanagement.entity.Issue; + +@Component +public class IssueMapper { + + // ================= CREATE ================= + public Issue toEntity(IssueCreateRequestDto dto) { + Issue issue = new Issue(); + + issue.setIssueTitle(dto.getIssueTitle()); + issue.setIssueProbability(dto.getIssueProbability()); + issue.setGrossIssueValue(dto.getGrossIssueValue()); + issue.setProbableIssueValue(dto.getProbableIssueValue()); + issue.setProbableIssueValueInUSD(dto.getProbableIssueValueInUSD()); + issue.setIssueImpact(dto.getIssueImpact()); + issue.setIssueOwner(dto.getIssueOwner()); + issue.setIssueDescription(dto.getIssueDescription()); + issue.setMitigationAction(dto.getMitigationAction()); + issue.setFinancialIssue(dto.getFinancialIssue()); + issue.setIssueCreatedDate(dto.getIssueCreatedDate()); + issue.setIssueOptionsSelectId(dto.getIssueOptionsSelectId()); + issue.setIssueStatus(dto.getIssueStatus()); + issue.setIssueAge(dto.getIssueAge()); + issue.setEffectedSprintId(dto.getEffectedSprintId()); + issue.setProjectIdentifier(dto.getProjectIdentifier()); + + return issue; + } + + // ================= RESPONSE ================= + public IssueResponseDto toResponse(Issue issue) { + IssueResponseDto dto = new IssueResponseDto(); + + dto.setIssueId(issue.getIssueId()); + dto.setIssueTitle(issue.getIssueTitle()); + dto.setIssueProbability(issue.getIssueProbability()); + dto.setGrossIssueValue(issue.getGrossIssueValue()); + dto.setProbableIssueValue(issue.getProbableIssueValue()); + dto.setProbableIssueValueInUSD(issue.getProbableIssueValueInUSD()); + dto.setIssueImpact(issue.getIssueImpact()); + dto.setIssueOwner(issue.getIssueOwner()); + dto.setIssueDescription(issue.getIssueDescription()); + dto.setMitigationAction(issue.getMitigationAction()); + dto.setFinancialIssue(issue.getFinancialIssue()); + dto.setIssueCreatedDate(issue.getIssueCreatedDate()); + dto.setIssueOptionsSelectId(issue.getIssueOptionsSelectId()); + dto.setIssueStatus(issue.getIssueStatus()); + dto.setIssueAge(issue.getIssueAge()); + dto.setEffectedSprintId(issue.getEffectedSprintId()); + dto.setProjectIdentifier(issue.getProjectIdentifier()); + + return dto; + } + + // ================= UPDATE ================= + public void updateEntityFromDto(IssueCreateRequestDto dto, Issue issue) { + + if (dto.getIssueTitle() != null) + issue.setIssueTitle(dto.getIssueTitle()); + + if (dto.getIssueProbability() != null) + issue.setIssueProbability(dto.getIssueProbability()); + + if (dto.getGrossIssueValue() != null) + issue.setGrossIssueValue(dto.getGrossIssueValue()); + + if (dto.getProbableIssueValue() != null) + issue.setProbableIssueValue(dto.getProbableIssueValue()); + + if (dto.getProbableIssueValueInUSD() != null) + issue.setProbableIssueValueInUSD(dto.getProbableIssueValueInUSD()); + + if (dto.getIssueImpact() != null) + issue.setIssueImpact(dto.getIssueImpact()); + + if (dto.getIssueOwner() != null) + issue.setIssueOwner(dto.getIssueOwner()); + + if (dto.getIssueDescription() != null) + issue.setIssueDescription(dto.getIssueDescription()); + + if (dto.getMitigationAction() != null) + issue.setMitigationAction(dto.getMitigationAction()); + + if (dto.getFinancialIssue() != null) + issue.setFinancialIssue(dto.getFinancialIssue()); + + if (dto.getIssueCreatedDate() != null) + issue.setIssueCreatedDate(dto.getIssueCreatedDate()); + + if (dto.getIssueOptionsSelectId() != null) + issue.setIssueOptionsSelectId(dto.getIssueOptionsSelectId()); + + if (dto.getIssueStatus() != null) + issue.setIssueStatus(dto.getIssueStatus()); + + if (dto.getIssueAge() != null) + issue.setIssueAge(dto.getIssueAge()); + + if (dto.getEffectedSprintId() != null) + issue.setEffectedSprintId(dto.getEffectedSprintId()); + + if (dto.getProjectIdentifier() != null) + issue.setProjectIdentifier(dto.getProjectIdentifier()); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/MeetingMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/MeetingMapper.java new file mode 100644 index 0000000..af1b0ff --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/MeetingMapper.java @@ -0,0 +1,263 @@ +package com.ikon.projectmanagement.mapper; + +import com.ikon.projectmanagement.dto.request.*; +import com.ikon.projectmanagement.dto.response.MeetingResponseDTO; +import com.ikon.projectmanagement.entity.Meeting; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Component +public class MeetingMapper { + + // ================= DTO TO ENTITY ================= + + public Meeting toEntity(MeetingRequestDTO dto) { + Meeting meeting = new Meeting(); + + if (dto.getMeeting() != null) { + meeting.setTitle(dto.getMeeting().getTitle()); + meeting.setProjectName(dto.getMeeting().getProjectName()); + meeting.setPlace(dto.getMeeting().getPlace()); + meeting.setDate(parseDate(dto.getMeeting().getDate())); + meeting.setTime(dto.getMeeting().getTime()); + meeting.setDuration(dto.getMeeting().getDuration()); + meeting.setCalledBy(dto.getMeeting().getCalledBy()); + } + + if (dto.getAttendees() != null && dto.getAttendees().getAttendees() != null) { + meeting.setAttendees( + dto.getAttendees().getAttendees().stream() + .map(this::toAttendeeEntity) + .collect(Collectors.toList()) + ); + } + + if (dto.getAgenda() != null && dto.getAgenda().getAgenda() != null) { + meeting.setAgenda( + dto.getAgenda().getAgenda().stream() + .map(this::toAgendaItemEntity) + .collect(Collectors.toList()) + ); + } + + if (dto.getDecisions() != null && dto.getDecisions().getDecisions() != null) { + meeting.setDecisions(dto.getDecisions().getDecisions()); + } + + if (dto.getActions() != null && dto.getActions().getActions() != null) { + meeting.setActions( + dto.getActions().getActions().stream() + .map(this::toActionItemEntity) + .collect(Collectors.toList()) + ); + } + + if (dto.getOthers() != null) { + meeting.setNotes(dto.getOthers().getNotes()); + } + + if (dto.getProjectIdentifier() != null) { + meeting.setProjectIdentifier(dto.getProjectIdentifier()); + } + + meeting.setStatus(dto.getStatus()); + + return meeting; + } + + // ================= UPDATE ENTITY FROM DTO ================= + + public void updateEntityFromDTO(Meeting existing, MeetingRequestDTO dto) { + + if (dto.getMeeting() != null) { + existing.setTitle(dto.getMeeting().getTitle()); + existing.setProjectName(dto.getMeeting().getProjectName()); + existing.setPlace(dto.getMeeting().getPlace()); + existing.setDate(parseDate(dto.getMeeting().getDate())); + existing.setTime(dto.getMeeting().getTime()); + existing.setDuration(dto.getMeeting().getDuration()); + existing.setCalledBy(dto.getMeeting().getCalledBy()); + } + + if (dto.getAttendees() != null && dto.getAttendees().getAttendees() != null) { + existing.setAttendees( + dto.getAttendees().getAttendees().stream() + .map(this::toAttendeeEntity) + .collect(Collectors.toList()) + ); + } + + if (dto.getAgenda() != null && dto.getAgenda().getAgenda() != null) { + existing.setAgenda( + dto.getAgenda().getAgenda().stream() + .map(this::toAgendaItemEntity) + .collect(Collectors.toList()) + ); + } + + if (dto.getDecisions() != null && dto.getDecisions().getDecisions() != null) { + existing.setDecisions(dto.getDecisions().getDecisions()); + } + + if (dto.getActions() != null && dto.getActions().getActions() != null) { + existing.setActions( + dto.getActions().getActions().stream() + .map(this::toActionItemEntity) + .collect(Collectors.toList()) + ); + } + + if (dto.getOthers() != null) { + existing.setNotes(dto.getOthers().getNotes()); + } + + if (dto.getProjectIdentifier() != null) { + existing.setProjectIdentifier(dto.getProjectIdentifier()); + } + + existing.setStatus(dto.getStatus()); + } + + // ================= ENTITY TO DTO ================= + + public MeetingResponseDTO toResponseDTO(Meeting meeting) { + MeetingResponseDTO dto = new MeetingResponseDTO(); + + dto.setId(meeting.getId()); + + MeetingDetailsDTO detailsDTO = new MeetingDetailsDTO(); + detailsDTO.setTitle(meeting.getTitle()); + detailsDTO.setProjectName(meeting.getProjectName()); + detailsDTO.setPlace(meeting.getPlace()); + detailsDTO.setDate(formatDate(meeting.getDate())); + detailsDTO.setTime(meeting.getTime()); + detailsDTO.setDuration(meeting.getDuration()); + detailsDTO.setCalledBy(meeting.getCalledBy()); + dto.setMeeting(detailsDTO); + + AttendeesWrapperDTO attendeesWrapper = new AttendeesWrapperDTO(); + attendeesWrapper.setAttendees( + meeting.getAttendees() != null + ? meeting.getAttendees().stream() + .map(this::toAttendeeDTO) + .collect(Collectors.toList()) + : Collections.emptyList() + ); + dto.setAttendees(attendeesWrapper); + + AgendaWrapperDTO agendaWrapper = new AgendaWrapperDTO(); + agendaWrapper.setAgenda( + meeting.getAgenda() != null + ? meeting.getAgenda().stream() + .map(this::toAgendaItemDTO) + .collect(Collectors.toList()) + : Collections.emptyList() + ); + dto.setAgenda(agendaWrapper); + + DecisionsWrapperDTO decisionsWrapper = new DecisionsWrapperDTO(); + decisionsWrapper.setDecisions( + meeting.getDecisions() != null + ? meeting.getDecisions() + : Collections.emptyList() + ); + dto.setDecisions(decisionsWrapper); + + ActionsWrapperDTO actionsWrapper = new ActionsWrapperDTO(); + actionsWrapper.setActions( + meeting.getActions() != null + ? meeting.getActions().stream() + .map(this::toActionItemDTO) + .collect(Collectors.toList()) + : Collections.emptyList() + ); + dto.setActions(actionsWrapper); + + OthersDTO othersDTO = new OthersDTO(); + othersDTO.setNotes(meeting.getNotes()); + dto.setOthers(othersDTO); + + if (meeting.getProjectIdentifier() != null) { + dto.setProjectIdentifier(meeting.getProjectIdentifier()); + } + + dto.setStatus(meeting.getStatus()); + dto.setCreatedAt(meeting.getCreatedAt()); + dto.setUpdatedAt(meeting.getUpdatedAt()); + + return dto; + } + + // ================= LIST MAPPING ================= + + public List toResponseDTOList(List meetings) { + return meetings.stream() + .map(this::toResponseDTO) + .collect(Collectors.toList()); + } + + // ================= PRIVATE HELPERS ================= + + private LocalDate parseDate(String dateStr) { + if (dateStr == null || dateStr.isBlank()) return null; + try { + return LocalDate.parse(dateStr); + } catch (Exception e) { + return null; + } + } + + private String formatDate(LocalDate date) { + return date != null ? date.toString() : null; + } + + private Meeting.Attendee toAttendeeEntity(AttendeeDTO dto) { + Meeting.Attendee attendee = new Meeting.Attendee(); + attendee.setName(dto.getName()); + attendee.setRole(dto.getRole()); + attendee.setContact(dto.getContact()); + return attendee; + } + + private AttendeeDTO toAttendeeDTO(Meeting.Attendee attendee) { + AttendeeDTO dto = new AttendeeDTO(); + dto.setName(attendee.getName()); + dto.setRole(attendee.getRole()); + dto.setContact(attendee.getContact()); + return dto; + } + + private Meeting.AgendaItem toAgendaItemEntity(AgendaItemDTO dto) { + Meeting.AgendaItem agendaItem = new Meeting.AgendaItem(); + agendaItem.setItem(dto.getItem()); + agendaItem.setOwner(dto.getOwner()); + return agendaItem; + } + + private AgendaItemDTO toAgendaItemDTO(Meeting.AgendaItem agendaItem) { + AgendaItemDTO dto = new AgendaItemDTO(); + dto.setItem(agendaItem.getItem()); + dto.setOwner(agendaItem.getOwner()); + return dto; + } + + private Meeting.ActionItem toActionItemEntity(ActionItemDTO dto) { + Meeting.ActionItem actionItem = new Meeting.ActionItem(); + actionItem.setItem(dto.getItem()); + actionItem.setResponsible(dto.getResponsible()); + actionItem.setDueDate(parseDate(dto.getDueDate())); + return actionItem; + } + + private ActionItemDTO toActionItemDTO(Meeting.ActionItem actionItem) { + ActionItemDTO dto = new ActionItemDTO(); + dto.setItem(actionItem.getItem()); + dto.setResponsible(actionItem.getResponsible()); + dto.setDueDate(formatDate(actionItem.getDueDate())); + return dto; + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProductOfProjectMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProductOfProjectMapper.java new file mode 100644 index 0000000..9750c5a --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProductOfProjectMapper.java @@ -0,0 +1,198 @@ +package com.ikon.projectmanagement.mapper; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import org.springframework.stereotype.Component; + +import com.ikon.projectmanagement.dto.request.ProductOfProjectRequestDto; +import com.ikon.projectmanagement.dto.response.ProductExpenseResponseDto; +import com.ikon.projectmanagement.dto.response.ProductOfProjectResponseDto; +import com.ikon.projectmanagement.dto.response.ProductPSResourceAllocationResponseDto; +import com.ikon.projectmanagement.entity.ProductOfProject; +import com.ikon.projectmanagement.entity.ProductOfProjectExpenseDetail; +import com.ikon.projectmanagement.entity.ProductPSResourceAllocation; + +@Component +public class ProductOfProjectMapper { + + public ProductOfProject toEntity(ProductOfProjectRequestDto dto) { + if (dto == null) + return null; + + ProductOfProject product = new ProductOfProject(); + + product.setProjectIdentifier(dto.getProjectIdentifier()); + product.setProjectName(dto.getProjectName()); + product.setProjectManager(dto.getProjectManager()); + product.setAccountId(dto.getAccountId()); + product.setLeadIdentifier(dto.getLeadIdentifier()); + product.setProductStatus(dto.getProductStatus()); + product.setProjectStatus(dto.getProjectStatus()); + product.setProductType(dto.getProductType()); + product.setProductDescription(dto.getProductDescription()); + product.setDiscountPercent(dto.getDiscountPercent()); + + if (dto.getExpenseDetails() != null && !dto.getExpenseDetails().isEmpty()) { + + Map expenseMap = new HashMap<>(); + + for (Entry entry : dto.getExpenseDetails().entrySet()) { + + UUID expenseId = entry.getKey(); + ProductExpenseResponseDto expDto = entry.getValue(); + + ProductOfProjectExpenseDetail exp = toExpenseEntity(expDto); + exp.setId(expenseId); + exp.setProductPS(product); + + expenseMap.put(expenseId, exp); + } + + product.setExpenseDetails(expenseMap); + } + + return product; + } + + public ProductOfProjectResponseDto toResponse(ProductOfProject entity) { + if (entity == null) + return null; + + ProductOfProjectResponseDto dto = new ProductOfProjectResponseDto(); + + dto.setProductIdentifier(entity.getProductIdentifier()); + dto.setProjectIdentifier(entity.getProjectIdentifier()); + dto.setProjectName(entity.getProjectName()); + dto.setProjectManager(entity.getProjectManager()); + dto.setAccountId(entity.getAccountId()); + dto.setLeadIdentifier(entity.getLeadIdentifier()); + dto.setProductStatus(entity.getProductStatus()); + dto.setProjectStatus(entity.getProjectStatus()); + dto.setProductType(entity.getProductType()); + dto.setProductDescription(entity.getProductDescription()); + dto.setDiscountPercent(entity.getDiscountPercent()); + dto.setCreatedOn(entity.getCreatedOn()); + dto.setUpdatedOn(entity.getUpdatedOn()); + dto.setCreatedBy(entity.getCreatedBy()); + dto.setUpdatedBy(entity.getUpdatedBy()); + + if (entity.getExpenseDetails() != null && !entity.getExpenseDetails().isEmpty()) { + + Map expenseDtos = new HashMap<>(); + + for (Map.Entry entry : entity.getExpenseDetails().entrySet()) { + + ProductOfProjectExpenseDetail exp = entry.getValue(); + + ProductExpenseResponseDto expDto = new ProductExpenseResponseDto(); + expDto.setExpenseName(exp.getExpenseName()); + expDto.setLocation(exp.getLocation()); + expDto.setCurrency(exp.getCurrency()); + expDto.setCost(exp.getCost()); + expDto.setQuantity(exp.getQuantity()); + expDto.setTotalCost(exp.getTotalCost()); + expDto.setRemarks(exp.getRemarks()); + + expenseDtos.put(entry.getKey(), expDto); + } + + dto.setExpenseDetails(expenseDtos); + } + + return dto; + } + + public void updateEntity(ProductOfProject entity, ProductOfProjectRequestDto dto) { + if (dto == null || entity == null) + return; + + if (dto.getProjectIdentifier() != null) + entity.setProjectIdentifier(dto.getProjectIdentifier()); + + if (dto.getProjectName() != null) + entity.setProjectName(dto.getProjectName()); + + if (dto.getProjectManager() != null) + entity.setProjectManager(dto.getProjectManager()); + + if (dto.getLeadIdentifier() != null) + entity.setLeadIdentifier(dto.getLeadIdentifier()); + + if (dto.getProductStatus() != null) + entity.setProductStatus(dto.getProductStatus()); + + if (dto.getProjectStatus() != null) + entity.setProjectStatus(dto.getProjectStatus()); + + if (dto.getProductType() != null) + entity.setProductType(dto.getProductType()); + + if (dto.getProductDescription() != null) + entity.setProductDescription(dto.getProductDescription()); + + if (dto.getDiscountPercent() != null) + entity.setDiscountPercent(dto.getDiscountPercent()); + + } + + public ProductOfProjectExpenseDetail toExpenseEntity(ProductExpenseResponseDto expDto) { + if (expDto == null) + return null; + + return ProductOfProjectExpenseDetail.builder() + .expenseName(expDto.getExpenseName()) + .location(expDto.getLocation()) + .currency(expDto.getCurrency()) + .cost(expDto.getCost()) + .quantity(expDto.getQuantity()) + .totalCost(expDto.getTotalCost()) + .remarks(expDto.getRemarks()) + .build(); + } + + public void updateExpenseEntity(ProductOfProjectExpenseDetail entity, + ProductExpenseResponseDto expenseDto) { + + if (entity == null || expenseDto == null) + return; + + if (expenseDto.getExpenseName() != null) + entity.setExpenseName(expenseDto.getExpenseName()); + + if (expenseDto.getLocation() != null) + entity.setLocation(expenseDto.getLocation()); + + if (expenseDto.getCurrency() != null) + entity.setCurrency(expenseDto.getCurrency()); + + if (expenseDto.getCost() != null) + entity.setCost(expenseDto.getCost()); + + if (expenseDto.getQuantity() != null) + entity.setQuantity(expenseDto.getQuantity()); + + if (expenseDto.getTotalCost() != null) + entity.setTotalCost(expenseDto.getTotalCost()); + + if (expenseDto.getRemarks() != null) + entity.setRemarks(expenseDto.getRemarks()); + } + + private ProductPSResourceAllocationResponseDto toResourceAllocationResponseDto(ProductPSResourceAllocation allocation) { + ProductPSResourceAllocationResponseDto dto = new ProductPSResourceAllocationResponseDto(); + dto.setId(allocation.getId()); + dto.setResourceType(allocation.getResourceType()); + dto.setRole(allocation.getRole()); + dto.setGradeId(allocation.getGradeId()); + dto.setEmployeeName(allocation.getEmployeeName()); + dto.setTaskName(allocation.getTaskName()); + dto.setResourceId(allocation.getResourceId()); + dto.setTaskId(allocation.getTaskId()); + dto.setAllocation(allocation.getAllocation()); + dto.setDetailedAllocation(allocation.getDetailedAllocation()); + return dto; + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProductResourceAllocationMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProductResourceAllocationMapper.java new file mode 100644 index 0000000..f08371e --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProductResourceAllocationMapper.java @@ -0,0 +1,74 @@ +package com.ikon.projectmanagement.mapper; + +import java.util.HashMap; + +import org.springframework.stereotype.Component; + +import com.ikon.projectmanagement.dto.request.ProductPSResourceAllocationRequestDto; +import com.ikon.projectmanagement.dto.response.ProductPSResourceAllocationResponseDto; +import com.ikon.projectmanagement.entity.ProductOfProject; +import com.ikon.projectmanagement.entity.ProductPSResourceAllocation; + +@Component +public class ProductResourceAllocationMapper { + + public ProductPSResourceAllocationResponseDto toResponse(ProductPSResourceAllocation entity) { + if (entity == null) + return null; + + ProductPSResourceAllocationResponseDto dto = new ProductPSResourceAllocationResponseDto(); + dto.setId(entity.getId()); + dto.setResourceType(entity.getResourceType()); + dto.setRole(entity.getRole()); + dto.setGradeId(entity.getGradeId()); + dto.setEmployeeName(entity.getEmployeeName()); + dto.setTaskName(entity.getTaskName()); + dto.setResourceId(entity.getResourceId()); + dto.setTaskId(entity.getTaskId()); + dto.setAllocation(entity.getAllocation()); + dto.setDetailedAllocation(entity.getDetailedAllocation()); + return dto; + } + + public ProductPSResourceAllocation toEntity(ProductPSResourceAllocationRequestDto dto, ProductOfProject product) { + if (dto == null) + return null; + + ProductPSResourceAllocation allocation = new ProductPSResourceAllocation(); + allocation.setResourceType(dto.getResourceType()); + allocation.setRole(dto.getRole()); + allocation.setGradeId(dto.getGradeId()); + allocation.setEmployeeName(dto.getEmployeeName()); + allocation.setTaskName(dto.getTaskName()); + allocation.setResourceId(dto.getResourceId()); + allocation.setTaskId(dto.getTaskId()); + allocation.setAllocation(dto.getAllocation() != null ? dto.getAllocation() : new HashMap<>()); + allocation.setDetailedAllocation(dto.getDetailedAllocation() != null ? dto.getDetailedAllocation() : new HashMap<>()); + allocation.setProductPS(product); + return allocation; + } + + public void updateEntity(ProductPSResourceAllocation entity, ProductPSResourceAllocationRequestDto dto) { + if (entity == null || dto == null) + return; + + if (dto.getResourceType() != null) + entity.setResourceType(dto.getResourceType()); + if (dto.getRole() != null) + entity.setRole(dto.getRole()); + if (dto.getGradeId() != null) + entity.setGradeId(dto.getGradeId()); + if (dto.getEmployeeName() != null) + entity.setEmployeeName(dto.getEmployeeName()); + if (dto.getTaskName() != null) + entity.setTaskName(dto.getTaskName()); + if (dto.getResourceId() != null) + entity.setResourceId(dto.getResourceId()); + if (dto.getTaskId() != null) + entity.setTaskId(dto.getTaskId()); + if (dto.getAllocation() != null) + entity.setAllocation(dto.getAllocation()); + if (dto.getDetailedAllocation() != null) + entity.setDetailedAllocation(dto.getDetailedAllocation()); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProjectMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProjectMapper.java new file mode 100644 index 0000000..f0e2b73 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ProjectMapper.java @@ -0,0 +1,118 @@ +package com.ikon.projectmanagement.mapper; + +import org.springframework.stereotype.Component; + +import com.ikon.projectmanagement.dto.request.ProductExpenseRequestDto; +import com.ikon.projectmanagement.dto.request.ProjectRequestDto; +import com.ikon.projectmanagement.dto.response.ProjectResponseDto; +import com.ikon.projectmanagement.entity.ProductOfProjectExpenseDetail; +import com.ikon.projectmanagement.entity.Project; + +@Component +public class ProjectMapper { + + public Project toEntity(ProjectRequestDto dto) { + Project project = new Project(); + mapCommonFields(dto, project); + return project; + } + + public void updateEntityFromDto(ProjectRequestDto dto, Project project) { + mapCommonFields(dto, project); + } + + private void mapCommonFields(ProjectRequestDto dto, Project project) { + + project.setProjectName(dto.getProjectName()); + project.setProjectManager(dto.getProjectManager()); + project.setProjectStatus(dto.getProjectStatus()); + project.setProjectNumber(dto.getProjectNumber()); + project.setParentProjectNo(dto.getParentProjectNo()); + project.setContractNumber(dto.getContractNumber()); + project.setProjectClient(dto.getProjectClient()); + project.setProjectCity(dto.getProjectCity()); + project.setProjectCountry(dto.getProjectCountry()); + project.setCurrency(dto.getCurrency()); + project.setProjectImage(dto.getProjectImage()); + project.setContractUpload(dto.getContractUpload()); + project.setSource(dto.getSource()); + project.setProductType(dto.getProductType()); + project.setExpenses(dto.getExpenses()); + project.setFormattedActualRevenueIncludingVAT_deal(dto.getFormattedActualRevenueIncludingVAT_deal()); + project.setIsCompleted(dto.getIsCompleted()); + project.setGroupNotExist(dto.getGroupNotExist()); + project.setIsDebtRevenue_deal(dto.getIsDebtRevenue_deal()); + project.setProjectDescription(dto.getProjectDescription()); + + project.setProjectStartDate(dto.getProjectStartDate()); + project.setContractedStartDate(dto.getContractedStartDate()); + project.setContractedEndDate(dto.getContractedEndDate()); + + project.setProjectTeam(dto.getProjectTeam()); + project.setProjectTeamUnderProjectManager(dto.getProjectTeamUnderProjectManager()); + project.setProjectTeamUnderProjectManagerDelegates(dto.getProjectTeamUnderProjectManagerDelegates()); + + project.setParticipants(dto.getParticipants()); + project.setContractedProductIdentifierWiseDataObj(dto.getContractedProductIdentifierWiseDataObj()); + + } + + public ProjectResponseDto toResponse(Project project) { + + if (project == null) + return null; + + ProjectResponseDto dto = new ProjectResponseDto(); + + dto.setProjectIdentifier(project.getProjectIdentifier()); + dto.setProjectName(project.getProjectName()); + dto.setProjectManager(project.getProjectManager()); + dto.setProjectStatus(project.getProjectStatus()); + dto.setProjectNumber(project.getProjectNumber()); + dto.setParentProjectNo(project.getParentProjectNo()); + dto.setContractNumber(project.getContractNumber()); + + dto.setProjectClient(project.getProjectClient()); + dto.setProjectCity(project.getProjectCity()); + dto.setProjectCountry(project.getProjectCountry()); + dto.setCurrency(project.getCurrency()); + + dto.setProjectImage(project.getProjectImage()); + dto.setContractUpload(project.getContractUpload()); + + dto.setSource(project.getSource()); + dto.setProductType(project.getProductType()); + dto.setExpenses(project.getExpenses()); + + dto.setFormattedActualRevenueIncludingVAT_deal( + project.getFormattedActualRevenueIncludingVAT_deal()); + dto.setIsCompleted(project.getIsCompleted()); + dto.setGroupNotExist(project.getGroupNotExist()); + dto.setIsDebtRevenue_deal(project.getIsDebtRevenue_deal()); + + dto.setProjectDescription(project.getProjectDescription()); + + dto.setProjectStartDate(project.getProjectStartDate()); + dto.setContractedStartDate(project.getContractedStartDate()); + dto.setContractedEndDate(project.getContractedEndDate()); + + dto.setProjectTeam(project.getProjectTeam()); + dto.setProjectTeamUnderProjectManager( + project.getProjectTeamUnderProjectManager()); + dto.setProjectTeamUnderProjectManagerDelegates( + project.getProjectTeamUnderProjectManagerDelegates()); + + dto.setParticipants(project.getParticipants()); + dto.setContractedProductIdentifierWiseDataObj( + project.getContractedProductIdentifierWiseDataObj()); + + if (project.getProduct() != null) { + dto.setProductIdentifier(project.getProduct().getProductIdentifier()); + dto.setProductType(project.getProduct().getProductType()); + } + + return dto; + } + + +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/RiskMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/RiskMapper.java new file mode 100644 index 0000000..f4e5114 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/RiskMapper.java @@ -0,0 +1,88 @@ +package com.ikon.projectmanagement.mapper; + +import org.springframework.stereotype.Component; + +import com.ikon.projectmanagement.dto.request.RiskCreateRequestDto; +import com.ikon.projectmanagement.dto.response.RiskResponseDto; +import com.ikon.projectmanagement.entity.Risks; + +@Component +public class RiskMapper { + + public Risks toEntity(RiskCreateRequestDto dto) { + Risks risk = new Risks(); + risk.setRiskTitle(dto.getRiskTitle()); + risk.setRiskProbability(dto.getRiskProbability()); + risk.setGrossRiskValue(dto.getGrossRiskValue()); + risk.setProbableRiskValue(dto.getProbableRiskValue()); + risk.setProbableRiskValueInUSD(dto.getProbableRiskValueInUSD()); + risk.setRiskImpact(dto.getRiskImpact()); + risk.setRiskOwner(dto.getRiskOwner()); + risk.setRiskDescription(dto.getRiskDescription()); + risk.setFinancialRisk(dto.getFinancialRisk()); + risk.setRiskCreatedDate(dto.getRiskCreatedDate()); + risk.setRiskOptionsSelectId(dto.getRiskOptionsSelectId()); + risk.setRiskStatus(dto.getRiskStatus()); + risk.setRiskAge(dto.getRiskAge()); + risk.setEffectedSprintId(dto.getEffectedSprintId()); + risk.setProjectIdentifier(dto.getProjectIdentifier()); + return risk; + } + + public RiskResponseDto toResponse(Risks risk) { + RiskResponseDto dto = new RiskResponseDto(); + dto.setRiskIdentifier(risk.getRiskIdentifier()); + dto.setRiskTitle(risk.getRiskTitle()); + dto.setRiskProbability(risk.getRiskProbability()); + dto.setGrossRiskValue(risk.getGrossRiskValue()); + dto.setProbableRiskValue(risk.getProbableRiskValue()); + dto.setProbableRiskValueInUSD(risk.getProbableRiskValueInUSD()); + dto.setRiskImpact(risk.getRiskImpact()); + dto.setRiskOwner(risk.getRiskOwner()); + dto.setRiskDescription(risk.getRiskDescription()); + dto.setFinancialRisk(risk.getFinancialRisk()); + dto.setRiskCreatedDate(risk.getRiskCreatedDate()); + dto.setRiskOptionsSelectId(risk.getRiskOptionsSelectId()); + dto.setRiskStatus(risk.getRiskStatus()); + dto.setRiskAge(risk.getRiskAge()); + dto.setEffectedSprintId(risk.getEffectedSprintId()); + // Now using plain UUID field instead of + // risk.getProject().getProjectIdentifier() + dto.setProjectIdentifier(risk.getProjectIdentifier()); + return dto; + } + + public void updateEntityFromDto(RiskCreateRequestDto dto, Risks risk) { + if (dto.getRiskTitle() != null) + risk.setRiskTitle(dto.getRiskTitle()); + if (dto.getRiskProbability() != null) + risk.setRiskProbability(dto.getRiskProbability()); + if (dto.getGrossRiskValue() != null) + risk.setGrossRiskValue(dto.getGrossRiskValue()); + if (dto.getProbableRiskValue() != null) + risk.setProbableRiskValue(dto.getProbableRiskValue()); + if (dto.getProbableRiskValueInUSD() != null) + risk.setProbableRiskValueInUSD(dto.getProbableRiskValueInUSD()); + if (dto.getRiskImpact() != null) + risk.setRiskImpact(dto.getRiskImpact()); + if (dto.getRiskOwner() != null) + risk.setRiskOwner(dto.getRiskOwner()); + if (dto.getRiskDescription() != null) + risk.setRiskDescription(dto.getRiskDescription()); + if (dto.getFinancialRisk() != null) + risk.setFinancialRisk(dto.getFinancialRisk()); + if (dto.getRiskCreatedDate() != null) + risk.setRiskCreatedDate(dto.getRiskCreatedDate()); + if (dto.getRiskOptionsSelectId() != null) + risk.setRiskOptionsSelectId(dto.getRiskOptionsSelectId()); + if (dto.getRiskStatus() != null) + risk.setRiskStatus(dto.getRiskStatus()); + if (dto.getRiskAge() != null) + risk.setRiskAge(dto.getRiskAge()); + if (dto.getEffectedSprintId() != null) + risk.setEffectedSprintId(dto.getEffectedSprintId()); + if (dto.getProjectIdentifier() != null) + risk.setProjectIdentifier(dto.getProjectIdentifier()); + } + +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/RoleMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/RoleMapper.java new file mode 100644 index 0000000..b4f98fc --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/RoleMapper.java @@ -0,0 +1,59 @@ +package com.ikon.projectmanagement.mapper; + +import java.util.UUID; + +import com.ikon.projectmanagement.dto.request.RoleRequestDto; +import com.ikon.projectmanagement.dto.response.RoleResponseDto; +import com.ikon.projectmanagement.entity.Role; +import org.springframework.stereotype.Component; + +/** + * Mapper for converting between Role entity and DTO objects. + * Handles bidirectional mapping for request and response DTOs. + */ +@Component +public class RoleMapper { + + /** + * Convert Role entity to response DTO + */ + public RoleResponseDto toResponseDto(Role role) { + if (role == null) { + return null; + } + return RoleResponseDto.builder() + .id(role.getId()) + .accountId(role.getAccountId()) + .role(role.getRole()) + .build(); + } + + /** + * Convert request DTO to Role entity + */ + public Role toEntity(RoleRequestDto dto) { + if (dto == null) { + return null; + } + // Role.id has no @GeneratedValue, so the PK must be supplied here or the + // insert fails with a null primary key. Honour a client-supplied id, else + // generate one. + return Role.builder() + .id(dto.getId() != null ? dto.getId() : UUID.randomUUID()) + .role(dto.getRole()) + .build(); + } + + /** + * Update Role entity from request DTO + */ + public Role updateEntity(Role role, RoleRequestDto dto) { + if (role == null || dto == null) { + return role; + } + if (dto.getRole() != null) { + role.setRole(dto.getRole()); + } + return role; + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ScheduleMapper.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ScheduleMapper.java new file mode 100644 index 0000000..025197a --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/mapper/ScheduleMapper.java @@ -0,0 +1,99 @@ +package com.ikon.projectmanagement.mapper; + +import com.ikon.projectmanagement.dto.request.ScheduleDependencyDto; +import com.ikon.projectmanagement.dto.request.ScheduleGroupDto; +import com.ikon.projectmanagement.dto.request.ScheduleTaskDto; +import com.ikon.projectmanagement.dto.response.ScheduleResponseDto; +import com.ikon.projectmanagement.entity.ProjectSchedule; +import com.ikon.projectmanagement.entity.ProjectScheduleDependency; +import com.ikon.projectmanagement.entity.ProjectScheduleGroup; +import com.ikon.projectmanagement.entity.ProjectScheduleTask; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ScheduleMapper { + + public ScheduleResponseDto toResponse(ProjectSchedule schedule) { + List tasks = new ArrayList<>(); + for (ProjectScheduleTask task : schedule.getTasks()) { + ScheduleTaskDto dto = new ScheduleTaskDto(); + dto.setId(task.getId()); + dto.setParentId(task.getParentId()); + dto.setTaskName(task.getTaskName()); + dto.setTaskDuration(task.getTaskDuration()); + dto.setTaskPredecessor(task.getTaskPredecessor()); + dto.setDependencyType(task.getDependencyType()); + dto.setTaskColour(task.getTaskColour()); + dto.setDelayDuration(task.getDelayDuration()); + dto.setTaskDescription(task.getTaskDescription()); + dto.setTaskStart(task.getTaskStart()); + dto.setTaskEnd(task.getTaskEnd()); + dto.setMilestoneTask(task.getMilestoneTask()); + tasks.add(dto); + } + + List dependencies = new ArrayList<>(); + for (ProjectScheduleDependency dep : schedule.getDependencies()) { + ScheduleDependencyDto dto = new ScheduleDependencyDto(); + dto.setId(dep.getId()); + dto.setPredecessorId(dep.getPredecessorId()); + dto.setDependencyType(dep.getDependencyType()); + dependencies.add(dto); + } + + Map groups = new LinkedHashMap<>(); + for (ProjectScheduleGroup g : schedule.getGroups()) { + ScheduleGroupDto dto = new ScheduleGroupDto(); + dto.setId(g.getGroupKey()); + dto.setGroupName(g.getGroupName()); + dto.setColor(g.getColor()); + dto.setTaskIds(new ArrayList<>(g.getTaskIds())); + groups.put(g.getGroupKey(), dto); + } + + return new ScheduleResponseDto(schedule.getProjectIdentifier(), schedule.getProductIdentifier(), tasks, dependencies, groups); + } + + public ProjectScheduleTask toTaskEntity(ScheduleTaskDto dto, ProjectSchedule schedule) { + ProjectScheduleTask task = new ProjectScheduleTask(); + task.setId(dto.getId()); + task.setParentId(dto.getParentId()); + task.setTaskName(dto.getTaskName()); + task.setTaskDuration(dto.getTaskDuration()); + task.setTaskPredecessor(dto.getTaskPredecessor()); + task.setDependencyType(dto.getDependencyType()); + task.setTaskColour(dto.getTaskColour()); + task.setDelayDuration(dto.getDelayDuration()); + task.setTaskDescription(dto.getTaskDescription()); + task.setTaskStart(dto.getTaskStart()); + task.setTaskEnd(dto.getTaskEnd()); + task.setMilestoneTask(dto.getMilestoneTask()); + task.setSchedule(schedule); + return task; + } + + public ProjectScheduleDependency toDependencyEntity(ScheduleDependencyDto dto, ProjectSchedule schedule) { + ProjectScheduleDependency dep = new ProjectScheduleDependency(); + dep.setId(dto.getId()); + dep.setPredecessorId(dto.getPredecessorId()); + dep.setDependencyType(dto.getDependencyType()); + dep.setSchedule(schedule); + return dep; + } + + public ProjectScheduleGroup toGroupEntity(String groupKey, ScheduleGroupDto dto, ProjectSchedule schedule) { + ProjectScheduleGroup g = new ProjectScheduleGroup(); + g.setGroupKey(groupKey); + g.setGroupName(dto.getGroupName()); + g.setColor(dto.getColor()); + g.setTaskIds(dto.getTaskIds() != null ? new ArrayList<>(dto.getTaskIds()) : new ArrayList<>()); + g.setSchedule(schedule); + return g; + } + +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/EmployeeRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/EmployeeRepository.java new file mode 100644 index 0000000..099919c --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/EmployeeRepository.java @@ -0,0 +1,12 @@ +package com.ikon.projectmanagement.repository; + +import com.ikon.projectmanagement.entity.Employee; +import java.util.Optional; +import java.util.UUID; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface EmployeeRepository extends JpaRepository { + Optional findByEmpId(String empId); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/FxRateRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/FxRateRepository.java new file mode 100644 index 0000000..706ca1f --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/FxRateRepository.java @@ -0,0 +1,26 @@ +package com.ikon.projectmanagement.repository; + +import java.util.Optional; +import java.util.UUID; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.ikon.projectmanagement.entity.FxRateEntity; + +@Repository +public interface FxRateRepository extends JpaRepository { + + @Query("SELECT f FROM FxRateEntity f LEFT JOIN FETCH f.fxRateDetails WHERE f.fxRateId = :id") + Optional findByIdWithDetails(@Param("id") UUID id); + + Optional findByAccountIdentifier(UUID accountIdentifier); + + @Query("SELECT f FROM FxRateEntity f JOIN f.fxRateDetails d WHERE d.year = :year") + Optional findByYear(@Param("year") String year); + + @Query("SELECT f FROM FxRateEntity f JOIN f.fxRateDetails d WHERE d.year = :year AND d.currency = :currency") + Optional findByYearAndCurrency(@Param("year") String year, @Param("currency") String currency); +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/GradeRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/GradeRepository.java new file mode 100644 index 0000000..a4d3435 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/GradeRepository.java @@ -0,0 +1,10 @@ +package com.ikon.projectmanagement.repository; + +import com.ikon.projectmanagement.entity.Grade; +import java.util.UUID; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface GradeRepository extends JpaRepository { +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/IssueRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/IssueRepository.java new file mode 100644 index 0000000..944727f --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/IssueRepository.java @@ -0,0 +1,16 @@ +package com.ikon.projectmanagement.repository; + +import java.util.List; +import java.util.UUID; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.ikon.projectmanagement.entity.Issue; + +@Repository +public interface IssueRepository extends JpaRepository { + List findByProjectIdentifier(UUID projectIdentifier); + + List findByIssueOwner(String issueOwner); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/MeetingRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/MeetingRepository.java new file mode 100644 index 0000000..8ac7720 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/MeetingRepository.java @@ -0,0 +1,16 @@ +package com.ikon.projectmanagement.repository; + +import com.ikon.projectmanagement.entity.Meeting; + +import org.apache.kafka.common.Uuid; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface MeetingRepository extends JpaRepository { + + List findByProjectIdentifier(UUID projectIdentifier); +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProductOfProjectRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProductOfProjectRepository.java new file mode 100644 index 0000000..68a10be --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProductOfProjectRepository.java @@ -0,0 +1,24 @@ +package com.ikon.projectmanagement.repository; + +import com.ikon.projectmanagement.entity.ProductOfProject; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ProductOfProjectRepository extends JpaRepository { + List findByAccountIdAndProjectIdentifier( + UUID accountId, + UUID projectIdentifier); + + Optional findByAccountIdAndProductIdentifier( + UUID accountId, + UUID productIdentifier); + + Optional findByAccountIdAndProjectIdentifierAndProductIdentifier(UUID accountId, UUID projectIdentifier, + UUID productIdentifier); +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProjectRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProjectRepository.java new file mode 100644 index 0000000..b77ca53 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProjectRepository.java @@ -0,0 +1,36 @@ +package com.ikon.projectmanagement.repository; + +import com.ikon.projectmanagement.dto.response.StatusWiseProjectResponseData; +import com.ikon.projectmanagement.entity.Project; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface ProjectRepository extends JpaRepository { + + List findByAccountId(UUID accountId); + + Optional getProjectByProjectIdentifier(UUID projectIdentifier); + + boolean existsByProjectIdentifier(UUID projectIdentifier); + + Optional findByProjectIdentifier(UUID projectIdentifier); + + Optional findByAccountIdAndProjectIdentifier(UUID accountId, UUID projectIdentifier); + + @Query(""" + SELECT new com.ikon.projectmanagement.dto.response.StatusWiseProjectResponseData ( + p.projectStatus, + COUNT(p) + )FROM Project p GROUP BY p.projectStatus + """) + List getProjectStatusCounts(); + + List findByProjectStatusIgnoreCase(String projectStatus); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProjectScheduleRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProjectScheduleRepository.java new file mode 100644 index 0000000..7051d1a --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/ProjectScheduleRepository.java @@ -0,0 +1,18 @@ +package com.ikon.projectmanagement.repository; + +import com.ikon.projectmanagement.entity.ProjectSchedule; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface ProjectScheduleRepository extends JpaRepository { + Optional findByAccountIdAndProjectIdentifier(UUID accountId, UUID projectIdentifier); + + Optional findByAccountIdAndProductIdentifier(UUID accountId, UUID productIdentifier); + + List findAllByAccountId(UUID accountId); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/RiskRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/RiskRepository.java new file mode 100644 index 0000000..1cf7c5c --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/RiskRepository.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.repository; + +import com.ikon.projectmanagement.entity.Risks; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface RiskRepository extends JpaRepository { + + List findByProjectIdentifier(UUID projectIdentifier); + + List findByRiskStatus(String riskStatus); + + List findByRiskOwner(String riskOwner); + + boolean existsByRiskTitleAndProjectIdentifier(String riskTitle, UUID projectIdentifier); + + Risks findByRiskIdentifierAndProjectIdentifier(UUID riskIdentifier, UUID projectIdentifier); +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/RoleRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/RoleRepository.java new file mode 100644 index 0000000..917173e --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/RoleRepository.java @@ -0,0 +1,10 @@ +package com.ikon.projectmanagement.repository; + +import com.ikon.projectmanagement.entity.Role; +import java.util.UUID; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface RoleRepository extends JpaRepository { +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/WorkingDaysRepository.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/WorkingDaysRepository.java new file mode 100644 index 0000000..99b963d --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/repository/WorkingDaysRepository.java @@ -0,0 +1,28 @@ +package com.ikon.projectmanagement.repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.ikon.projectmanagement.entity.WorkingDaysEntity; + +@Repository +public interface WorkingDaysRepository extends JpaRepository { + + @Query("SELECT w FROM WorkingDaysEntity w LEFT JOIN FETCH w.workingDaysDetails WHERE w.workingId = :id") + Optional findByIdWithDetails(@Param("id") UUID id); + + Optional findByAccountIdentifier(UUID accountIdentifier); + + List findAllByAccountIdentifier(UUID accountIdentifier); + + Optional findByWorkingId(UUID workingId); + + @Query("SELECT w FROM WorkingDaysEntity w JOIN w.workingDaysDetails d WHERE d.year = :year") + Optional findByYear(@Param("year") String year); +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/DashboardService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/DashboardService.java new file mode 100644 index 0000000..0117368 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/DashboardService.java @@ -0,0 +1,11 @@ +package com.ikon.projectmanagement.service; + +import java.util.List; + +import com.ikon.projectmanagement.dto.response.DashboardWidgetsResponseDto; +import com.ikon.projectmanagement.dto.response.StatusWiseProjectResponseData; + +public interface DashboardService { + DashboardWidgetsResponseDto getDashboardWidgetsData(); + List getStatusWiseProjectData(); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/EmployeeService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/EmployeeService.java new file mode 100644 index 0000000..08084d3 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/EmployeeService.java @@ -0,0 +1,33 @@ +package com.ikon.projectmanagement.service; + +import com.ikon.projectmanagement.dto.request.EmployeeRequestDto; +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; +import java.util.List; + +public interface EmployeeService { + + /** + * Retrieve all employees + */ + List getAllEmployees(); + + /** + * Retrieve employee by ID + */ + EmployeeResponseDto getEmployeeById(String id); + + /** + * Create a new employee + */ + EmployeeResponseDto createEmployee(EmployeeRequestDto dto); + + /** + * Update an existing employee + */ + EmployeeResponseDto updateEmployee(String id, EmployeeRequestDto dto); + + /** + * Delete an employee by ID + */ + void deleteEmployee(String id); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/FxRateService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/FxRateService.java new file mode 100644 index 0000000..898bafc --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/FxRateService.java @@ -0,0 +1,11 @@ +package com.ikon.projectmanagement.service; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import com.ikon.projectmanagement.dto.response.FxRateResponseDto; + +public interface FxRateService { + Page getAllFxRates(Pageable pageable); + + FxRateResponseDto getFxRateByYear(String year); +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/GradeService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/GradeService.java new file mode 100644 index 0000000..54083e4 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/GradeService.java @@ -0,0 +1,34 @@ +package com.ikon.projectmanagement.service; + +import com.ikon.projectmanagement.dto.request.GradeRequestDto; +import com.ikon.projectmanagement.dto.response.GradeResponseDto; +import java.util.List; +import java.util.UUID; + +public interface GradeService { + + /** + * Retrieve all grades + */ + List getAllGrades(); + + /** + * Retrieve grade by ID + */ + GradeResponseDto getGradeById(UUID id); + + /** + * Create a new grade + */ + GradeResponseDto createGrade(GradeRequestDto dto); + + /** + * Update an existing grade + */ + GradeResponseDto updateGrade(UUID id, GradeRequestDto dto); + + /** + * Delete a grade by ID + */ + void deleteGrade(UUID id); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportEmployeeService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportEmployeeService.java new file mode 100644 index 0000000..ada18d7 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportEmployeeService.java @@ -0,0 +1,10 @@ +package com.ikon.projectmanagement.service; + +import java.util.List; + +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; + +public interface ImportEmployeeService { + + List importEmployees(String accessToken); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportFxRateService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportFxRateService.java new file mode 100644 index 0000000..ae32833 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportFxRateService.java @@ -0,0 +1,10 @@ +package com.ikon.projectmanagement.service; + +import java.util.List; + +import com.ikon.projectmanagement.dto.response.FxRateDto; + +public interface ImportFxRateService { + + List importFxRates(String accessToken); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportGradeService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportGradeService.java new file mode 100644 index 0000000..44534e0 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportGradeService.java @@ -0,0 +1,10 @@ +package com.ikon.projectmanagement.service; + +import java.util.List; + +import com.ikon.projectmanagement.dto.response.GradeResponseDto; + +public interface ImportGradeService { + + List importGrades(String accessToken); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportRoleService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportRoleService.java new file mode 100644 index 0000000..c9fe2e8 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportRoleService.java @@ -0,0 +1,10 @@ +package com.ikon.projectmanagement.service; + +import java.util.List; + +import com.ikon.projectmanagement.dto.response.RoleResponseDto; + +public interface ImportRoleService { + + List importRoles(String accessToken); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportWorkingDayService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportWorkingDayService.java new file mode 100644 index 0000000..7ee1e6d --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ImportWorkingDayService.java @@ -0,0 +1,10 @@ +package com.ikon.projectmanagement.service; + +import java.util.List; + +import com.ikon.projectmanagement.dto.response.WorkingDayDto; + +public interface ImportWorkingDayService { + + List importWorkingDays(String accessToken); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/IssueService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/IssueService.java new file mode 100644 index 0000000..6c6eb66 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/IssueService.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.service; + +import com.ikon.projectmanagement.dto.request.IssueCreateRequestDto; +import com.ikon.projectmanagement.dto.request.RiskCreateRequestDto; +import com.ikon.projectmanagement.dto.response.IssueResponseDto; + +import java.util.List; +import java.util.UUID; + +public interface IssueService { + + IssueResponseDto createIssue(IssueCreateRequestDto issueCreateRequestDto); + + List getAllIssues(UUID projectIdentifier); + + + IssueResponseDto getIssueById(UUID issueId); + + IssueResponseDto updateIssue(UUID issueId, IssueCreateRequestDto issueCreateRequestDto); + + List getIssuesByProject(String projectIdentifier); +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/MeetingService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/MeetingService.java new file mode 100644 index 0000000..89db062 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/MeetingService.java @@ -0,0 +1,22 @@ +package com.ikon.projectmanagement.service; + +import com.ikon.projectmanagement.dto.request.MeetingRequestDTO; +import com.ikon.projectmanagement.dto.response.MeetingResponseDTO; + +import java.util.List; +import java.util.UUID; + +public interface MeetingService { + + MeetingResponseDTO createMeeting(MeetingRequestDTO meetingRequestDTO); + + List getAllMeetings(UUID projectIdentifier); + + List getMeetingsByProjectIdentifier(String projectIdentifier); + + MeetingResponseDTO getMeetingById(UUID meetingId); + + MeetingResponseDTO updateMeeting(UUID meetingId, MeetingRequestDTO meetingRequestDTO); + + void deleteMeeting(UUID meetingId); +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProductOfProjectService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProductOfProjectService.java new file mode 100644 index 0000000..dd0379d --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProductOfProjectService.java @@ -0,0 +1,27 @@ +package com.ikon.projectmanagement.service; + +import java.util.List; +import java.util.UUID; + +import com.ikon.projectmanagement.dto.request.ProductOfProjectRequestDto; +import com.ikon.projectmanagement.dto.response.ProductOfProjectResponseDto; + +public interface ProductOfProjectService { + + + List getProductsByProject(UUID projectIdentifier); + + ProductOfProjectResponseDto getProduct(UUID projectIdentifier, UUID productIdentifier); + + ProductOfProjectResponseDto updateProduct( + UUID projectIdentifier, + UUID productIdentifier, + ProductOfProjectRequestDto productDto + ); + + ProductOfProjectResponseDto transitionStatus( + UUID projectIdentifier, + UUID productIdentifier, + String targetStatus + ); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProductResourceAllocationService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProductResourceAllocationService.java new file mode 100644 index 0000000..b6ed177 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProductResourceAllocationService.java @@ -0,0 +1,20 @@ +package com.ikon.projectmanagement.service; + +import com.ikon.projectmanagement.dto.request.ProductPSResourceAllocationRequestDto; +import com.ikon.projectmanagement.dto.response.ProductPSResourceAllocationResponseDto; + +import java.util.List; +import java.util.UUID; + +public interface ProductResourceAllocationService { + + List getResourceAllocations(UUID productIdentifier); + + ProductPSResourceAllocationResponseDto getResourceAllocation(UUID productIdentifier, UUID allocationIdentifier); + + ProductPSResourceAllocationResponseDto createResourceAllocation(UUID productIdentifier, ProductPSResourceAllocationRequestDto dto); + + ProductPSResourceAllocationResponseDto updateResourceAllocation(UUID productIdentifier, UUID allocationIdentifier, ProductPSResourceAllocationRequestDto dto); + + void deleteResourceAllocation(UUID productIdentifier, UUID allocationIdentifier); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProjectService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProjectService.java new file mode 100644 index 0000000..4052f57 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ProjectService.java @@ -0,0 +1,21 @@ +package com.ikon.projectmanagement.service; + +import java.util.List; +import java.util.UUID; + +import com.ikon.projectmanagement.dto.request.ProjectRequestDto; +import com.ikon.projectmanagement.dto.response.ProjectResponseDto; +import com.ikon.projectmanagement.dto.response.ProjectTimelineResponseDto; + +public interface ProjectService { + + ProjectResponseDto createProject(ProjectRequestDto projectDto); + + List getAllProjects(); + + ProjectResponseDto getProjectByProjectIdentifier(UUID projectIdentifier); + + ProjectResponseDto updateProject(UUID projectIdentifier, ProjectRequestDto projectDto); + + List getAllActiveProjectsTimeline(); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/RiskService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/RiskService.java new file mode 100644 index 0000000..e192f6d --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/RiskService.java @@ -0,0 +1,20 @@ +package com.ikon.projectmanagement.service; + +import com.ikon.projectmanagement.dto.request.RiskCreateRequestDto; +import com.ikon.projectmanagement.dto.response.RiskResponseDto; + +import java.util.List; +import java.util.UUID; + +public interface RiskService { + + RiskResponseDto createRisk(RiskCreateRequestDto riskCreateRequestDto); + + List getAllRisks(); + + RiskResponseDto getRiskById(UUID riskId); + + RiskResponseDto updateRisk(UUID riskId, RiskCreateRequestDto riskCreateRequestDto); + + List getRisksByProject(String projectIdentifier); +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/RoleService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/RoleService.java new file mode 100644 index 0000000..80ee2ff --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/RoleService.java @@ -0,0 +1,34 @@ +package com.ikon.projectmanagement.service; + +import com.ikon.projectmanagement.dto.request.RoleRequestDto; +import com.ikon.projectmanagement.dto.response.RoleResponseDto; +import java.util.List; +import java.util.UUID; + +public interface RoleService { + + /** + * Retrieve all roles + */ + List getAllRoles(); + + /** + * Retrieve role by ID + */ + RoleResponseDto getRoleById(UUID id); + + /** + * Create a new role + */ + RoleResponseDto createRole(RoleRequestDto dto); + + /** + * Update an existing role + */ + RoleResponseDto updateRole(UUID id, RoleRequestDto dto); + + /** + * Delete a role by ID + */ + void deleteRole(UUID id); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ScheduleService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ScheduleService.java new file mode 100644 index 0000000..1d8a529 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/ScheduleService.java @@ -0,0 +1,13 @@ +package com.ikon.projectmanagement.service; + +import com.ikon.projectmanagement.dto.request.ScheduleRequestDto; +import com.ikon.projectmanagement.dto.response.ScheduleResponseDto; + +import java.util.List; +import java.util.UUID; + +public interface ScheduleService { + ScheduleResponseDto saveSchedule(UUID projectIdentifier, ScheduleRequestDto dto, String accessToken); + ScheduleResponseDto getSchedule(UUID projectIdentifier, String accessToken); + List getAllSchedules(); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/WorkingDayService.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/WorkingDayService.java new file mode 100644 index 0000000..7fc0578 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/WorkingDayService.java @@ -0,0 +1,11 @@ +package com.ikon.projectmanagement.service; + +import com.ikon.projectmanagement.dto.response.WorkingDaysResponseDto; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface WorkingDayService { + public Page getAllWorkingDays(Pageable pageable); + + public WorkingDaysResponseDto getWorkingDaysByYear(String year); +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/DealConnector.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/DealConnector.java new file mode 100644 index 0000000..d5196fc --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/DealConnector.java @@ -0,0 +1,366 @@ +package com.ikon.projectmanagement.service.etl; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.springframework.stereotype.Component; + +import com.ikon.connector.dto.response.FieldsConfigDto; +import com.ikon.connector.spi.ConnectorDataSync; +import com.ikon.projectmanagement.entity.ProductOfProject; +import com.ikon.projectmanagement.entity.Project; +import com.ikon.projectmanagement.repository.ProjectRepository; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Component +@RequiredArgsConstructor +public class DealConnector implements ConnectorDataSync { + + private static final Logger log = LoggerFactory.getLogger(DealConnector.class); + + private final ProjectRepository projectRepository; + + @Override + public List getFieldsConfig() { + List fieldsConfig = new ArrayList<>(); + fieldsConfig + .add(FieldsConfigDto.builder().key("dealIdentifier").label("Deal Identifier").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("dealName").label("Deal Name").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("projectName").label("Project Name").type("string").build()); + fieldsConfig.add( + FieldsConfigDto.builder().key("accountIdentifier").label("Account Identifier").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("dealStatus").label("Deal Status").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("currency").label("Currency").type("string").build()); + fieldsConfig + .add(FieldsConfigDto.builder().key("contractNumber").label("Contract Number").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("contractedStartDate").label("Contracted Start Date") + .type("string").build()); + fieldsConfig.add( + FieldsConfigDto.builder().key("contractedEndDate").label("Contracted End Date").type("string").build()); + fieldsConfig.add( + FieldsConfigDto.builder().key("parentProjectNo").label("Parent Project No").type("string").build()); + fieldsConfig + .add(FieldsConfigDto.builder().key("isDebtRevenue").label("Is Debt Revenue").type("boolean").build()); + fieldsConfig + .add(FieldsConfigDto.builder().key("leadIdentifier").label("Lead Identifier").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("formattedActualRevenueIncludingVAT") + .label("Formatted Actual Revenue Including VAT").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("dealTeam").label("Deal Team").type("array").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("updatedBy").label("Updated By").type("string").build()); + fieldsConfig + .add(FieldsConfigDto.builder().key("dealStartDate").label("Deal Start Date").type("string").build()); + fieldsConfig + .add(FieldsConfigDto.builder().key("productDetails").label("Product Details").type("object").build()); + return fieldsConfig; + } + + @Override + public String getModule() { + return "Deal"; + } + + @Override + @Transactional + public void syncBatch(List> payload) { + + log.info("[DealConnector] Received {} records for sync", payload.size()); + + payload.stream() + .filter(data -> { + + String dealId = toStr(data.get("dealIdentifier")); + String status = toStr(data.get("dealStatus")); + + log.info( + "[DealConnector] Evaluating deal [{}], status=[{}]", + dealId, + status); + + return "WON".equalsIgnoreCase(status); + }) + .forEach(data -> { + + log.info("===================================================="); + log.info("[DealConnector] Processing Deal"); + log.info("===================================================="); + + log.info("[DealConnector] Full Payload : {}", data); + + UUID dealIdentifier = parseUUID(data.get("dealIdentifier")); + + UUID accountId = parseUUID( + data.get("accountIdentifier") != null + ? data.get("accountIdentifier") + : data.get("accountId")); + + UUID leadIdentifier = parseUUID(data.get("leadIdentifier")); + UUID updatedByUUID = parseUUID(data.get("updatedBy")); + + log.info( + "[DealConnector] dealIdentifier=[{}], accountId=[{}], leadIdentifier=[{}], updatedBy=[{}]", + dealIdentifier, + accountId, + leadIdentifier, + updatedByUUID); + + Object rawProductDetails = data.get("productDetails"); + + log.info( + "[DealConnector] productDetails type=[{}]", + rawProductDetails != null + ? rawProductDetails.getClass().getName() + : "null"); + + log.info( + "[DealConnector] productDetails value=[{}]", + rawProductDetails); + + ProductOfProject product = buildProduct( + rawProductDetails, + accountId, + dealIdentifier, + leadIdentifier); + + if (product == null) { + + log.warn( + "[DealConnector] Product creation FAILED for deal [{}]", + dealIdentifier); + + log.warn( + "[DealConnector] Raw productDetails = {}", + rawProductDetails); + + return; + } + + log.info( + "[DealConnector] Product created successfully. productIdentifier=[{}], type=[{}]", + product.getProductIdentifier(), + product.getProductType()); + + String name = data.get("projectName") != null + ? (String) data.get("projectName") + : (String) data.get("dealName"); + + UUID projectManager = product.getProjectManager() != null + ? product.getProjectManager() + : accountId; + + List projectTeam = parseUUIDList(data.get("dealTeam")); + + Project project = Project.builder() + .projectIdentifier(dealIdentifier) + .accountId(accountId) + .projectName(name) + .projectStatus((String) data.get("dealStatus")) + .currency((String) data.get("currency")) + .isDebtRevenue_deal((Boolean) data.get("isDebtRevenue")) + .formattedActualRevenueIncludingVAT_deal( + toStr(data.get("formattedActualRevenueIncludingVAT_contracted"))) + .contractNumber(toStr(data.get("contractNumber"))) + .contractedStartDate(parseDate((String) data.get("contractedStartDate"))) + .contractedEndDate(parseDate((String) data.get("contractedEndDate"))) + .projectStartDate(parseDate((String) data.get("dealStartDate"))) + .parentProjectNo((String) data.get("parentProjectNo")) + .projectManager(projectManager) + .updatedBy(updatedByUUID) + .projectTeam(projectTeam) + .source("SalesCRM") + .product(product) + .build(); + + log.info( + "[DealConnector] Saving project for deal [{}] projectName=[{}]", + dealIdentifier, + name); + + projectRepository.save(project); + + log.info( + "[DealConnector] Project saved successfully for deal [{}]", + dealIdentifier); + }); + } + + private ProductOfProject buildProduct( + Object raw, + UUID accountId, + UUID projectIdentifier, + UUID leadIdentifier) { + + log.info( + "[DealConnector] buildProduct() called. rawType=[{}]", + raw != null ? raw.getClass().getName() : "null"); + + if (raw == null) { + + log.warn( + "[DealConnector] productDetails is NULL for deal [{}]", + projectIdentifier); + + return null; + } + + if (!(raw instanceof Map)) { + + log.warn( + "[DealConnector] productDetails is NOT a Map. type=[{}], value=[{}]", + raw.getClass().getName(), + raw); + + return null; + } + + Map productMap = (Map) raw; + + log.info( + "[DealConnector] productDetails contains {} entries", + productMap.size()); + + if (productMap.isEmpty()) { + + log.warn( + "[DealConnector] productDetails map is EMPTY"); + + return null; + } + + productMap.forEach((key, value) -> { + + log.info( + "[DealConnector] Entry key=[{}], valueType=[{}]", + key, + value != null ? value.getClass().getName() : "null"); + + log.info( + "[DealConnector] Entry value=[{}]", + value); + }); + + for (Object value : productMap.values()) { + + if (!(value instanceof Map)) { + + log.warn( + "[DealConnector] Product entry is not Map : {}", + value); + + continue; + } + + Map pd = (Map) value; + + String productType = toStr(pd.get("productType")); + + log.info( + "[DealConnector] Checking productType=[{}]", + productType); + + if (!"Professional Service".equalsIgnoreCase(productType)) { + + log.info( + "[DealConnector] Skipping product because type is [{}]", + productType); + + continue; + } + + log.info( + "[DealConnector] Professional Service product FOUND"); + + UUID pmUuid = tryParseUUID(toStr(pd.get("projectManager"))); + + UUID productId = tryParseUUID(toStr(pd.get("productIdentifier"))); + + log.info( + "[DealConnector] productIdentifier=[{}], projectManager=[{}]", + productId, + pmUuid); + + return ProductOfProject.builder() + .productIdentifier(productId) + .projectIdentifier(projectIdentifier) + .accountId(accountId) + .leadIdentifier(leadIdentifier) + .productType(productType) + .productDescription( + toStr(pd.get("productDescription"))) + .discountPercent( + toDouble(pd.get("discountPercent"))) + .projectManager(pmUuid) + .productStatus("Active") + .build(); + } + + log.warn( + "[DealConnector] No Professional Service product found in productDetails. productMap={}", + productMap); + + return null; + } + + // --------------------------------------------------------------------------- + // Helpers + // --------------------------------------------------------------------------- + private UUID parseUUID(Object value) { + if (value == null) + return null; + try { + return UUID.fromString(value.toString()); + } catch (Exception e) { + return null; + } + } + + private UUID tryParseUUID(String value) { + if (value == null) + return null; + try { + return UUID.fromString(value); + } catch (Exception e) { + return null; + } + } + + private List parseUUIDList(Object value) { + List result = new ArrayList<>(); + if (!(value instanceof List)) + return result; + for (Object item : (List) value) { + UUID uuid = parseUUID(item); + if (uuid != null) + result.add(uuid); + } + return result; + } + + private LocalDate parseDate(String value) { + if (value == null || value.isBlank()) + return null; + try { + return LocalDate.parse(value); + } catch (DateTimeParseException e) { + return null; + } + } + + private String toStr(Object value) { + return value != null ? String.valueOf(value) : null; + } + + private Double toDouble(Object value) { + if (value instanceof Number) + return ((Number) value).doubleValue(); + return null; + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/EmployeeConector.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/EmployeeConector.java new file mode 100644 index 0000000..02cb540 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/EmployeeConector.java @@ -0,0 +1,71 @@ +package com.ikon.projectmanagement.service.etl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.springframework.stereotype.Component; + +import com.ikon.connector.dto.response.FieldsConfigDto; +import com.ikon.connector.spi.ConnectorDataSync; +import com.ikon.projectmanagement.entity.Employee; +import com.ikon.projectmanagement.repository.EmployeeRepository; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; + + +@Component +@RequiredArgsConstructor +public class EmployeeConector implements ConnectorDataSync{ + + private final EmployeeRepository employeeRepository; + + @Override + public List getFieldsConfig() { + List fieldsConfig = new ArrayList<>(); + fieldsConfig.add(FieldsConfigDto.builder().key("empId").label("Employee Identifier").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("name").label("Name").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("role").label("Role").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("grade").label("Grade").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("email").label("Email").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("organizationEmail").label("Organization Email").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("active").label("Active").type("boolean").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("highestQualification").label("Highest Qualification").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("joiningDate").label("Joining Date").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("confirmationDate").label("Confirmation Date").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("accountId").label("Account Identifier").type("string").build()); + return fieldsConfig; + } + + @Override + public String getModule() { + return "Employee"; + } + + @Override + @Transactional + public void syncBatch(List> payload) { + payload.stream() + .forEach(data -> { + + + Employee employee = Employee.builder() + .name(data.get("name") != null ? data.get("name").toString() : null) + .accountId(data.get("accountId") != null ? UUID.fromString(data.get("accountId").toString()) : null) + .empId(data.get("empId") != null ? data.get("empId").toString() : null) + .email(data.get("email") != null ? data.get("email").toString() : null) + .organizationEmail(data.get("organizationEmail") != null ? data.get("organizationEmail").toString() : null) + .role(data.get("role") != null ? data.get("role").toString() : null) + .grade(data.get("grade") != null ? data.get("grade").toString() : null) + .active(data.get("active") != null ? Boolean.parseBoolean(data.get("active").toString()) : null) + .highestQualification(data.get("highestQualification") != null ? data.get("highestQualification").toString(): null) + .joiningDate(data.get("joiningDate") != null ? data.get("joiningDate").toString() : null) + .confirmationDate(data.get("confirmationDate") != null ? data.get("confirmationDate").toString() : null) + .build(); + + employeeRepository.save(employee); + }); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/FxRateConnector.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/FxRateConnector.java new file mode 100644 index 0000000..8962eb8 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/FxRateConnector.java @@ -0,0 +1,184 @@ +package com.ikon.projectmanagement.service.etl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ikon.connector.dto.response.FieldsConfigDto; +import com.ikon.connector.spi.ConnectorDataSync; +import com.ikon.projectmanagement.entity.FxRateDetailsEntity; +import com.ikon.projectmanagement.entity.FxRateEntity; +import com.ikon.projectmanagement.repository.FxRateRepository; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Component +@RequiredArgsConstructor +@Slf4j +public class FxRateConnector implements ConnectorDataSync { + + private final FxRateRepository fxRateRepository; + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public List getFieldsConfig() { + List fieldsConfig = new ArrayList<>(); + fieldsConfig.add(FieldsConfigDto.builder().key("fxRateId").label("FX Rate ID").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("accountIdentifier").label("Account Identifier").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("fxRateDetails").label("FX Rate Details").type("object").build()); + return fieldsConfig; + } + + @Override + public String getModule() { + return "FxRate"; + } + + @Override + @Transactional + public void syncBatch(List> payload) { + if (payload == null || payload.isEmpty()) + return; + + List fxRates = payload.stream() + .map(data -> { + UUID fxRateId = parseUUID(data.get("fxRateId")); + UUID accountIdentifier = parseUUID(data.get("accountIdentifier")); + + if (fxRateId == null) { + log.warn("Skipping record with null fxRateId"); + return null; + } + + FxRateEntity fxRate = fxRateRepository.findByIdWithDetails(fxRateId) + .orElseGet(() -> FxRateEntity.builder() + .fxRateId(fxRateId) + .build()); + + fxRate.setAccountIdentifier(accountIdentifier); + + Map detailsMap = buildDetailsMap(data.get("fxRateDetails")); + log.info("Built detailsMap size: {}", detailsMap.size()); + + if (!detailsMap.isEmpty()) { + fxRate.getFxRateDetails().clear(); + detailsMap.values().forEach(fxRate::addFxRateDetail); + log.info("fxRateDetails after repopulation: {}", fxRate.getFxRateDetails().size()); + } + + return fxRate; + }) + .filter(Objects::nonNull) + .toList(); + + log.info("Saving {} FxRate entities", fxRates.size()); + fxRateRepository.saveAll(fxRates); + } + + private Map buildDetailsMap(Object rawDetails) { + Map resultMap = new HashMap<>(); + + // Convert to JsonNode — handles ObjectNode, String, or Map + JsonNode rootNode = toJsonNode(rawDetails); + if (rootNode == null || rootNode.isNull() || !rootNode.isObject()) { + log.warn("fxRateDetails could not be parsed as an object, type: {}", + rawDetails == null ? "NULL" : rawDetails.getClass().getName()); + return resultMap; + } + + // Outer loop: year keys e.g. "2026", "2025" + rootNode.fields().forEachRemaining(yearEntry -> { + JsonNode currencyMapNode = yearEntry.getValue(); + if (!currencyMapNode.isObject()) + return; + + // Inner loop: currency keys e.g. "USD", "CNY" + currencyMapNode.fields().forEachRemaining(currencyEntry -> { + JsonNode fd = currencyEntry.getValue(); + if (!fd.isObject()) + return; + + // currencyId is null in payload, fallback to currency field + String currencyId = !fd.path("currencyId").isNull() && fd.hasNonNull("currencyId") + ? fd.path("currencyId").asText(null) + : fd.path("currency").asText(null); + + if (currencyId == null) { + log.warn("Skipping detail with null currencyId and currency for year: {}", yearEntry.getKey()); + return; + } + + Boolean active = fd.hasNonNull("activeStatus") + ? fd.path("activeStatus").asBoolean(true) + : Boolean.TRUE; + + FxRateDetailsEntity detail = FxRateDetailsEntity.builder() + .currencyId(currencyId) + .currency(fd.path("currency").asText(null)) + .fxRate(fd.hasNonNull("fxRate") ? fd.path("fxRate").asDouble() : null) + .activeStatus(active) + .year(fd.path("year").asText(null)) + .build(); + + resultMap.put(currencyId, detail); + log.debug("Added detail: currencyId={}, fxRate={}, year={}", + currencyId, detail.getFxRate(), detail.getYear()); + }); + }); + + return resultMap; + } + + /** + * Converts ObjectNode, Map, or JSON String → JsonNode + */ + private JsonNode toJsonNode(Object rawDetails) { + if (rawDetails == null) + return null; + + // Already a JsonNode (e.g. ObjectNode from Jackson) + if (rawDetails instanceof JsonNode) { + return (JsonNode) rawDetails; + } + + // Plain JSON String + if (rawDetails instanceof String) { + try { + return objectMapper.readTree((String) rawDetails); + } catch (Exception e) { + log.error("Failed to parse fxRateDetails JSON string: {}", e.getMessage()); + return null; + } + } + + // Plain Map (e.g. LinkedHashMap) + if (rawDetails instanceof Map) { + return objectMapper.valueToTree(rawDetails); + } + + log.warn("Unrecognized fxRateDetails type: {}", rawDetails.getClass().getName()); + return null; + } + + // --- Utility Helpers --- + + private UUID parseUUID(Object value) { + if (value == null) + return null; + try { + return UUID.fromString(value.toString()); + } catch (Exception e) { + log.warn("Failed to parse UUID from value: {}", value); + return null; + } + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/GradeConnector.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/GradeConnector.java new file mode 100644 index 0000000..3490ba4 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/GradeConnector.java @@ -0,0 +1,134 @@ +package com.ikon.projectmanagement.service.etl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.springframework.stereotype.Component; + +import com.ikon.connector.dto.response.FieldsConfigDto; +import com.ikon.connector.spi.ConnectorDataSync; +import com.ikon.projectmanagement.entity.Grade; +import com.ikon.projectmanagement.repository.GradeRepository; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; + +/** + * GradeConnector: Maps external grade/salary grade data to local Grade entity + * + * This connector syncs grade information from an external HR system or database. + * It handles field mapping, type conversion, and persistence of grade records. + */ +@Component +@RequiredArgsConstructor +public class GradeConnector implements ConnectorDataSync { + + private final GradeRepository gradeRepository; + + /** + * Define the configuration for fields that will be synced from external source. + * This specifies the external field names, labels, and their data types. + */ + @Override + public List getFieldsConfig() { + List fieldsConfig = new ArrayList<>(); + + fieldsConfig.add(FieldsConfigDto.builder() + .key("id") + .label("Grade ID") + .type("string") + .build()); + + fieldsConfig.add(FieldsConfigDto.builder() + .key("accountId") + .label("Account ID") + .type("string") + .build()); + + fieldsConfig.add(FieldsConfigDto.builder() + .key("grade") + .label("Grade") + .type("string") + .build()); + + return fieldsConfig; + } + + /** + * Returns the module name for this connector. + * Used for identification and logging purposes. + */ + @Override + public String getModule() { + return "Grade"; + } + + /** + * Core method that processes incoming grade data from external source. + * + * Process flow: + * 1. Extract and parse fields from Map + * 2. Convert data types using utility methods + * 3. Build Grade entity + * 4. Save to repository + * + * @param payload List of Map objects containing grade data from external source + */ + @Override + @Transactional + public void syncBatch(List> payload) { + payload.stream() + .forEach(data -> { + try { + UUID gradeId = parseUUID(data.get("id")); + UUID accountId = parseUUID(data.get("accountId")); + String gradeName = toStr(data.get("grade")); + + // Skip if required fields are missing + if (gradeId == null || gradeName == null) { + System.err.println("Skipping grade record: missing required fields (id or grade)"); + return; + } + + // Build Grade entity with mapped fields + Grade grade = Grade.builder() + .id(gradeId) + .accountId(accountId) + .grade(gradeName) + .build(); + + // Save the grade entity to repository + gradeRepository.save(grade); + + } catch (Exception e) { + // Log error but continue processing other records + System.err.println("Error syncing grade: " + e.getMessage()); + } + }); + } + + // ============ Utility Methods for Type Conversion ============ + + /** + * Parse UUID from Object safely. + * Returns null if value is null or cannot be parsed as UUID. + */ + private UUID parseUUID(Object value) { + if (value == null) return null; + try { + return UUID.fromString(value.toString()); + } catch (Exception e) { + return null; + } + } + + /** + * Convert Object to String safely. + * Returns null if value is null, otherwise returns String representation. + */ + private String toStr(Object value) { + return value != null ? String.valueOf(value) : null; + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/RoleConnector.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/RoleConnector.java new file mode 100644 index 0000000..51828af --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/RoleConnector.java @@ -0,0 +1,94 @@ +package com.ikon.projectmanagement.service.etl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.springframework.stereotype.Component; + +import com.ikon.connector.dto.response.FieldsConfigDto; +import com.ikon.connector.spi.ConnectorDataSync; +import com.ikon.projectmanagement.entity.Role; +import com.ikon.projectmanagement.repository.RoleRepository; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; + +/** + * RoleConnector: Maps external role data to local Role entity. + * + * This connector syncs role information from an external system. + * It handles field mapping, type conversion, and persistence of Role records. + */ +@Component +@RequiredArgsConstructor +public class RoleConnector implements ConnectorDataSync { + + private final RoleRepository roleRepository; + + /** + * Define the configuration for fields that will be synced from the external + * source. + * This specifies the external field names, labels, and their data types. + */ + @Override + public List getFieldsConfig() { + List fieldsConfig = new ArrayList<>(); + + fieldsConfig.add(FieldsConfigDto.builder() + .key("id") + .label("Role ID") + .type("string") + .build()); + + fieldsConfig.add(FieldsConfigDto.builder() + .key("accountId") + .label("Account ID") + .type("string") + .build()); + + fieldsConfig.add(FieldsConfigDto.builder() + .key("role") + .label("Role") + .type("string") + .build()); + + return fieldsConfig; + } + + /** + * Returns the module name for this connector. + * Used for identification and logging purposes. + */ + @Override + public String getModule() { + return "Role"; + } + + /** + * Core method that processes incoming role data from an external source. + * + * Process flow: + * 1. Extract and parse fields from Map + * 2. Convert data types using utility methods + * 3. Build Role entity + * 4. Save to repository + * + * @param payload List of Map objects containing role data from external source + */ + @Override + @Transactional + public void syncBatch(List> payload) { + payload.stream() + .forEach(data -> { + Role role = Role.builder() + .id(data.get("id") != null ? UUID.fromString(data.get("id").toString()) : null) + .accountId(data.get("id") != null ? UUID.fromString(data.get("id").toString()) : null) + .role(data.get("role") != null ? data.get("role").toString() : null) + .build(); + roleRepository.save(role); + }); + } + +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/WorkingDaysConnector.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/WorkingDaysConnector.java new file mode 100644 index 0000000..7a7bf44 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/etl/WorkingDaysConnector.java @@ -0,0 +1,188 @@ +package com.ikon.projectmanagement.service.etl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ikon.connector.dto.response.FieldsConfigDto; +import com.ikon.connector.spi.ConnectorDataSync; +import com.ikon.projectmanagement.entity.WorkingDaysDetailsEntity; +import com.ikon.projectmanagement.entity.WorkingDaysEntity; +import com.ikon.projectmanagement.repository.WorkingDaysRepository; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Component +@RequiredArgsConstructor +@Slf4j +public class WorkingDaysConnector implements ConnectorDataSync { + + private final WorkingDaysRepository workingDaysRepository; + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public List getFieldsConfig() { + List fieldsConfig = new ArrayList<>(); + fieldsConfig.add(FieldsConfigDto.builder().key("workingId").label("Working ID").type("string").build()); + fieldsConfig.add( + FieldsConfigDto.builder().key("accountIdentifier").label("Account Identifier").type("string").build()); + fieldsConfig.add(FieldsConfigDto.builder().key("workingDaysDetails").label("Working Days Details") + .type("object").build()); + return fieldsConfig; + } + + @Override + public String getModule() { + return "WorkingDays"; + } + + @Override + @Transactional + public void syncBatch(List> payload) { + if (payload == null || payload.isEmpty()) + return; + + List workingDaysList = payload.stream() + .map(data -> { + UUID workingId = parseUUID(data.get("workingId")); + UUID accountIdentifier = parseUUID(data.get("accountIdentifier")); + + if (workingId == null) { + log.warn("Skipping record with null workingId"); + return null; + } + + // Fetch existing entity with details eagerly, or create new + WorkingDaysEntity workingDays = workingDaysRepository.findByIdWithDetails(workingId) + .orElseGet(() -> WorkingDaysEntity.builder() + .workingId(workingId) + .build()); + + workingDays.setAccountIdentifier(accountIdentifier); + + log.info("RAW workingDaysDetails type: {}", + data.get("workingDaysDetails") == null ? "NULL" + : data.get("workingDaysDetails").getClass().getName()); + log.info("RAW workingDaysDetails value: {}", data.get("workingDaysDetails")); + + Map detailsMap = buildDetailsMap(data.get("workingDaysDetails")); + log.info("Built detailsMap size: {}", detailsMap.size()); + + if (!detailsMap.isEmpty()) { + // Clear existing managed collection (orphanRemoval deletes old rows) + workingDays.getWorkingDaysDetails().clear(); + // Repopulate via addWorkingDaysDetail to keep parent link intact + detailsMap.values().forEach(workingDays::addWorkingDaysDetail); + log.info("workingDaysDetails after repopulation: {}", + workingDays.getWorkingDaysDetails().size()); + } + + return workingDays; + }) + .filter(Objects::nonNull) + .toList(); + + log.info("Saving {} WorkingDays entities", workingDaysList.size()); + workingDaysRepository.saveAll(workingDaysList); + } + + private Map buildDetailsMap(Object rawDetails) { + Map resultMap = new HashMap<>(); + + JsonNode rootNode = toJsonNode(rawDetails); + if (rootNode == null || rootNode.isNull() || !rootNode.isObject()) { + log.warn("workingDaysDetails could not be parsed as an object, type: {}", + rawDetails == null ? "NULL" : rawDetails.getClass().getName()); + return resultMap; + } + + // Outer loop: year keys e.g. "2025", "2026" + rootNode.fields().forEachRemaining(yearEntry -> { + String year = yearEntry.getKey(); + JsonNode monthMapNode = yearEntry.getValue(); + if (!monthMapNode.isObject()) + return; + + // Inner loop: month keys e.g. "January", "February" + monthMapNode.fields().forEachRemaining(monthEntry -> { + JsonNode fd = monthEntry.getValue(); + if (!fd.isObject()) + return; + + String month = fd.hasNonNull("month") + ? fd.path("month").asText(null) + : monthEntry.getKey(); + + if (month == null) { + log.warn("Skipping detail with null month for year: {}", year); + return; + } + + Integer workingDays = fd.hasNonNull("workingDays") + ? fd.path("workingDays").asInt() + : null; + + WorkingDaysDetailsEntity detail = WorkingDaysDetailsEntity.builder() + .year(fd.hasNonNull("year") ? fd.path("year").asText(null) : year) + .month(month) + .workingDays(workingDays) + .build(); + + resultMap.put(month, detail); + log.debug("Added detail: year={}, month={}, workingDays={}", year, month, workingDays); + }); + }); + + return resultMap; + } + + /** + * Converts ObjectNode, Map, or JSON String → JsonNode + */ + private JsonNode toJsonNode(Object rawDetails) { + if (rawDetails == null) + return null; + + if (rawDetails instanceof JsonNode) { + return (JsonNode) rawDetails; + } + + if (rawDetails instanceof String) { + try { + return objectMapper.readTree((String) rawDetails); + } catch (Exception e) { + log.error("Failed to parse workingDaysDetails JSON string: {}", e.getMessage()); + return null; + } + } + + if (rawDetails instanceof Map) { + return objectMapper.valueToTree(rawDetails); + } + + log.warn("Unrecognized workingDaysDetails type: {}", rawDetails.getClass().getName()); + return null; + } + + // --- Utility Helpers --- + + private UUID parseUUID(Object value) { + if (value == null) + return null; + try { + return UUID.fromString(value.toString()); + } catch (Exception e) { + log.warn("Failed to parse UUID from value: {}", value); + return null; + } + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/DashboardServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/DashboardServiceImpl.java new file mode 100644 index 0000000..3670499 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/DashboardServiceImpl.java @@ -0,0 +1,35 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.ikon.projectmanagement.dto.response.DashboardWidgetsResponseDto; +import com.ikon.projectmanagement.dto.response.StatusWiseProjectResponseData; +import com.ikon.projectmanagement.repository.IssueRepository; +import com.ikon.projectmanagement.repository.ProjectRepository; +import com.ikon.projectmanagement.repository.RiskRepository; +import com.ikon.projectmanagement.service.DashboardService; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class DashboardServiceImpl implements DashboardService { + private final ProjectRepository projectRepository; + private final IssueRepository issueRepository; + private final RiskRepository riskRepository; + + @Override + public DashboardWidgetsResponseDto getDashboardWidgetsData() { + DashboardWidgetsResponseDto widgetsData = new DashboardWidgetsResponseDto(); + widgetsData.setTotalProjects(projectRepository.count()); + widgetsData.setTotalIssues(issueRepository.count()); + widgetsData.setTotalRisksCount(riskRepository.count()); + return widgetsData; + } + + @Override + public List getStatusWiseProjectData() { + return projectRepository.getProjectStatusCounts(); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/EmployeeServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/EmployeeServiceImpl.java new file mode 100644 index 0000000..fd30bfb --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/EmployeeServiceImpl.java @@ -0,0 +1,61 @@ +package com.ikon.projectmanagement.service.impl; + +import com.ikon.projectmanagement.dto.request.EmployeeRequestDto; +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; +import com.ikon.projectmanagement.entity.Employee; +import com.ikon.projectmanagement.mapper.EmployeeMapper; +import com.ikon.projectmanagement.repository.EmployeeRepository; +import com.ikon.projectmanagement.service.EmployeeService; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class EmployeeServiceImpl implements EmployeeService { + + private final EmployeeRepository employeeRepository; + private final EmployeeMapper employeeMapper; + + @Override + public List getAllEmployees() { + return employeeRepository.findAll().stream() + .map(employeeMapper::toResponseDto) + .collect(Collectors.toList()); + } + + @Override + public EmployeeResponseDto getEmployeeById(String id) { + Employee employee = employeeRepository.findByEmpId(id) + .orElseThrow(() -> new RuntimeException("Employee not found with ID: " + id)); + return employeeMapper.toResponseDto(employee); + } + + @Override + public EmployeeResponseDto createEmployee(EmployeeRequestDto dto) { + // Check if employee already exists + if (dto.getEmpId() != null && employeeRepository.findByEmpId(dto.getEmpId()).isPresent()) { + throw new RuntimeException("Employee already exists with ID: " + dto.getEmpId()); + } + Employee employee = employeeMapper.toEntity(dto); + Employee savedEmployee = employeeRepository.save(employee); + return employeeMapper.toResponseDto(savedEmployee); + } + + @Override + public EmployeeResponseDto updateEmployee(String id, EmployeeRequestDto dto) { + Employee employee = employeeRepository.findByEmpId(id) + .orElseThrow(() -> new RuntimeException("Employee not found with ID: " + id)); + employeeMapper.updateEntity(employee, dto); + Employee updatedEmployee = employeeRepository.save(employee); + return employeeMapper.toResponseDto(updatedEmployee); + } + + @Override + public void deleteEmployee(String id) { + Employee employee = employeeRepository.findByEmpId(id) + .orElseThrow(() -> new RuntimeException("Employee not found with ID: " + id)); + employeeRepository.delete(employee); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/FxRateServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/FxRateServiceImpl.java new file mode 100644 index 0000000..52610bf --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/FxRateServiceImpl.java @@ -0,0 +1,64 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.HashMap; +import java.util.Map; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import com.ikon.projectmanagement.dto.response.FxRateDetailsDto; +import com.ikon.projectmanagement.dto.response.FxRateResponseDto; +import com.ikon.projectmanagement.entity.FxRateEntity; +import com.ikon.projectmanagement.repository.FxRateRepository; +import com.ikon.projectmanagement.service.FxRateService; +import com.ikon.webservice.WebService; +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class FxRateServiceImpl extends WebService implements FxRateService { + + private final FxRateRepository fxRateRepository; + + @Override + public Page getAllFxRates(Pageable pageable) { + return fxRateRepository.findAll(pageable) + .map(this::mapToResponseDto); + } + + @Override + public FxRateResponseDto getFxRateByYear(String year) { + FxRateEntity entity = fxRateRepository.findByYear(year) + .orElseThrow(() -> new EntityNotFoundException( + "FX rate not found for year: " + year)); + + return mapToResponseDto(entity); + } + + // ------------------------------------------------------------------------- + // Private helpers + // ------------------------------------------------------------------------ + + private FxRateResponseDto mapToResponseDto(FxRateEntity entity) { + Map> detailsMap = new HashMap<>(); + + entity.getFxRateDetails().values().forEach(detail -> { + FxRateDetailsDto dto = new FxRateDetailsDto(); + dto.setId(detail.getCurrencyId()); + dto.setCurrency(detail.getCurrency()); + dto.setFxRate(detail.getFxRate()); + dto.setActiveStatus(detail.getActiveStatus()); + dto.setYear(detail.getYear()); + + detailsMap + .computeIfAbsent(detail.getYear(), y -> new HashMap<>()) + .put(detail.getCurrencyId(), dto); + }); + + FxRateResponseDto responseDto = new FxRateResponseDto(); + responseDto.setFxRateId(entity.getFxRateId()); + responseDto.setAccountIdentifier(entity.getAccountIdentifier()); + responseDto.setFxRateDetails(detailsMap); + return responseDto; + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/GradeServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/GradeServiceImpl.java new file mode 100644 index 0000000..099e8b9 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/GradeServiceImpl.java @@ -0,0 +1,58 @@ +package com.ikon.projectmanagement.service.impl; + +import com.ikon.projectmanagement.dto.request.GradeRequestDto; +import com.ikon.projectmanagement.dto.response.GradeResponseDto; +import com.ikon.projectmanagement.entity.Grade; +import com.ikon.projectmanagement.mapper.GradeMapper; +import com.ikon.projectmanagement.repository.GradeRepository; +import com.ikon.projectmanagement.service.GradeService; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class GradeServiceImpl implements GradeService { + + private final GradeRepository gradeRepository; + private final GradeMapper gradeMapper; + + @Override + public List getAllGrades() { + return gradeRepository.findAll().stream() + .map(gradeMapper::toResponseDto) + .collect(Collectors.toList()); + } + + @Override + public GradeResponseDto getGradeById(UUID id) { + Grade grade = gradeRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Grade not found with ID: " + id)); + return gradeMapper.toResponseDto(grade); + } + + @Override + public GradeResponseDto createGrade(GradeRequestDto dto) { + Grade grade = gradeMapper.toEntity(dto); + Grade savedGrade = gradeRepository.save(grade); + return gradeMapper.toResponseDto(savedGrade); + } + + @Override + public GradeResponseDto updateGrade(UUID id, GradeRequestDto dto) { + Grade grade = gradeRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Grade not found with ID: " + id)); + gradeMapper.updateEntity(grade, dto); + Grade updatedGrade = gradeRepository.save(grade); + return gradeMapper.toResponseDto(updatedGrade); + } + + @Override + public void deleteGrade(UUID id) { + Grade grade = gradeRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Grade not found with ID: " + id)); + gradeRepository.delete(grade); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportEmployeeServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportEmployeeServiceImpl.java new file mode 100644 index 0000000..a3f8227 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportEmployeeServiceImpl.java @@ -0,0 +1,132 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; +import com.ikon.projectmanagement.dto.request.EmployeeRequestDto; +import com.ikon.projectmanagement.dto.response.EmployeeResponseDto; +import com.ikon.projectmanagement.entity.Employee; +import com.ikon.projectmanagement.repository.EmployeeRepository; +import com.ikon.projectmanagement.mapper.EmployeeMapper; +import com.ikon.projectmanagement.service.ImportEmployeeService; +import com.ikon.webservice.WebService; + +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.UUID; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ImportEmployeeServiceImpl extends WebService implements ImportEmployeeService { + + private final EmployeeMapper employeeMapper; + + private final RestTemplate restTemplate; + private final EmployeeRepository employeeRepository; + + @Value("${salescrm.api.base-url}") + private String salesCrmBaseUrl; + + private HttpHeaders createHeaders(String accessToken) { + HttpHeaders headers = new HttpHeaders(); + if (accessToken != null && !accessToken.isEmpty()) { + headers.set("Authorization", accessToken); + } + headers.set("Content-Type", "application/json"); + return headers; + } + + private static final int PAGE_SIZE = 200; + + @Override + @Transactional + public List importEmployees(String accessToken) { + String baseUrl = salesCrmBaseUrl + "/employee"; + UUID accountId = getActiveAccountId(); + log.info("Fetching all employees from Sales CRM: {}", baseUrl); + try { + HttpEntity entity = new HttpEntity<>(createHeaders(accessToken)); + List allDtos = new ArrayList<>(); + List savedResponses = new ArrayList<>(); + int page = 0; + int totalPages = 1; + + while (page < totalPages) { + String url = baseUrl + "?page=" + page + "&size=" + PAGE_SIZE; + ResponseEntity> response = restTemplate.exchange( + url, HttpMethod.GET, entity, new ParameterizedTypeReference>() {}); + + if (response.getBody() == null || response.getBody().getContent() == null) { + break; + } + + PageResponse body = response.getBody(); + allDtos.addAll(body.getContent()); + totalPages = body.getTotalPages(); + log.info("Fetched employees page {}/{}", page + 1, totalPages); + page++; + } + + for (EmployeeRequestDto dto : allDtos) { + Optional existingOpt = employeeRepository.findByEmpId(dto.getEmpId()); + Employee emp; + if (existingOpt.isPresent()) { + emp = existingOpt.get(); + emp.setAccountId(accountId); + emp.setName(dto.getName()); + emp.setEmail(dto.getEmail()); + emp.setOrganizationEmail(dto.getOrganizationEmail()); + emp.setRole(dto.getRole()); + emp.setGrade(dto.getGrade()); + emp.setActive(dto.getActive()); + } else { + emp = Employee.builder() + .empId(dto.getEmpId()) + .accountId(accountId) + .name(dto.getName()) + .email(dto.getEmail()) + .organizationEmail(dto.getOrganizationEmail()) + .role(dto.getRole()) + .grade(dto.getGrade()) + .active(dto.getActive()) + .build(); + } + employeeRepository.save(emp); + savedResponses.add(employeeMapper.toResponseDto(emp)); + } + + if (!allDtos.isEmpty()) { + log.info("Saved/Updated {} employees in total", allDtos.size()); + } + + return savedResponses; + } catch (RestClientException e) { + log.error("Failed to fetch employees from Sales CRM: {}", e.getMessage()); + return Collections.emptyList(); + } + } + + @Data + public static class PageResponse { + private List content; + private int totalPages; + private long totalElements; + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportFxRateServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportFxRateServiceImpl.java new file mode 100644 index 0000000..289a093 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportFxRateServiceImpl.java @@ -0,0 +1,141 @@ +package com.ikon.projectmanagement.service.impl; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.ikon.projectmanagement.dto.response.FxRateDto; +import com.ikon.projectmanagement.entity.FxRateEntity; +import com.ikon.projectmanagement.entity.FxRateEntity; +import com.ikon.projectmanagement.repository.FxRateRepository; +import com.ikon.projectmanagement.service.ImportFxRateService; +import com.ikon.webservice.WebService; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ImportFxRateServiceImpl extends WebService implements ImportFxRateService { + + private final RestTemplate restTemplate; + private final FxRateRepository fxRateRepository; + + @Value("${salescrm.api.base-url}") + private String salesCrmBaseUrl; + + private HttpHeaders createHeaders(String accessToken) { + HttpHeaders headers = new HttpHeaders(); + if (accessToken != null && !accessToken.isEmpty()) { + headers.set("Authorization", accessToken); + } + headers.set("Content-Type", "application/json"); + return headers; + } + + private static final int PAGE_SIZE = 200; + + @Override + @Transactional + public List importFxRates(String accessToken) { + String baseUrl = salesCrmBaseUrl + "/fxrate"; + log.info("Fetching all FX rates from Sales CRM: {}", baseUrl); + try { + HttpEntity entity = new HttpEntity<>(createHeaders(accessToken)); + List allRaw = new ArrayList<>(); + int page = 0; + int totalPages = 1; + + while (page < totalPages) { + String url = baseUrl + "?page=" + page + "&size=" + PAGE_SIZE; + ResponseEntity> response = restTemplate.exchange( + url, HttpMethod.GET, entity, + new ParameterizedTypeReference>() {}); + + if (response.getBody() == null || response.getBody().getContent() == null) { + break; + } + + PageResponse body = response.getBody(); + allRaw.addAll(body.getContent()); + totalPages = body.getTotalPages(); + log.info("Fetched FX rates page {}/{}", page + 1, totalPages); + page++; + } + + List dtos = allRaw.stream() + .map(this::mapToFxRateDto) + .collect(Collectors.toList()); + + List entities = dtos.stream().map(dto -> FxRateEntity.builder() + .fxRateId(dto.getId()) + .accountIdentifier(dto.getAccountId()) + .build()).collect(Collectors.toList()); + + if (!entities.isEmpty()) { + fxRateRepository.saveAll(entities); + log.info("Saved/Updated {} FX rates in total", entities.size()); + } + + return dtos; + } catch (RestClientException e) { + log.error("Failed to fetch FX rates from Sales CRM: {}", e.getMessage()); + return Collections.emptyList(); + } + } + + private FxRateDto mapToFxRateDto(SalesCrmFxRateDto source) { + BigDecimal rateValue = BigDecimal.ZERO; + if (source.getRate() != null) { + try { + rateValue = new BigDecimal(source.getRate()); + } catch (NumberFormatException e) { + log.warn("Invalid rate format for id {}: {}", source.getId(), source.getRate()); + } + } + return FxRateDto.builder() + .id(source.getId()) + .accountId(source.getAccountId()) + .toCurrency(source.getCurrency()) + .fromCurrency("USD") + .rate(rateValue) + .effectiveDate(source.getYear()) + .build(); + } + + @Data + public static class PageResponse { + private List content; + private int totalPages; + private long totalElements; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + private static class SalesCrmFxRateDto { + private UUID id; + private UUID accountId; + private String year; + private String rate; + private String currency; + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportGradeServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportGradeServiceImpl.java new file mode 100644 index 0000000..0a1a91c --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportGradeServiceImpl.java @@ -0,0 +1,85 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.ikon.projectmanagement.dto.request.GradeRequestDto; +import com.ikon.projectmanagement.dto.response.GradeResponseDto; +import com.ikon.projectmanagement.entity.Grade; +import com.ikon.projectmanagement.mapper.GradeMapper; +import com.ikon.projectmanagement.repository.GradeRepository; +import com.ikon.projectmanagement.service.ImportGradeService; +import com.ikon.webservice.WebService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.UUID; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ImportGradeServiceImpl extends WebService implements ImportGradeService { + + private final GradeMapper gradeMapper; + + private final RestTemplate restTemplate; + private final GradeRepository gradeRepository; + + @Value("${salescrm.api.base-url}") + private String salesCrmBaseUrl; + + private HttpHeaders createHeaders(String accessToken) { + HttpHeaders headers = new HttpHeaders(); + if (accessToken != null && !accessToken.isEmpty()) { + headers.set("Authorization", accessToken); + } + headers.set("Content-Type", "application/json"); + return headers; + } + + @Override + @Transactional + public List importGrades(String accessToken) { + String url = salesCrmBaseUrl + "/grade"; + UUID accountId = getActiveAccountId(); + log.info("Fetching all grades from Sales CRM: {}", url); + try { + HttpEntity entity = new HttpEntity<>(createHeaders(accessToken)); + ResponseEntity> response = restTemplate.exchange( + url, HttpMethod.GET, entity, new ParameterizedTypeReference>() {}); + List dtos = response.getBody() != null ? response.getBody() : Collections.emptyList(); + List savedResponses = new ArrayList<>(); + + List entities = dtos.stream().map(dto -> Grade.builder() + .id(dto.getId()) + .accountId(accountId) + .grade(dto.getGrade()) + .build()).collect(Collectors.toList()); + + if (!entities.isEmpty()) { + gradeRepository.saveAll(entities); + log.info("Saved/Updated {} grades", entities.size()); + } + + entities.forEach(g -> savedResponses.add(gradeMapper.toResponseDto(g))); + return savedResponses; + } catch (RestClientException e) { + log.error("Failed to fetch grades from Sales CRM: {}", e.getMessage()); + return Collections.emptyList(); + } + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportRoleServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportRoleServiceImpl.java new file mode 100644 index 0000000..05ed82e --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportRoleServiceImpl.java @@ -0,0 +1,85 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.ikon.projectmanagement.dto.request.RoleRequestDto; +import com.ikon.projectmanagement.dto.response.RoleResponseDto; +import com.ikon.projectmanagement.entity.Role; +import com.ikon.projectmanagement.mapper.RoleMapper; +import com.ikon.projectmanagement.repository.RoleRepository; +import com.ikon.projectmanagement.service.ImportRoleService; +import com.ikon.webservice.WebService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.UUID; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ImportRoleServiceImpl extends WebService implements ImportRoleService { + + private final RoleMapper roleMapper; + + private final RestTemplate restTemplate; + private final RoleRepository roleRepository; + + @Value("${salescrm.api.base-url}") + private String salesCrmBaseUrl; + + private HttpHeaders createHeaders(String accessToken) { + HttpHeaders headers = new HttpHeaders(); + if (accessToken != null && !accessToken.isEmpty()) { + headers.set("Authorization", accessToken); + } + headers.set("Content-Type", "application/json"); + return headers; + } + + @Override + @Transactional + public List importRoles(String accessToken) { + String url = salesCrmBaseUrl + "/crm-role"; + UUID accountId = getActiveAccountId(); + log.info("Fetching all roles from Sales CRM: {}", url); + try { + HttpEntity entity = new HttpEntity<>(createHeaders(accessToken)); + ResponseEntity> response = restTemplate.exchange( + url, HttpMethod.GET, entity, new ParameterizedTypeReference>() {}); + List dtos = response.getBody() != null ? response.getBody() : Collections.emptyList(); + List savedResponses = new ArrayList<>(); + + List entities = dtos.stream().map(dto -> Role.builder() + .id(dto.getId()) + .accountId(accountId) + .role(dto.getRole()) + .build()).collect(Collectors.toList()); + + if (!entities.isEmpty()) { + roleRepository.saveAll(entities); + log.info("Saved/Updated {} roles", entities.size()); + } + + entities.forEach(r -> savedResponses.add(roleMapper.toResponseDto(r))); + return savedResponses; + } catch (RestClientException e) { + log.error("Failed to fetch roles from Sales CRM: {}", e.getMessage()); + return Collections.emptyList(); + } + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportWorkingDayServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportWorkingDayServiceImpl.java new file mode 100644 index 0000000..50acc93 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ImportWorkingDayServiceImpl.java @@ -0,0 +1,109 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.ikon.projectmanagement.dto.response.WorkingDayDto; +import com.ikon.projectmanagement.entity.WorkingDaysEntity; +import com.ikon.projectmanagement.repository.WorkingDaysRepository; +import com.ikon.projectmanagement.service.ImportWorkingDayService; +import com.ikon.webservice.WebService; + +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.UUID; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ImportWorkingDayServiceImpl extends WebService implements ImportWorkingDayService { + + private final RestTemplate restTemplate; + private final WorkingDaysRepository workingDayRepository; + + @Value("${salescrm.api.base-url}") + private String salesCrmBaseUrl; + + private HttpHeaders createHeaders(String accessToken) { + HttpHeaders headers = new HttpHeaders(); + if (accessToken != null && !accessToken.isEmpty()) { + headers.set("Authorization", accessToken); + } + headers.set("Content-Type", "application/json"); + return headers; + } + + private static final int PAGE_SIZE = 200; + + @Override + @Transactional + public List importWorkingDays(String accessToken) { + String baseUrl = salesCrmBaseUrl + "/workingday"; + UUID accountId = getActiveAccountId(); + log.info("Fetching all working days from Sales CRM: {}", baseUrl); + try { + HttpEntity entity = new HttpEntity<>(createHeaders(accessToken)); + List allDtos = new ArrayList<>(); + int page = 0; + int totalPages = 1; + + while (page < totalPages) { + String url = baseUrl + "?page=" + page + "&size=" + PAGE_SIZE; + ResponseEntity> response = restTemplate.exchange( + url, HttpMethod.GET, entity, new ParameterizedTypeReference>() { + }); + + if (response.getBody() == null || response.getBody().getContent() == null) { + break; + } + + PageResponse body = response.getBody(); + allDtos.addAll(body.getContent()); + totalPages = body.getTotalPages(); + log.info("Fetched working days page {}/{}", page + 1, totalPages); + page++; + } + + // List entities = allDtos.stream().map(dto -> + // WorkingDaysEntity.builder() + // .id(dto.getId()) + // .accountId(accountId) + // .year(dto.getYear()) + // .month(dto.getMonth()) + // .workingDays(dto.getWorkingDays()) + // .build()).collect(Collectors.toList()); + + // if (!entities.isEmpty()) { + // workingDayRepository.saveAll(entities); + // log.info("Saved/Updated {} working days in total", entities.size()); + // } + + return allDtos; + } catch (RestClientException e) { + log.error("Failed to fetch working days from Sales CRM: {}", e.getMessage()); + return Collections.emptyList(); + } + } + + @Data + public static class PageResponse { + private List content; + private int totalPages; + private long totalElements; + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/IssueServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/IssueServiceImpl.java new file mode 100644 index 0000000..dc9a579 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/IssueServiceImpl.java @@ -0,0 +1,112 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; + +import com.ikon.projectmanagement.dto.request.IssueCreateRequestDto; +import com.ikon.projectmanagement.dto.response.IssueResponseDto; +import com.ikon.projectmanagement.entity.Issue; +import com.ikon.projectmanagement.mapper.IssueMapper; +import com.ikon.projectmanagement.repository.IssueRepository; +import com.ikon.projectmanagement.repository.ProjectRepository; +import com.ikon.projectmanagement.service.IssueService; +import com.ikon.webservice.WebService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.apache.kafka.common.errors.ResourceNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Slf4j +public class IssueServiceImpl extends WebService implements IssueService { + + private final IssueRepository issueRepository; + private final ProjectRepository projectRepository; + private final IssueMapper issueMapper; + + @Override + @Transactional + public IssueResponseDto createIssue(IssueCreateRequestDto issueCreateRequestDto) { + + log.info("Creating issue for project: {}", issueCreateRequestDto.getProjectIdentifier()); + + UUID projectId = issueCreateRequestDto.getProjectIdentifier(); + + projectRepository.findByProjectIdentifier(projectId) + .orElseThrow(() -> new NoSuchElementException( + "Project not found with identifier: " + issueCreateRequestDto.getProjectIdentifier())); + + Issue issue = issueMapper.toEntity(issueCreateRequestDto); + issue.setProjectIdentifier(projectId); + issue.setIssueStatus("Active"); + + Issue savedIssue = issueRepository.save(issue); + + return issueMapper.toResponse(savedIssue); + } + + @Override + public List getAllIssues(UUID projectIdentifier) { + + log.info("Fetching all issues"); + + return issueRepository.findByProjectIdentifier(projectIdentifier) + .stream() + .map(issueMapper::toResponse) + .toList(); + } + + @Override + public IssueResponseDto getIssueById(UUID issueIdentifier) { + + log.info("Fetching issue with identifier: {}", issueIdentifier); + + Issue issue = issueRepository.findById(issueIdentifier) + .orElseThrow(() -> new NoSuchElementException( + "Issue not found with identifier: " + issueIdentifier)); + + return issueMapper.toResponse(issue); + } + + @Override + @Transactional + public IssueResponseDto updateIssue(UUID issueIdentifier, IssueCreateRequestDto issueCreateRequestDto) { + + log.info("Updating issue with identifier: {}", issueIdentifier); + + Issue existingIssue = issueRepository.findById(issueIdentifier) + .orElseThrow(() -> new ResourceNotFoundException( + "Issue not found with identifier: " + issueIdentifier)); + + issueMapper.updateEntityFromDto(issueCreateRequestDto, existingIssue); + + Issue updatedIssue = issueRepository.save(existingIssue); + + log.info("Issue updated successfully with identifier: {}", issueIdentifier); + + return issueMapper.toResponse(updatedIssue); + } + + @Override + public List getIssuesByProject(String projectIdentifier) { + + log.info("Fetching all issues for project: {}", projectIdentifier); + + UUID projectId = UUID.fromString(projectIdentifier); + + // Validate project exists + projectRepository.findByProjectIdentifier(projectId) + .orElseThrow(() -> new NoSuchElementException( + "Project not found with identifier: " + projectIdentifier)); + + return issueRepository.findByProjectIdentifier(projectId) + .stream() + .map(issueMapper::toResponse) + .toList(); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/MeetingServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/MeetingServiceImpl.java new file mode 100644 index 0000000..41a1fb0 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/MeetingServiceImpl.java @@ -0,0 +1,98 @@ +package com.ikon.projectmanagement.service.impl; + +import com.ikon.projectmanagement.dto.request.MeetingRequestDTO; +import com.ikon.projectmanagement.dto.response.MeetingResponseDTO; +import com.ikon.projectmanagement.entity.Meeting; +import com.ikon.projectmanagement.mapper.MeetingMapper; +import com.ikon.projectmanagement.repository.MeetingRepository; +import com.ikon.projectmanagement.service.MeetingService; +import com.ikon.webservice.WebService; + +import lombok.RequiredArgsConstructor; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class MeetingServiceImpl extends WebService implements MeetingService { + + @Autowired + private MeetingMapper meetingMapper; + + @Autowired + private MeetingRepository meetingRepository; + + @Override + @Transactional + public MeetingResponseDTO createMeeting(MeetingRequestDTO meetingRequestDTO) { + + UUID accountId = getActiveAccountId(); + UUID createdBy = getCurrentUserId(); + + Meeting meeting = meetingMapper.toEntity(meetingRequestDTO); + + meeting.setAccountId(accountId); + meeting.setCreatedBy(createdBy); + + Meeting savedMeeting = meetingRepository.save(meeting); + + return meetingMapper.toResponseDTO(savedMeeting); + } + + @Override + @Transactional(readOnly = true) + public List getAllMeetings(UUID projectIdentifier) { + + List meetings = meetingRepository.findByProjectIdentifier(projectIdentifier); + + return meetingMapper.toResponseDTOList(meetings); + } + + @Override + @Transactional(readOnly = true) + public List getMeetingsByProjectIdentifier(String projectIdentifier) { + + List meetings = meetingRepository.findByProjectIdentifier(UUID.fromString(projectIdentifier)); + + return meetingMapper.toResponseDTOList(meetings); + } + + @Override + @Transactional(readOnly = true) + public MeetingResponseDTO getMeetingById(UUID meetingId) { + + Meeting meeting = meetingRepository.findById(meetingId) + .orElseThrow(() -> new RuntimeException("Meeting not found with id: " + meetingId)); + + return meetingMapper.toResponseDTO(meeting); + } + + @Override + @Transactional + public MeetingResponseDTO updateMeeting(UUID meetingId, MeetingRequestDTO meetingRequestDTO) { + + Meeting existingMeeting = meetingRepository.findById(meetingId) + .orElseThrow(() -> new RuntimeException("Meeting not found with id: " + meetingId)); + + meetingMapper.updateEntityFromDTO(existingMeeting, meetingRequestDTO); + + Meeting updatedMeeting = meetingRepository.save(existingMeeting); + + return meetingMapper.toResponseDTO(updatedMeeting); + } + + @Override + @Transactional + public void deleteMeeting(UUID meetingId) { + + Meeting meeting = meetingRepository.findById(meetingId) + .orElseThrow(() -> new RuntimeException("Meeting not found with id: " + meetingId)); + + meetingRepository.delete(meeting); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProductOfProjectServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProductOfProjectServiceImpl.java new file mode 100644 index 0000000..8581a4d --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProductOfProjectServiceImpl.java @@ -0,0 +1,213 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.ikon.projectmanagement.dto.request.ProductOfProjectRequestDto; +import com.ikon.projectmanagement.dto.response.ProductExpenseResponseDto; +import com.ikon.projectmanagement.dto.response.ProductOfProjectResponseDto; +import com.ikon.projectmanagement.entity.ProductOfProject; +import com.ikon.projectmanagement.entity.ProductOfProjectExpenseDetail; +import com.ikon.projectmanagement.mapper.ProductOfProjectMapper; +import com.ikon.projectmanagement.repository.ProductOfProjectRepository; +import com.ikon.projectmanagement.repository.ProjectScheduleRepository; +import com.ikon.projectmanagement.service.ProductOfProjectService; +import com.ikon.projectmanagement.service.ScheduleService; +import com.ikon.webservice.WebService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ProductOfProjectServiceImpl extends WebService implements ProductOfProjectService { + + private final ProductOfProjectMapper productMapper; + private final ProductOfProjectRepository productRepository; + private final ScheduleService scheduleService; + private final ProjectScheduleRepository projectScheduleRepository; + + // Valid workflow transitions: currentStatus -> Set of allowed targetStatuses + private static final Map> VALID_TRANSITIONS = Map.of( + // Forward transitions + "Product Created", Set.of("Schedule Submitted From Product"), + "Schedule Submitted From Product", Set.of("Submitted Resources and Expenses For Product", + "Recall Schedule from Resource & Expense"), + // "Submitted Resources and Expenses For Product", Set.of("Closed", + // "Recall Schedule from Resource & Expense"), + // "Closed", Set.of("Recall Resources & Expenses from Closed"), + + // Also allow transitions from recall statuses + // "Recall Product Created from Schedule", Set.of("Schedule Submitted From + // Product"), + "Recall Schedule from Resource & Expense", Set.of("Schedule Submitted From Product") + // "Recall Resources & Expenses from Closed", Set.of("Closed", + // "Recall Schedule from Resource & Expense") + ); + + // The target status that requires schedule data to exist + private static final String REQUIRES_SCHEDULE = "Schedule Submitted From Product"; + + @Override + @Transactional(readOnly = true) + public List getProductsByProject(UUID projectIdentifier) { + + UUID accountId = getActiveAccountId(); + var scheduleData = scheduleService.getSchedule(projectIdentifier, null); + + return productRepository + .findByAccountIdAndProjectIdentifier(accountId, projectIdentifier) + .stream() + .map(p -> { + ProductOfProjectResponseDto dto = productMapper.toResponse(p); + dto.setScheduleData(scheduleData); + return dto; + }) + .toList(); + } + + @Override + @Transactional(readOnly = true) + public ProductOfProjectResponseDto getProduct(UUID projectIdentifier, UUID productIdentifier) { + + UUID accountId = getActiveAccountId(); + + ProductOfProject product = productRepository + .findByAccountIdAndProjectIdentifierAndProductIdentifier( + accountId, projectIdentifier, productIdentifier) + .orElseThrow(() -> new RuntimeException("Product not found")); + + ProductOfProjectResponseDto dto = productMapper.toResponse(product); + dto.setScheduleData(scheduleService.getSchedule(projectIdentifier, null)); + return dto; + } + + @Override + @Transactional + public ProductOfProjectResponseDto updateProduct(UUID projectIdentifier, UUID productIdentifier, + ProductOfProjectRequestDto dto) { + UUID accountId = getActiveAccountId(); + + ProductOfProject product = productRepository + .findByAccountIdAndProjectIdentifierAndProductIdentifier(accountId, projectIdentifier, + productIdentifier) + .orElseThrow(() -> new RuntimeException("Product not found")); + + productMapper.updateEntity(product, dto); + + if (dto.getExpenseDetails() != null) { + Map existingExpenses = product.getExpenseDetails(); + Map incomingExpenses = dto.getExpenseDetails(); + + existingExpenses.keySet().removeIf(id -> !incomingExpenses.containsKey(id)); + + for (Map.Entry entry : incomingExpenses.entrySet()) { + UUID incomingId = entry.getKey(); + ProductExpenseResponseDto expenseDto = entry.getValue(); + + if (incomingId != null && existingExpenses.containsKey(incomingId)) { + ProductOfProjectExpenseDetail existing = existingExpenses.get(incomingId); + productMapper.updateExpenseEntity(existing, expenseDto); + } else { + ProductOfProjectExpenseDetail newExpense = productMapper + .toExpenseEntity(expenseDto); + newExpense.setProductPS(product); + + existingExpenses.put(UUID.randomUUID(), newExpense); + } + } + } + + ProductOfProject saved = productRepository.save(product); + return productMapper.toResponse(saved); + } + + @Override + @Transactional + public ProductOfProjectResponseDto transitionStatus( + UUID projectIdentifier, + UUID productIdentifier, + String targetStatus) { + + UUID accountId = getActiveAccountId(); + + ProductOfProject product = productRepository + .findByAccountIdAndProjectIdentifierAndProductIdentifier( + accountId, projectIdentifier, productIdentifier) + .orElseThrow(() -> new RuntimeException("Product not found")); + + String currentStatus = product.getProductStatus(); + log.info("Workflow transition requested: '{}' -> '{}' for product {}", + currentStatus, targetStatus, productIdentifier); + + // Validate that this transition is allowed + Set allowedTargets = VALID_TRANSITIONS.get(currentStatus); + log.info("Allowed target statuses for current status '{}': {}", currentStatus, allowedTargets); + if (allowedTargets == null || !allowedTargets.contains(targetStatus)) { + throw new IllegalStateException( + "Transition from '" + currentStatus + "' to '" + targetStatus + + "' is not allowed."); + } + + // Special validation: Schedule -> Resources & Expenses requires schedule data + if (REQUIRES_SCHEDULE.equals(targetStatus)) { + boolean hasScheduleData = checkScheduleDataExists(projectIdentifier, productIdentifier, + accountId); + if (!hasScheduleData) { + throw new IllegalStateException( + "Cannot move to Resources & Expenses: No schedule data found. " + + "Please create a schedule before proceeding."); + } + } + + // Perform the transition + product.setProductStatus(targetStatus); + ProductOfProject saved = productRepository.save(product); + + log.info("Workflow transition completed: '{}' -> '{}' for product {}", + currentStatus, targetStatus, productIdentifier); + + return productMapper.toResponse(saved); + } + + /** + * Checks if schedule data exists by looking up: + * 1. Project schedule (by projectIdentifier) + * 2. Product schedule data (by productIdentifier — stored on the product + * entity) + * If either has tasks, returns true. + */ + private boolean checkScheduleDataExists(UUID projectIdentifier, UUID productIdentifier, UUID accountId) { + // Check 1: Project-level schedule + boolean hasProjectSchedule = projectScheduleRepository + .findByAccountIdAndProjectIdentifier(accountId, projectIdentifier) + .map(schedule -> schedule.getTasks() != null && !schedule.getTasks().isEmpty()) + .orElse(false); + + if (hasProjectSchedule) { + log.debug("Schedule data found via project schedule for project {}", projectIdentifier); + return true; + } + + // Check 2: Product-level schedule data + boolean hasProductSchedule = projectScheduleRepository + .findByAccountIdAndProductIdentifier(accountId, productIdentifier) + .map(schedule -> schedule.getTasks() != null && !schedule.getTasks().isEmpty()) + .orElse(false); + + if (hasProductSchedule) { + log.debug("Schedule data found via product schedule for product {}", productIdentifier); + return true; + } + + log.warn("No schedule data found for project {} or product {}", projectIdentifier, productIdentifier); + return false; + } + +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProductResourceAllocationServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProductResourceAllocationServiceImpl.java new file mode 100644 index 0000000..7ac638a --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProductResourceAllocationServiceImpl.java @@ -0,0 +1,89 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.List; +import java.util.UUID; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.ikon.projectmanagement.dto.request.ProductPSResourceAllocationRequestDto; +import com.ikon.projectmanagement.dto.response.ProductPSResourceAllocationResponseDto; +import com.ikon.projectmanagement.entity.ProductOfProject; +import com.ikon.projectmanagement.entity.ProductPSResourceAllocation; +import com.ikon.projectmanagement.mapper.ProductResourceAllocationMapper; +import com.ikon.projectmanagement.repository.ProductOfProjectRepository; +import com.ikon.projectmanagement.service.ProductResourceAllocationService; +import com.ikon.webservice.WebService; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ProductResourceAllocationServiceImpl extends WebService implements ProductResourceAllocationService { + + private final ProductOfProjectRepository productRepository; + private final ProductResourceAllocationMapper allocationMapper; + + private ProductOfProject getProduct(UUID productIdentifier) { + UUID accountId = getActiveAccountId(); + return productRepository + .findByAccountIdAndProductIdentifier(accountId, productIdentifier) + .orElseThrow(() -> new RuntimeException("Product not found")); + } + + @Override + @Transactional(readOnly = true) + public List getResourceAllocations(UUID productIdentifier) { + ProductOfProject product = getProduct(productIdentifier); + return product.getResourceDataWithAllocation().stream() + .map(allocationMapper::toResponse) + .toList(); + } + + @Override + @Transactional(readOnly = true) + public ProductPSResourceAllocationResponseDto getResourceAllocation(UUID productIdentifier, UUID allocationIdentifier) { + ProductOfProject product = getProduct(productIdentifier); + ProductPSResourceAllocation allocation = product.getResourceDataWithAllocation().stream() + .filter(a -> a.getId().equals(allocationIdentifier)) + .findFirst() + .orElseThrow(() -> new RuntimeException("Allocation not found")); + + return allocationMapper.toResponse(allocation); + } + + @Override + @Transactional + public ProductPSResourceAllocationResponseDto createResourceAllocation(UUID productIdentifier, ProductPSResourceAllocationRequestDto dto) { + ProductOfProject product = getProduct(productIdentifier); + ProductPSResourceAllocation allocation = allocationMapper.toEntity(dto, product); + product.getResourceDataWithAllocation().add(allocation); + productRepository.save(product); + return allocationMapper.toResponse(allocation); + } + + @Override + @Transactional + public ProductPSResourceAllocationResponseDto updateResourceAllocation(UUID productIdentifier, UUID allocationIdentifier, ProductPSResourceAllocationRequestDto dto) { + ProductOfProject product = getProduct(productIdentifier); + ProductPSResourceAllocation allocation = product.getResourceDataWithAllocation().stream() + .filter(a -> a.getId().equals(allocationIdentifier)) + .findFirst() + .orElseThrow(() -> new RuntimeException("Allocation not found")); + + allocationMapper.updateEntity(allocation, dto); + productRepository.save(product); + return allocationMapper.toResponse(allocation); + } + + @Override + @Transactional + public void deleteResourceAllocation(UUID productIdentifier, UUID allocationIdentifier) { + ProductOfProject product = getProduct(productIdentifier); + boolean removed = product.getResourceDataWithAllocation().removeIf(a -> a.getId().equals(allocationIdentifier)); + if (!removed) { + throw new RuntimeException("Allocation not found"); + } + productRepository.save(product); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProjectServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProjectServiceImpl.java new file mode 100644 index 0000000..b693a0c --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ProjectServiceImpl.java @@ -0,0 +1,139 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; + +import com.ikon.projectmanagement.dto.request.ProjectRequestDto; +import com.ikon.projectmanagement.dto.response.ProjectResponseDto; +import com.ikon.projectmanagement.dto.response.ProjectTimelineResponseDto; +import com.ikon.projectmanagement.entity.ProductOfProject; +import com.ikon.projectmanagement.entity.Project; +import com.ikon.projectmanagement.mapper.ProjectMapper; +import com.ikon.projectmanagement.repository.ProductOfProjectRepository; +import com.ikon.projectmanagement.repository.ProjectRepository; +import com.ikon.projectmanagement.service.ProjectService; +import com.ikon.webservice.WebService; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.apache.kafka.common.errors.ResourceNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ProjectServiceImpl extends WebService implements ProjectService { + + private final ProjectRepository projectRepository; + private final ProductOfProjectRepository productOfProjectRepository; + private final ProjectMapper projectMapper; + + // private final IkonServiceClient ikonServiceClient; + + @Override + @Transactional + public ProjectResponseDto createProject(ProjectRequestDto projectDto) { + + Project project = projectMapper.toEntity(projectDto); + + UUID accountId = getActiveAccountId(); + UUID createdById = getCurrentUserId(); + + String createdAt = LocalDateTime.now().toString(); + + project.setAccountId(accountId); + project.setProjectStatus("Ongoing"); + + Project savedProject = projectRepository.save(project); + + ProductOfProject product = new ProductOfProject(); + product.setAccountId(accountId); + product.setCreatedBy(createdById); + product.setCreatedOn(createdAt); + product.setProductType(projectDto.getProductType()); + product.setProductStatus("Product Created"); + + product.setProjectIdentifier(savedProject.getProjectIdentifier()); + product.setProjectName(savedProject.getProjectName()); + product.setProjectManager(savedProject.getProjectManager()); + + ProductOfProject savedProduct = productOfProjectRepository.save(product); + + savedProject.setProduct(savedProduct); + projectRepository.save(savedProject); + + return projectMapper.toResponse(savedProject); + } + + @Override + public List getAllProjects() { + + UUID activeAccountId = getActiveAccountId(); + + List projectList = projectRepository.findByAccountId(activeAccountId); + + return projectList.stream() + .map(projectMapper::toResponse) + .toList(); + } + + @Override + public ProjectResponseDto getProjectByProjectIdentifier(UUID projectIdentifier) { + Project project = projectRepository + .findByProjectIdentifier(projectIdentifier) + .orElseThrow(() -> new NoSuchElementException( + "Project not found with identifier: " + projectIdentifier)); + + return projectMapper.toResponse(project); + } + + @Override + @Transactional + public ProjectResponseDto updateProject(UUID projectIdentifier, ProjectRequestDto projectDto) { + + Project existingProject = projectRepository.findById(projectIdentifier) + .orElseThrow(() -> new ResourceNotFoundException( + "Project not found with id: " + projectIdentifier)); + + projectMapper.updateEntityFromDto(projectDto, existingProject); + + existingProject.setUpdatedOn(LocalDate.now()); + existingProject.setUpdatedBy(projectDto.getUpdatedBy()); + + Project updatedProject = projectRepository.save(existingProject); + + return projectMapper.toResponse(updatedProject); + } + + @Override + public List getAllActiveProjectsTimeline() { + // Projects are created with status "Ongoing" (see createProject), so the + // active-timeline must query that value — "ACTIVE" never matched anything. + List activeProjects = projectRepository + .findByProjectStatusIgnoreCase("Ongoing"); + + return activeProjects.stream() + .map(project -> ProjectTimelineResponseDto.builder() + .projectIdentifier( + project.getProjectIdentifier() != null + ? project.getProjectIdentifier() + : null) + .projectName(project.getProjectName()) + .startDate( + project.getContractedStartDate() != null + ? project.getContractedStartDate().toString() + : null) + .endDate( + project.getContractedEndDate() != null + ? project.getContractedEndDate().toString() + : null) + .build()) + .toList(); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/RiskServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/RiskServiceImpl.java new file mode 100644 index 0000000..106b2e7 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/RiskServiceImpl.java @@ -0,0 +1,118 @@ +package com.ikon.projectmanagement.service.impl; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; + +import com.ikon.projectmanagement.dto.request.RiskCreateRequestDto; +import com.ikon.projectmanagement.dto.response.RiskResponseDto; +import com.ikon.projectmanagement.entity.Risks; +import com.ikon.projectmanagement.mapper.RiskMapper; +import com.ikon.projectmanagement.repository.ProjectRepository; +import com.ikon.projectmanagement.repository.RiskRepository; +import com.ikon.projectmanagement.service.RiskService; +import com.ikon.webservice.WebService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.apache.kafka.common.errors.ResourceNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Slf4j +public class RiskServiceImpl extends WebService implements RiskService { + + private final RiskRepository riskRepository; + private final ProjectRepository projectRepository; + private final RiskMapper riskMapper; + + @Override + @Transactional + public RiskResponseDto createRisk(RiskCreateRequestDto riskCreateRequestDto) { + + log.info("Creating risk for project: {}", riskCreateRequestDto.getProjectIdentifier()); + + // UUID projectId = UUID.fromString(riskCreateRequestDto.getProjectIdentifier()); + + UUID projectId = riskCreateRequestDto.getProjectIdentifier(); + + projectRepository.findByProjectIdentifier(projectId) + .orElseThrow(() -> new NoSuchElementException( + "Project not found with identifier: " + riskCreateRequestDto.getProjectIdentifier())); + + Risks risk = riskMapper.toEntity(riskCreateRequestDto); + // No more risk.setProject(project) — just set the UUID directly + // risk.setProjectIdentifier(projectId); + + // Risks savedRisk = riskRepository.saveAndFlush(risk); + + + Risks savedRisk = riskRepository.save(risk); + + return riskMapper.toResponse(savedRisk); + } + + @Override + public List getAllRisks() { + + log.info("Fetching all risks"); + + return riskRepository.findAll() + .stream() + .map(riskMapper::toResponse) + .toList(); + } + + @Override + public RiskResponseDto getRiskById(UUID riskIdentifier) { + + log.info("Fetching risk with identifier: {}", riskIdentifier); + + Risks risk = riskRepository.findById(riskIdentifier) + .orElseThrow(() -> new NoSuchElementException( + "Risk not found with identifier: " + riskIdentifier)); + + return riskMapper.toResponse(risk); + } + + @Override + @Transactional + public RiskResponseDto updateRisk(UUID riskIdentifier, RiskCreateRequestDto riskCreateRequestDto) { + + log.info("Updating risk with identifier: {}", riskIdentifier); + + Risks existingRisk = riskRepository.findById(riskIdentifier) + .orElseThrow(() -> new ResourceNotFoundException( + "Risk not found with identifier: " + riskIdentifier)); + + riskMapper.updateEntityFromDto(riskCreateRequestDto, existingRisk); + + Risks updatedRisk = riskRepository.save(existingRisk); + + log.info("Risk updated successfully with identifier: {}", riskIdentifier); + + return riskMapper.toResponse(updatedRisk); + } + + @Override + public List getRisksByProject(String projectIdentifier) { + + log.info("Fetching all risks for project: {}", projectIdentifier); + + UUID projectId = UUID.fromString(projectIdentifier); + + // Validate project exists + projectRepository.findByProjectIdentifier(projectId) + .orElseThrow(() -> new NoSuchElementException( + "Project not found with identifier: " + projectIdentifier)); + + // Updated to use direct field query instead of relationship navigation + return riskRepository.findByProjectIdentifier(projectId) + .stream() + .map(riskMapper::toResponse) + .toList(); + } +} \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/RoleServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..3cbe501 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/RoleServiceImpl.java @@ -0,0 +1,58 @@ +package com.ikon.projectmanagement.service.impl; + +import com.ikon.projectmanagement.dto.request.RoleRequestDto; +import com.ikon.projectmanagement.dto.response.RoleResponseDto; +import com.ikon.projectmanagement.entity.Role; +import com.ikon.projectmanagement.mapper.RoleMapper; +import com.ikon.projectmanagement.repository.RoleRepository; +import com.ikon.projectmanagement.service.RoleService; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class RoleServiceImpl implements RoleService { + + private final RoleRepository roleRepository; + private final RoleMapper roleMapper; + + @Override + public List getAllRoles() { + return roleRepository.findAll().stream() + .map(roleMapper::toResponseDto) + .collect(Collectors.toList()); + } + + @Override + public RoleResponseDto getRoleById(UUID id) { + Role role = roleRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Role not found with ID: " + id)); + return roleMapper.toResponseDto(role); + } + + @Override + public RoleResponseDto createRole(RoleRequestDto dto) { + Role role = roleMapper.toEntity(dto); + Role savedRole = roleRepository.save(role); + return roleMapper.toResponseDto(savedRole); + } + + @Override + public RoleResponseDto updateRole(UUID id, RoleRequestDto dto) { + Role role = roleRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Role not found with ID: " + id)); + roleMapper.updateEntity(role, dto); + Role updatedRole = roleRepository.save(role); + return roleMapper.toResponseDto(updatedRole); + } + + @Override + public void deleteRole(UUID id) { + Role role = roleRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Role not found with ID: " + id)); + roleRepository.delete(role); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ScheduleServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ScheduleServiceImpl.java new file mode 100644 index 0000000..310b426 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/ScheduleServiceImpl.java @@ -0,0 +1,127 @@ +package com.ikon.projectmanagement.service.impl; + +import com.ikon.projectmanagement.dto.request.ScheduleDependencyDto; +import com.ikon.projectmanagement.dto.request.ScheduleGroupDto; +import com.ikon.projectmanagement.dto.request.ScheduleRequestDto; +import com.ikon.projectmanagement.dto.request.ScheduleTaskDto; +import com.ikon.projectmanagement.dto.response.ScheduleResponseDto; +import com.ikon.projectmanagement.entity.ProductOfProject; +import com.ikon.projectmanagement.entity.ProjectSchedule; +import com.ikon.projectmanagement.mapper.ScheduleMapper; +import com.ikon.projectmanagement.repository.ProductOfProjectRepository; +import com.ikon.projectmanagement.repository.ProjectScheduleRepository; +import com.ikon.projectmanagement.service.ScheduleService; +import com.ikon.webservice.WebService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ScheduleServiceImpl extends WebService implements ScheduleService { + + private final ProjectScheduleRepository scheduleRepository; + private final ProductOfProjectRepository productOfProjectRepository; + private final ScheduleMapper scheduleMapper; + + @PersistenceContext + private EntityManager entityManager; + + private ProjectSchedule getOrCreateSchedule(UUID projectIdentifier) { + UUID accountId = getActiveAccountId(); + return scheduleRepository + .findByAccountIdAndProjectIdentifier(accountId, projectIdentifier) + .orElseGet(() -> { + UUID productId = productOfProjectRepository + .findByAccountIdAndProjectIdentifier(accountId, projectIdentifier) + .stream().findFirst() + .map(ProductOfProject::getProductIdentifier) + .orElse(null); + ProjectSchedule newSchedule = ProjectSchedule.builder() + .projectIdentifier(projectIdentifier) + .productIdentifier(productId) + .accountId(accountId) + .build(); + return scheduleRepository.save(newSchedule); + }); + } + + @Override + @Transactional + public ScheduleResponseDto saveSchedule(UUID projectIdentifier, ScheduleRequestDto dto, String accessToken) { + log.debug("saveSchedule called for project: {}", projectIdentifier); + ProjectSchedule schedule = getOrCreateSchedule(projectIdentifier); + + // Clear existing data — orphanRemoval = true handles DB deletion + schedule.getTasks().clear(); + schedule.getDependencies().clear(); + schedule.getGroups().clear(); + + // Flush DELETEs first to avoid PK conflicts when re-inserting same IDs + entityManager.flush(); + + // Repopulate tasks + List tasks = dto.getTask(); + if (tasks != null) { + for (ScheduleTaskDto taskDto : tasks) { + schedule.getTasks().add(scheduleMapper.toTaskEntity(taskDto, schedule)); + } + } + + // Repopulate dependencies + List dependencies = dto.getDependency(); + if (dependencies != null) { + for (ScheduleDependencyDto depDto : dependencies) { + schedule.getDependencies().add(scheduleMapper.toDependencyEntity(depDto, schedule)); + } + } + + // Repopulate groups + Map groups = dto.getGroup(); + if (groups != null) { + for (Map.Entry entry : groups.entrySet()) { + schedule.getGroups().add(scheduleMapper.toGroupEntity(entry.getKey(), entry.getValue(), schedule)); + } + } + + ProjectSchedule saved = scheduleRepository.save(schedule); + log.debug("Schedule saved for project {}: {} tasks, {} dependencies, {} groups", + projectIdentifier, + saved.getTasks().size(), + saved.getDependencies().size(), + saved.getGroups().size()); + + return scheduleMapper.toResponse(saved); + } + + @Override + @Transactional(readOnly = true) + public ScheduleResponseDto getSchedule(UUID projectIdentifier, String accessToken) { + UUID accountId = getActiveAccountId(); + return scheduleRepository + .findByAccountIdAndProjectIdentifier(accountId, projectIdentifier) + .map(scheduleMapper::toResponse) + .orElse(new ScheduleResponseDto(projectIdentifier, null, new ArrayList<>(), new ArrayList<>(), new LinkedHashMap<>())); + } + + @Override + @Transactional(readOnly = true) + public List getAllSchedules() { + UUID accountId = getActiveAccountId(); + return scheduleRepository + .findAllByAccountId(accountId) + .stream() + .map(scheduleMapper::toResponse) + .toList(); + } +} diff --git a/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/WorkingDayServiceImpl.java b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/WorkingDayServiceImpl.java new file mode 100644 index 0000000..50675b7 --- /dev/null +++ b/backend/projectmanagement-server/src/main/java/com/ikon/projectmanagement/service/impl/WorkingDayServiceImpl.java @@ -0,0 +1,58 @@ +package com.ikon.projectmanagement.service.impl; + +import com.ikon.projectmanagement.dto.response.WorkingDaysMonthDto; +import com.ikon.projectmanagement.dto.response.WorkingDaysResponseDto; +import com.ikon.projectmanagement.entity.WorkingDaysEntity; +import com.ikon.projectmanagement.repository.WorkingDaysRepository; +import com.ikon.projectmanagement.service.WorkingDayService; +import jakarta.persistence.EntityNotFoundException; +import java.util.HashMap; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class WorkingDayServiceImpl implements WorkingDayService { + + private final WorkingDaysRepository workingDayRepository; + + @Override + public Page getAllWorkingDays(Pageable pageable) { + return workingDayRepository.findAll(pageable) + .map(this::mapToResponseDto); + } + + @Override + public WorkingDaysResponseDto getWorkingDaysByYear(String year) { + WorkingDaysEntity entity = workingDayRepository.findByYear(year) + .orElseThrow(() -> new EntityNotFoundException( + "Working days not found for year: " + year)); + + return mapToResponseDto(entity); + } + + private WorkingDaysResponseDto mapToResponseDto(WorkingDaysEntity entity) { + Map> detailsMap = new HashMap<>(); + + entity.getWorkingDaysDetails().values().forEach(detail -> { + WorkingDaysMonthDto monthDto = new WorkingDaysMonthDto(); + monthDto.setYear(detail.getYear()); + monthDto.setMonth(detail.getMonth()); + monthDto.setWorkingDays(detail.getWorkingDays()); + + // outer key = year, inner key = month + detailsMap + .computeIfAbsent(detail.getYear(), y -> new HashMap<>()) + .put(detail.getMonth(), monthDto); + }); + + WorkingDaysResponseDto responseDto = new WorkingDaysResponseDto(); + responseDto.setWorkingDaysDetails(detailsMap); + responseDto.setAccountIdentifier(entity.getAccountIdentifier()); + responseDto.setWorkingId(entity.getWorkingId()); + return responseDto; + } +} diff --git a/backend/projectmanagement-server/src/main/resources/activiti.engine.schema.sql b/backend/projectmanagement-server/src/main/resources/activiti.engine.schema.sql new file mode 100644 index 0000000..ce1dd9e --- /dev/null +++ b/backend/projectmanagement-server/src/main/resources/activiti.engine.schema.sql @@ -0,0 +1,1502 @@ +-- Modified version of script at (https://raw.githubusercontent.com/Activiti/Activiti/refs/tags/activiti-6.0.0/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mysql.create.engine.sql) + +start transaction; + +create table if not exists ACT_GE_PROPERTY ( + NAME_ varchar(64), + VALUE_ varchar(300), + REV_ integer, + primary key (NAME_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +insert ignore into ACT_GE_PROPERTY +values ('schema.version', '6.0.0.4', 1); + +insert ignore into ACT_GE_PROPERTY +values ('schema.history', 'create(6.0.0.4)', 1); + +insert ignore into ACT_GE_PROPERTY +values ('next.dbid', '1', 1); + +create table if not exists ACT_GE_BYTEARRAY ( + ID_ varchar(64), + REV_ integer, + NAME_ varchar(255), + DEPLOYMENT_ID_ varchar(64), + BYTES_ LONGBLOB, + GENERATED_ TINYINT, + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RE_DEPLOYMENT ( + ID_ varchar(64), + NAME_ varchar(255), + CATEGORY_ varchar(255), + KEY_ varchar(255), + TENANT_ID_ varchar(255) default '', + DEPLOY_TIME_ timestamp(3) NULL, + ENGINE_VERSION_ varchar(255), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RE_MODEL ( + ID_ varchar(64) not null, + REV_ integer, + NAME_ varchar(255), + KEY_ varchar(255), + CATEGORY_ varchar(255), + CREATE_TIME_ timestamp(3) null, + LAST_UPDATE_TIME_ timestamp(3) null, + VERSION_ integer, + META_INFO_ varchar(4000), + DEPLOYMENT_ID_ varchar(64), + EDITOR_SOURCE_VALUE_ID_ varchar(64), + EDITOR_SOURCE_EXTRA_VALUE_ID_ varchar(64), + TENANT_ID_ varchar(255) default '', + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RU_EXECUTION ( + ID_ varchar(64), + REV_ integer, + PROC_INST_ID_ varchar(64), + BUSINESS_KEY_ varchar(255), + PARENT_ID_ varchar(64), + PROC_DEF_ID_ varchar(64), + SUPER_EXEC_ varchar(64), + ROOT_PROC_INST_ID_ varchar(64), + ACT_ID_ varchar(255), + IS_ACTIVE_ TINYINT, + IS_CONCURRENT_ TINYINT, + IS_SCOPE_ TINYINT, + IS_EVENT_SCOPE_ TINYINT, + IS_MI_ROOT_ TINYINT, + SUSPENSION_STATE_ integer, + CACHED_ENT_STATE_ integer, + TENANT_ID_ varchar(255) default '', + NAME_ varchar(255), + START_TIME_ datetime(3), + START_USER_ID_ varchar(255), + LOCK_TIME_ timestamp(3) NULL, + IS_COUNT_ENABLED_ TINYINT, + EVT_SUBSCR_COUNT_ integer, + TASK_COUNT_ integer, + JOB_COUNT_ integer, + TIMER_JOB_COUNT_ integer, + SUSP_JOB_COUNT_ integer, + DEADLETTER_JOB_COUNT_ integer, + VAR_COUNT_ integer, + ID_LINK_COUNT_ integer, + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RU_JOB ( + ID_ varchar(64) NOT NULL, + REV_ integer, + TYPE_ varchar(255) NOT NULL, + LOCK_EXP_TIME_ timestamp(3) NULL, + LOCK_OWNER_ varchar(255), + EXCLUSIVE_ boolean, + EXECUTION_ID_ varchar(64), + PROCESS_INSTANCE_ID_ varchar(64), + PROC_DEF_ID_ varchar(64), + RETRIES_ integer, + EXCEPTION_STACK_ID_ varchar(64), + EXCEPTION_MSG_ varchar(4000), + DUEDATE_ timestamp(3) NULL, + REPEAT_ varchar(255), + HANDLER_TYPE_ varchar(255), + HANDLER_CFG_ varchar(4000), + TENANT_ID_ varchar(255) default '', + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RU_TIMER_JOB ( + ID_ varchar(64) NOT NULL, + REV_ integer, + TYPE_ varchar(255) NOT NULL, + LOCK_EXP_TIME_ timestamp(3) NULL, + LOCK_OWNER_ varchar(255), + EXCLUSIVE_ boolean, + EXECUTION_ID_ varchar(64), + PROCESS_INSTANCE_ID_ varchar(64), + PROC_DEF_ID_ varchar(64), + RETRIES_ integer, + EXCEPTION_STACK_ID_ varchar(64), + EXCEPTION_MSG_ varchar(4000), + DUEDATE_ timestamp(3) NULL, + REPEAT_ varchar(255), + HANDLER_TYPE_ varchar(255), + HANDLER_CFG_ varchar(4000), + TENANT_ID_ varchar(255) default '', + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RU_SUSPENDED_JOB ( + ID_ varchar(64) NOT NULL, + REV_ integer, + TYPE_ varchar(255) NOT NULL, + EXCLUSIVE_ boolean, + EXECUTION_ID_ varchar(64), + PROCESS_INSTANCE_ID_ varchar(64), + PROC_DEF_ID_ varchar(64), + RETRIES_ integer, + EXCEPTION_STACK_ID_ varchar(64), + EXCEPTION_MSG_ varchar(4000), + DUEDATE_ timestamp(3) NULL, + REPEAT_ varchar(255), + HANDLER_TYPE_ varchar(255), + HANDLER_CFG_ varchar(4000), + TENANT_ID_ varchar(255) default '', + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RU_DEADLETTER_JOB ( + ID_ varchar(64) NOT NULL, + REV_ integer, + TYPE_ varchar(255) NOT NULL, + EXCLUSIVE_ boolean, + EXECUTION_ID_ varchar(64), + PROCESS_INSTANCE_ID_ varchar(64), + PROC_DEF_ID_ varchar(64), + EXCEPTION_STACK_ID_ varchar(64), + EXCEPTION_MSG_ varchar(4000), + DUEDATE_ timestamp(3) NULL, + REPEAT_ varchar(255), + HANDLER_TYPE_ varchar(255), + HANDLER_CFG_ varchar(4000), + TENANT_ID_ varchar(255) default '', + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RE_PROCDEF ( + ID_ varchar(64) not null, + REV_ integer, + CATEGORY_ varchar(255), + NAME_ varchar(255), + KEY_ varchar(255) not null, + VERSION_ integer not null, + DEPLOYMENT_ID_ varchar(64), + RESOURCE_NAME_ varchar(4000), + DGRM_RESOURCE_NAME_ varchar(4000), + DESCRIPTION_ varchar(4000), + HAS_START_FORM_KEY_ TINYINT, + HAS_GRAPHICAL_NOTATION_ TINYINT, + SUSPENSION_STATE_ integer, + TENANT_ID_ varchar(255) default '', + ENGINE_VERSION_ varchar(255), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RU_TASK ( + ID_ varchar(64), + REV_ integer, + EXECUTION_ID_ varchar(64), + PROC_INST_ID_ varchar(64), + PROC_DEF_ID_ varchar(64), + NAME_ varchar(255), + PARENT_TASK_ID_ varchar(64), + DESCRIPTION_ varchar(4000), + TASK_DEF_KEY_ varchar(255), + OWNER_ varchar(255), + ASSIGNEE_ varchar(255), + DELEGATION_ varchar(64), + PRIORITY_ integer, + CREATE_TIME_ timestamp(3) NULL, + DUE_DATE_ datetime(3), + CATEGORY_ varchar(255), + SUSPENSION_STATE_ integer, + TENANT_ID_ varchar(255) default '', + FORM_KEY_ varchar(255), + CLAIM_TIME_ datetime(3), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RU_IDENTITYLINK ( + ID_ varchar(64), + REV_ integer, + GROUP_ID_ varchar(255), + TYPE_ varchar(255), + USER_ID_ varchar(255), + TASK_ID_ varchar(64), + PROC_INST_ID_ varchar(64), + PROC_DEF_ID_ varchar(64), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RU_VARIABLE ( + ID_ varchar(64) not null, + REV_ integer, + TYPE_ varchar(255) not null, + NAME_ varchar(255) not null, + EXECUTION_ID_ varchar(64), + PROC_INST_ID_ varchar(64), + TASK_ID_ varchar(64), + BYTEARRAY_ID_ varchar(64), + DOUBLE_ double, + LONG_ bigint, + TEXT_ varchar(4000), + TEXT2_ varchar(4000), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_RU_EVENT_SUBSCR ( + ID_ varchar(64) not null, + REV_ integer, + EVENT_TYPE_ varchar(255) not null, + EVENT_NAME_ varchar(255), + EXECUTION_ID_ varchar(64), + PROC_INST_ID_ varchar(64), + ACTIVITY_ID_ varchar(64), + CONFIGURATION_ varchar(255), + CREATED_ timestamp(3) not null DEFAULT CURRENT_TIMESTAMP(3), + PROC_DEF_ID_ varchar(64), + TENANT_ID_ varchar(255) default '', + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_EVT_LOG ( + LOG_NR_ bigint auto_increment, + TYPE_ varchar(64), + PROC_DEF_ID_ varchar(64), + PROC_INST_ID_ varchar(64), + EXECUTION_ID_ varchar(64), + TASK_ID_ varchar(64), + TIME_STAMP_ timestamp(3) not null, + USER_ID_ varchar(255), + DATA_ LONGBLOB, + LOCK_OWNER_ varchar(255), + LOCK_TIME_ timestamp(3) null, + IS_PROCESSED_ tinyint default 0, + primary key (LOG_NR_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_ID_GROUP ( + ID_ varchar(64), + REV_ integer, + NAME_ varchar(255), + TYPE_ varchar(255), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_ID_MEMBERSHIP ( + USER_ID_ varchar(64), + GROUP_ID_ varchar(64), + primary key (USER_ID_, GROUP_ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_ID_USER ( + ID_ varchar(64), + REV_ integer, + FIRST_ varchar(255), + LAST_ varchar(255), + EMAIL_ varchar(255), + PWD_ varchar(255), + PICTURE_ID_ varchar(64), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_ID_INFO ( + ID_ varchar(64), + REV_ integer, + USER_ID_ varchar(64), + TYPE_ varchar(64), + KEY_ varchar(255), + VALUE_ varchar(255), + PASSWORD_ LONGBLOB, + PARENT_ID_ varchar(255), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_HI_PROCINST ( + ID_ varchar(64) not null, + PROC_INST_ID_ varchar(64) not null, + BUSINESS_KEY_ varchar(255), + PROC_DEF_ID_ varchar(64) not null, + START_TIME_ datetime(3) not null, + END_TIME_ datetime(3), + DURATION_ bigint, + START_USER_ID_ varchar(255), + START_ACT_ID_ varchar(255), + END_ACT_ID_ varchar(255), + SUPER_PROCESS_INSTANCE_ID_ varchar(64), + DELETE_REASON_ varchar(4000), + TENANT_ID_ varchar(255) default '', + NAME_ varchar(255), + primary key (ID_), + unique (PROC_INST_ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_HI_ACTINST ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + PROC_INST_ID_ varchar(64) not null, + EXECUTION_ID_ varchar(64) not null, + ACT_ID_ varchar(255) not null, + TASK_ID_ varchar(64), + CALL_PROC_INST_ID_ varchar(64), + ACT_NAME_ varchar(255), + ACT_TYPE_ varchar(255) not null, + ASSIGNEE_ varchar(255), + START_TIME_ datetime(3) not null, + END_TIME_ datetime(3), + DURATION_ bigint, + DELETE_REASON_ varchar(4000), + TENANT_ID_ varchar(255) default '', + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_HI_TASKINST ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64), + TASK_DEF_KEY_ varchar(255), + PROC_INST_ID_ varchar(64), + EXECUTION_ID_ varchar(64), + NAME_ varchar(255), + PARENT_TASK_ID_ varchar(64), + DESCRIPTION_ varchar(4000), + OWNER_ varchar(255), + ASSIGNEE_ varchar(255), + START_TIME_ datetime(3) not null, + CLAIM_TIME_ datetime(3), + END_TIME_ datetime(3), + DURATION_ bigint, + DELETE_REASON_ varchar(4000), + PRIORITY_ integer, + DUE_DATE_ datetime(3), + FORM_KEY_ varchar(255), + CATEGORY_ varchar(255), + TENANT_ID_ varchar(255) default '', + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_HI_VARINST ( + ID_ varchar(64) not null, + PROC_INST_ID_ varchar(64), + EXECUTION_ID_ varchar(64), + TASK_ID_ varchar(64), + NAME_ varchar(255) not null, + VAR_TYPE_ varchar(100), + REV_ integer, + BYTEARRAY_ID_ varchar(64), + DOUBLE_ double, + LONG_ bigint, + TEXT_ varchar(4000), + TEXT2_ varchar(4000), + CREATE_TIME_ datetime(3), + LAST_UPDATED_TIME_ datetime(3), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_HI_DETAIL ( + ID_ varchar(64) not null, + TYPE_ varchar(255) not null, + PROC_INST_ID_ varchar(64), + EXECUTION_ID_ varchar(64), + TASK_ID_ varchar(64), + ACT_INST_ID_ varchar(64), + NAME_ varchar(255) not null, + VAR_TYPE_ varchar(255), + REV_ integer, + TIME_ datetime(3) not null, + BYTEARRAY_ID_ varchar(64), + DOUBLE_ double, + LONG_ bigint, + TEXT_ varchar(4000), + TEXT2_ varchar(4000), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_HI_COMMENT ( + ID_ varchar(64) not null, + TYPE_ varchar(255), + TIME_ datetime(3) not null, + USER_ID_ varchar(255), + TASK_ID_ varchar(64), + PROC_INST_ID_ varchar(64), + ACTION_ varchar(255), + MESSAGE_ varchar(4000), + FULL_MSG_ LONGBLOB, + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_HI_ATTACHMENT ( + ID_ varchar(64) not null, + REV_ integer, + USER_ID_ varchar(255), + NAME_ varchar(255), + DESCRIPTION_ varchar(4000), + TYPE_ varchar(255), + TASK_ID_ varchar(64), + PROC_INST_ID_ varchar(64), + URL_ varchar(4000), + CONTENT_ID_ varchar(64), + TIME_ datetime(3), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create table if not exists ACT_HI_IDENTITYLINK ( + ID_ varchar(64), + GROUP_ID_ varchar(255), + TYPE_ varchar(255), + USER_ID_ varchar(255), + TASK_ID_ varchar(64), + PROC_INST_ID_ varchar(64), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +-- index start -- + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_RU_EXECUTION' + and index_name = 'ACT_IDX_EXEC_BUSKEY' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_RU_EXECUTION' + and index_name = 'ACT_IDC_EXEC_ROOT' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDC_EXEC_ROOT on ACT_RU_EXECUTION(ROOT_PROC_INST_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_RU_TASK' + and index_name = 'ACT_IDX_TASK_CREATE' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_RU_IDENTITYLINK' + and index_name = 'ACT_IDX_IDENT_LNK_USER' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_IDENT_LNK_USER on ACT_RU_IDENTITYLINK(USER_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_RU_IDENTITYLINK' + and index_name = 'ACT_IDX_IDENT_LNK_GROUP' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_IDENT_LNK_GROUP on ACT_RU_IDENTITYLINK(GROUP_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_RU_EVENT_SUBSCR' + and index_name = 'ACT_IDX_EVENT_SUBSCR_CONFIG_' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_EVENT_SUBSCR_CONFIG_ on ACT_RU_EVENT_SUBSCR(CONFIGURATION_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_RU_VARIABLE' + and index_name = 'ACT_IDX_VARIABLE_TASK_ID' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_VARIABLE_TASK_ID on ACT_RU_VARIABLE(TASK_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_RU_IDENTITYLINK' + and index_name = 'ACT_IDX_ATHRZ_PROCEDEF' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_ATHRZ_PROCEDEF on ACT_RU_IDENTITYLINK(PROC_DEF_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_PROCDEF_INFO' + and index_name = 'ACT_IDX_INFO_PROCDEF' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_PROCINST' + and index_name = 'ACT_IDX_HI_PRO_INST_END' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_PRO_INST_END on ACT_HI_PROCINST(END_TIME_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_PROCINST' + and index_name = 'ACT_IDX_HI_PRO_I_BUSKEY' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_PRO_I_BUSKEY on ACT_HI_PROCINST(BUSINESS_KEY_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_ACTINST' + and index_name = 'ACT_IDX_HI_ACT_INST_START' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_ACT_INST_START on ACT_HI_ACTINST(START_TIME_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_ACTINST' + and index_name = 'ACT_IDX_HI_ACT_INST_END' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_ACT_INST_END on ACT_HI_ACTINST(END_TIME_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_DETAIL' + and index_name = 'ACT_IDX_HI_DETAIL_PROC_INST' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_DETAIL_PROC_INST on ACT_HI_DETAIL(PROC_INST_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_DETAIL' + and index_name = 'ACT_IDX_HI_DETAIL_ACT_INST' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_DETAIL_ACT_INST on ACT_HI_DETAIL(ACT_INST_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_DETAIL' + and index_name = 'ACT_IDX_HI_DETAIL_TIME' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_DETAIL_TIME on ACT_HI_DETAIL(TIME_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_DETAIL' + and index_name = 'ACT_IDX_HI_DETAIL_NAME' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_DETAIL_NAME on ACT_HI_DETAIL(NAME_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_DETAIL' + and index_name = 'ACT_IDX_HI_DETAIL_TASK_ID' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_DETAIL_TASK_ID on ACT_HI_DETAIL(TASK_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_VARINST' + and index_name = 'ACT_IDX_HI_PROCVAR_PROC_INST' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_PROCVAR_PROC_INST on ACT_HI_VARINST(PROC_INST_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_VARINST' + and index_name = 'ACT_IDX_HI_PROCVAR_NAME_TYPE' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_PROCVAR_NAME_TYPE on ACT_HI_VARINST(NAME_, VAR_TYPE_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_VARINST' + and index_name = 'ACT_IDX_HI_PROCVAR_TASK_ID' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_PROCVAR_TASK_ID on ACT_HI_VARINST(TASK_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_ACTINST' + and index_name = 'ACT_IDX_HI_ACT_INST_PROCINST' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_ACT_INST_PROCINST on ACT_HI_ACTINST(PROC_INST_ID_, ACT_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_ACTINST' + and index_name = 'ACT_IDX_HI_ACT_INST_EXEC' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_ACT_INST_EXEC on ACT_HI_ACTINST(EXECUTION_ID_, ACT_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_IDENTITYLINK' + and index_name = 'ACT_IDX_HI_IDENT_LNK_USER' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_IDENT_LNK_USER on ACT_HI_IDENTITYLINK(USER_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_IDENTITYLINK' + and index_name = 'ACT_IDX_HI_IDENT_LNK_TASK' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_IDENT_LNK_TASK on ACT_HI_IDENTITYLINK(TASK_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_IDENTITYLINK' + and index_name = 'ACT_IDX_HI_IDENT_LNK_PROCINST' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_IDENT_LNK_PROCINST on ACT_HI_IDENTITYLINK(PROC_INST_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = ( + select count(1) + from information_schema.statistics + where table_schema = database() + and table_name = 'ACT_HI_TASKINST' + and index_name = 'ACT_IDX_HI_TASK_INST_PROCINST' +); + +set @sql = IF(@index_exists = 0, + 'create index ACT_IDX_HI_TASK_INST_PROCINST on ACT_HI_TASKINST(PROC_INST_ID_)', + 'SELECT "Index already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @index_exists = NULL; +set @sql = NULL; + +-- index end -- + +-- constraint start -- + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_GE_BYTEARRAY' + and CONSTRAINT_NAME = 'ACT_FK_BYTEARR_DEPL' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_GE_BYTEARRAY add constraint ACT_FK_BYTEARR_DEPL foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RE_PROCDEF' + and CONSTRAINT_NAME = 'ACT_UNIQ_PROCDEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RE_PROCDEF add constraint ACT_UNIQ_PROCDEF unique (KEY_,VERSION_, TENANT_ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_EXECUTION' + and CONSTRAINT_NAME = 'ACT_FK_EXE_PROCINST' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_EXECUTION add constraint ACT_FK_EXE_PROCINST foreign key (PROC_INST_ID_) references ACT_RU_EXECUTION (ID_) on delete cascade on update cascade', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_EXECUTION' + and CONSTRAINT_NAME = 'ACT_FK_EXE_PARENT' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_EXECUTION add constraint ACT_FK_EXE_PARENT foreign key (PARENT_ID_) references ACT_RU_EXECUTION (ID_) on delete cascade', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_EXECUTION' + and CONSTRAINT_NAME = 'ACT_FK_EXE_SUPER' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_EXECUTION add constraint ACT_FK_EXE_SUPER foreign key (SUPER_EXEC_) references ACT_RU_EXECUTION (ID_) on delete cascade', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_EXECUTION' + and CONSTRAINT_NAME = 'ACT_FK_EXE_PROCDEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_EXECUTION add constraint ACT_FK_EXE_PROCDEF foreign key (PROC_DEF_ID_) references ACT_RE_PROCDEF (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_IDENTITYLINK' + and CONSTRAINT_NAME = 'ACT_FK_TSKASS_TASK' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_IDENTITYLINK add constraint ACT_FK_TSKASS_TASK foreign key (TASK_ID_) references ACT_RU_TASK (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_IDENTITYLINK' + and CONSTRAINT_NAME = 'ACT_FK_ATHRZ_PROCEDEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_IDENTITYLINK add constraint ACT_FK_ATHRZ_PROCEDEF foreign key (PROC_DEF_ID_) references ACT_RE_PROCDEF(ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_IDENTITYLINK' + and CONSTRAINT_NAME = 'ACT_FK_IDL_PROCINST' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_IDENTITYLINK add constraint ACT_FK_IDL_PROCINST foreign key (PROC_INST_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_TASK' + and CONSTRAINT_NAME = 'ACT_FK_TASK_EXE' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_TASK add constraint ACT_FK_TASK_EXE foreign key (EXECUTION_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_TASK' + and CONSTRAINT_NAME = 'ACT_FK_TASK_PROCINST' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_TASK add constraint ACT_FK_TASK_PROCINST foreign key (PROC_INST_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_TASK' + and CONSTRAINT_NAME = 'ACT_FK_TASK_PROCDEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_TASK add constraint ACT_FK_TASK_PROCDEF foreign key (PROC_DEF_ID_) references ACT_RE_PROCDEF (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_VARIABLE' + and CONSTRAINT_NAME = 'ACT_FK_VAR_EXE' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_VARIABLE add constraint ACT_FK_VAR_EXE foreign key (EXECUTION_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_VARIABLE' + and CONSTRAINT_NAME = 'ACT_FK_VAR_PROCINST' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_VARIABLE add constraint ACT_FK_VAR_PROCINST foreign key (PROC_INST_ID_) references ACT_RU_EXECUTION(ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_VARIABLE' + and CONSTRAINT_NAME = 'ACT_FK_VAR_BYTEARRAY' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_VARIABLE add constraint ACT_FK_VAR_BYTEARRAY foreign key (BYTEARRAY_ID_) references ACT_GE_BYTEARRAY (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_JOB' + and CONSTRAINT_NAME = 'ACT_FK_JOB_EXECUTION' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_JOB add constraint ACT_FK_JOB_EXECUTION foreign key (EXECUTION_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_JOB' + and CONSTRAINT_NAME = 'ACT_FK_JOB_PROCESS_INSTANCE' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_JOB add constraint ACT_FK_JOB_PROCESS_INSTANCE foreign key (PROCESS_INSTANCE_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_JOB' + and CONSTRAINT_NAME = 'ACT_FK_JOB_PROC_DEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_JOB add constraint ACT_FK_JOB_PROC_DEF foreign key (PROC_DEF_ID_) references ACT_RE_PROCDEF (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_JOB' + and CONSTRAINT_NAME = 'ACT_FK_JOB_EXCEPTION' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_JOB add constraint ACT_FK_JOB_EXCEPTION foreign key (EXCEPTION_STACK_ID_) references ACT_GE_BYTEARRAY (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_TIMER_JOB' + and CONSTRAINT_NAME = 'ACT_FK_TIMER_JOB_EXECUTION' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_TIMER_JOB add constraint ACT_FK_TIMER_JOB_EXECUTION foreign key (EXECUTION_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_TIMER_JOB' + and CONSTRAINT_NAME = 'ACT_FK_TIMER_JOB_PROCESS_INSTANCE' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_TIMER_JOB add constraint ACT_FK_TIMER_JOB_PROCESS_INSTANCE foreign key (PROCESS_INSTANCE_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_TIMER_JOB' + and CONSTRAINT_NAME = 'ACT_FK_TIMER_JOB_PROC_DEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_TIMER_JOB add constraint ACT_FK_TIMER_JOB_PROC_DEF foreign key (PROC_DEF_ID_) references ACT_RE_PROCDEF (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_TIMER_JOB' + and CONSTRAINT_NAME = 'ACT_FK_TIMER_JOB_EXCEPTION' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_TIMER_JOB add constraint ACT_FK_TIMER_JOB_EXCEPTION foreign key (EXCEPTION_STACK_ID_) references ACT_GE_BYTEARRAY (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_SUSPENDED_JOB' + and CONSTRAINT_NAME = 'ACT_FK_SUSPENDED_JOB_EXECUTION' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_SUSPENDED_JOB add constraint ACT_FK_SUSPENDED_JOB_EXECUTION foreign key (EXECUTION_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_SUSPENDED_JOB' + and CONSTRAINT_NAME = 'ACT_FK_SUSPENDED_JOB_PROCESS_INSTANCE' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_SUSPENDED_JOB add constraint ACT_FK_SUSPENDED_JOB_PROCESS_INSTANCE foreign key (PROCESS_INSTANCE_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_SUSPENDED_JOB' + and CONSTRAINT_NAME = 'ACT_FK_SUSPENDED_JOB_PROC_DEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_SUSPENDED_JOB add constraint ACT_FK_SUSPENDED_JOB_PROC_DEF foreign key (PROC_DEF_ID_) references ACT_RE_PROCDEF (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_SUSPENDED_JOB' + and CONSTRAINT_NAME = 'ACT_FK_SUSPENDED_JOB_EXCEPTION' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_SUSPENDED_JOB add constraint ACT_FK_SUSPENDED_JOB_EXCEPTION foreign key (EXCEPTION_STACK_ID_) references ACT_GE_BYTEARRAY (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_DEADLETTER_JOB' + and CONSTRAINT_NAME = 'ACT_FK_DEADLETTER_JOB_EXECUTION' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_DEADLETTER_JOB add constraint ACT_FK_DEADLETTER_JOB_EXECUTION foreign key (EXECUTION_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_DEADLETTER_JOB' + and CONSTRAINT_NAME = 'ACT_FK_DEADLETTER_JOB_PROCESS_INSTANCE' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_DEADLETTER_JOB add constraint ACT_FK_DEADLETTER_JOB_PROCESS_INSTANCE foreign key (PROCESS_INSTANCE_ID_) references ACT_RU_EXECUTION (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_DEADLETTER_JOB' + and CONSTRAINT_NAME = 'ACT_FK_DEADLETTER_JOB_PROC_DEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_DEADLETTER_JOB add constraint ACT_FK_DEADLETTER_JOB_PROC_DEF foreign key (PROC_DEF_ID_) references ACT_RE_PROCDEF (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_DEADLETTER_JOB' + and CONSTRAINT_NAME = 'ACT_FK_DEADLETTER_JOB_EXCEPTION' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_DEADLETTER_JOB add constraint ACT_FK_DEADLETTER_JOB_EXCEPTION foreign key (EXCEPTION_STACK_ID_) references ACT_GE_BYTEARRAY (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RU_EVENT_SUBSCR' + and CONSTRAINT_NAME = 'ACT_FK_EVENT_EXEC' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RU_EVENT_SUBSCR add constraint ACT_FK_EVENT_EXEC foreign key (EXECUTION_ID_) references ACT_RU_EXECUTION(ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RE_MODEL' + and CONSTRAINT_NAME = 'ACT_FK_MODEL_SOURCE' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_SOURCE foreign key (EDITOR_SOURCE_VALUE_ID_) references ACT_GE_BYTEARRAY (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RE_MODEL' + and CONSTRAINT_NAME = 'ACT_FK_MODEL_SOURCE_EXTRA' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_SOURCE_EXTRA foreign key (EDITOR_SOURCE_EXTRA_VALUE_ID_) references ACT_GE_BYTEARRAY (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_RE_MODEL' + and CONSTRAINT_NAME = 'ACT_FK_MODEL_DEPLOYMENT' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_DEPLOYMENT foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_PROCDEF_INFO' + and CONSTRAINT_NAME = 'ACT_FK_INFO_JSON_BA' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_PROCDEF_INFO add constraint ACT_FK_INFO_JSON_BA foreign key (INFO_JSON_ID_) references ACT_GE_BYTEARRAY (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_PROCDEF_INFO' + and CONSTRAINT_NAME = 'ACT_FK_INFO_PROCDEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_PROCDEF_INFO add constraint ACT_FK_INFO_PROCDEF foreign key (PROC_DEF_ID_) references ACT_RE_PROCDEF (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_PROCDEF_INFO' + and CONSTRAINT_NAME = 'ACT_UNIQ_INFO_PROCDEF' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_PROCDEF_INFO add constraint ACT_UNIQ_INFO_PROCDEF unique (PROC_DEF_ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_ID_MEMBERSHIP' + and CONSTRAINT_NAME = 'ACT_FK_MEMB_GROUP' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_ID_MEMBERSHIP add constraint ACT_FK_MEMB_GROUP foreign key (GROUP_ID_) references ACT_ID_GROUP (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = ( + select COUNT(*) + from information_schema.key_column_usage + where table_schema = database() + and TABLE_NAME = 'ACT_ID_MEMBERSHIP' + and CONSTRAINT_NAME = 'ACT_FK_MEMB_USER' +); +set @sql = IF(@fk_exists = 0, + 'alter table ACT_ID_MEMBERSHIP add constraint ACT_FK_MEMB_USER foreign key (USER_ID_) references ACT_ID_USER (ID_)', + 'SELECT "Constraint already exists, skipping."'); + +prepare stmt from @sql; +execute stmt; +deallocate prepare stmt; + +set @fk_exists = NULL; +set @sql = NULL; + +-- constraint end -- + +commit; \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/resources/application-local.yml b/backend/projectmanagement-server/src/main/resources/application-local.yml new file mode 100644 index 0000000..39b131e --- /dev/null +++ b/backend/projectmanagement-server/src/main/resources/application-local.yml @@ -0,0 +1,71 @@ +spring: + application: + name: projectmanagement + + datasource: + url: jdbc:mysql://localhost:3306/projectmanagement?createDatabaseIfNotExist=true + username: root + password: rootpassword123 + driver-class-name: com.mysql.cj.jdbc.Driver + hikari: + connectionTimeout: 20000 + maximumPoolSize: 20 + jpa: + database-platform: org.hibernate.dialect.MySQL8Dialect + hibernate: + ddl-auto: update # Options: none, validate, update, create, create-drop + show-sql: true + defer-datasource-initialization: false + properties: + hibernate: + format_sql: true + + + + + security: + oauth2: + resourceserver: + jwt: +# issuer-uri: http://localhost:8081/api/platform + issuer-uri: https://ikoncloud-dev.keross.com/ikon-api/platform + +ikon: + user: + agent: "IKON App Server" + time-zone: "Asia/Kolkata" + platform: + rest: + url: https://ikoncloud-dev.keross.com/ikon-api + logger: + enabled: false # set true when deployed in dev/uat/prod otherwise set to false if running in local/devtools environment. + app: + softwareId: "fe6e3390-c5e1-4797-9d59-7393d2fab5c1" + softwareVerion: 1 + softwareName: ${spring.application.name} + softwareRepositoryName: projectmanagement + accessmanagement: + init: + file: C:\Sales_CRM_New\projectmanagement\projectmanagement\bpmn\project.json + + +logging: + level: + com.ikon: DEBUG + file: + name: "../logs/${spring.application.name}-app.log" + +server: + address: 0.0.0.0 + port: 8070 + +eureka: + instance: + ip-address: ${server.address} + preferIpAddress: true + instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} + client: + register-with-eureka: false + fetch-registry: false + service-url: + default-zone: http://localhost:8761/eureka diff --git a/backend/projectmanagement-server/src/main/resources/application-server.yml b/backend/projectmanagement-server/src/main/resources/application-server.yml new file mode 100644 index 0000000..9e1b512 --- /dev/null +++ b/backend/projectmanagement-server/src/main/resources/application-server.yml @@ -0,0 +1,119 @@ +spring: + application: + name: bpmnprocessdemo + + datasource: + url: jdbc:mysql://localhost:3306/bpmnprocessdemo + username: system + password: admin + driver-class-name: com.mysql.cj.jdbc.Driver + hikari: + connectionTimeout: 20000 + maximumPoolSize: 20 + jpa: + database-platform: org.hibernate.dialect.MySQL8Dialect + hibernate: + ddl-auto: update # Options: none, validate, update, create, create-drop + show-sql: true + defer-datasource-initialization: false + properties: + hibernate: + format_sql: true + sql: + init: + schema-locations: + - classpath:activiti.engine.schema.sql + mode: always + + data: + redis: + host: localhost + port: 6379 + password: 7410 + database: 0 + lettuce: + pool: + max-active: 10 # Maximum number of connections + max-idle: 8 # Maximum idle connections + min-idle: 2 # Minimum idle connections + max-wait: 5s # Max wait time for a connection + mongodb: + host: localhost + port: 27017 + username: system + password: admin + authentication-database: admin + mongodb: + client: + settings: + connection-pool: + max-size: 500 # Maximum connections in the pool + min-size: 10 # Minimum idle connections + max-connection-idle-time: 10s # Time a connection can be idle before being closed + max-wait-time: 5s + + kafka: + bootstrap-servers: localhost:9092 + properties: + schema: + registry: + url: http://localhost:9093 + specific: + avro: + reader: true + producer: + key-serializer: org.apache.kafka.common.serialization.StringSerializer + value-serializer: io.confluent.kafka.serializers.KafkaAvroSerializer + consumer: + key-deserializer: org.apache.kafka.common.serialization.StringDeserializer + value-deserializer: io.confluent.kafka.serializers.KafkaAvroDeserializer + group-id: ${spring.application.name}-consumer-group + auto-offset-reset: earliest + + security: + oauth2: + resourceserver: + jwt: +# issuer-uri: http://localhost:8081/api/platform + issuer-uri: https://ikoncloud-dev.keross.com/ikon-api/platform + +ikon: + user: + agent: "IKON App Server" + time-zone: "Asia/Kolkata" + platform: + rest: + url: http://localhost:8081/api + logger: + enabled: false # set true when deployed in dev/uat/prod otherwise set to false if running in local/devtools environment. + accessmanagement: + init: + file: ../../bpmn/project.json + processengine: + databaseSchemaUpdate: false # possible values: "true", "false", "create-drop" + bpmn: + enabled: true + path: "../../bpmn" + job: + max-pool-size: 100 + +logging: + level: + com.ikon: DEBUG + file: + name: "../logs/${spring.application.name}-app.log" + +server: + address: localhost + port: 8060 + +eureka: + instance: + ip-address: ${server.address} + preferIpAddress: true + instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} + client: + register-with-eureka: true + fetch-registry: true + service-url: + default-zone: http://localhost:8761/eureka diff --git a/backend/projectmanagement-server/src/main/resources/application.properties b/backend/projectmanagement-server/src/main/resources/application.properties new file mode 100644 index 0000000..1923269 --- /dev/null +++ b/backend/projectmanagement-server/src/main/resources/application.properties @@ -0,0 +1,2 @@ +# Sales-CRM URL +salescrm.api.base-url=https://ikoncloud-dev.keross.com/ikon-api diff --git a/backend/projectmanagement-server/src/main/resources/application.yml b/backend/projectmanagement-server/src/main/resources/application.yml new file mode 100644 index 0000000..4339dce --- /dev/null +++ b/backend/projectmanagement-server/src/main/resources/application.yml @@ -0,0 +1,116 @@ +spring: + main: + allow-bean-definition-overriding: true + application: + name: projectmanagement + + service: + token: + enabled: true + + # ============================= + # MySQL Database Configuration + # ============================= + datasource: + url: jdbc:mysql://192.168.3.144:3306/projectmanagement?createDatabaseIfNotExist=true + username: app_user + password: userpassword123 + driver-class-name: com.mysql.cj.jdbc.Driver + hikari: + connectionTimeout: 20000 + maximumPoolSize: 20 + + jpa: + database-platform: org.hibernate.dialect.MySQL8Dialect + hibernate: + ddl-auto: update + show-sql: true + defer-datasource-initialization: false + properties: + hibernate: + format_sql: true + + + + + # ============================= + # Security Configuration + # ============================= + security: + oauth2: + resourceserver: + jwt: + issuer-uri: https://ikoncloud-dev.keross.com/ikon-api/platform + + +# ============================= +# IKON Platform Configurations +# ============================= +ikon: + connector: + internal-auth: + tokenUri: https://ikoncloud-dev.keross.com/ikon-api/platform/oauth2/token + clientId: ikon-client-management + clientSecret: F38Ysb4VEOSXUeISKcMyvpKqxtrIL8nf + crypto: + secretKey: MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY= + + user: + agent: "IKON App Server" + platform: + rest: https://ikoncloud-dev.keross.com/ikon-api + logger: + enabled: false + accessmanagement: + init: + file: ../../bpmn/project.json + + app: + #softwareId: "bfbb1d15-7e43-46ea-9b4c-109c8574aff8" + softwareId: "ed3d5e4f-1ea9-4008-92f9-6d09cec9e0ff" + softwareVerion: 1 + softwareName: ${spring.application.name} + softwareRepositoryName: projectmanagement + + + + +# ============================= +# Sales-CRM API Configuration +# ============================= +salescrm: + api: + base-url: https://ikoncloud-dev.keross.com/ikon-api/salescrm/api/v1 + + +# ============================= +# Logging Configuration +# ============================= +logging: + level: + com.ikon: DEBUG + file: + name: "../logs/${spring.application.name}-app.log" + + +# ============================= +# Server Configuration +# ============================= +server: + address: 0.0.0.0 + port: 8071 + + +# ============================= +# Eureka (Optional) +# ============================= +eureka: + instance: + ip-address: ${server.address} + preferIpAddress: true + instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} + client: + register-with-eureka: false + fetch-registry: false + service-url: + default-zone: http://localhost:8761/eureka \ No newline at end of file diff --git a/backend/projectmanagement-server/src/main/resources/application_old.yml b/backend/projectmanagement-server/src/main/resources/application_old.yml new file mode 100644 index 0000000..d787dfc --- /dev/null +++ b/backend/projectmanagement-server/src/main/resources/application_old.yml @@ -0,0 +1,117 @@ +spring: + application: + name: projectmanagement + + datasource: + url: jdbc:mysql://localhost:3306/projectmanagement?createDatabaseIfNotExist=true + username: root + password: rootpassword123 + driver-class-name: com.mysql.cj.jdbc.Driver + hikari: + connectionTimeout: 20000 + maximumPoolSize: 20 + jpa: + database-platform: org.hibernate.dialect.MySQL8Dialect + hibernate: + ddl-auto: update # Options: none, validate, update, create, create-drop + show-sql: true + defer-datasource-initialization: false + properties: + hibernate: + format_sql: true + sql: + init: + schema-locations: + - classpath:activiti.engine.schema.sql + mode: always + + data: + redis: + host: localhost + port: 6379 + password: 7410 + database: 0 + lettuce: + pool: + max-active: 10 # Maximum number of connections + max-idle: 8 # Maximum idle connections + min-idle: 2 # Minimum idle connections + max-wait: 5s # Max wait time for a connection + mongodb: + host: localhost + port: 27017 + username: admin + password: password123 + authentication-database: admin + mongodb: + client: + settings: + connection-pool: + max-size: 500 # Maximum connections in the pool + min-size: 10 # Minimum idle connections + max-connection-idle-time: 10s # Time a connection can be idle before being closed + max-wait-time: 5s + + kafka: + bootstrap-servers: localhost:9092 + properties: + schema: + registry: + url: http://localhost:9093 + specific: + avro: + reader: true + producer: + key-serializer: org.apache.kafka.common.serialization.StringSerializer + value-serializer: io.confluent.kafka.serializers.KafkaAvroSerializer + consumer: + key-deserializer: org.apache.kafka.common.serialization.StringDeserializer + value-deserializer: io.confluent.kafka.serializers.KafkaAvroDeserializer + group-id: ${spring.application.name}-consumer-group + auto-offset-reset: earliest + + security: + oauth2: + resourceserver: + jwt: +# issuer-uri: http://localhost:8081/api/platform + issuer-uri: https://ikoncloud-dev.keross.com/ikon-api/platform + +ikon: + user: + agent: "IKON App Server" + platform: + rest: + url: https://ikoncloud-dev.keross.com/ikon-api + logger: + enabled: false # set true when deployed in dev/uat/prod otherwise set to false if running in local/devtools environment. + accessmanagement: + init: + file: ../../bpmn/project.json + processengine: + databaseSchemaUpdate: false # possible values: "true", "false", "create-drop" + bpmn: + enabled: true + path: "../../bpmn" + +logging: + level: + com.ikon: DEBUG + file: + name: "../logs/${spring.application.name}-app.log" + +server: + address: 0.0.0.0 +# address: 127.0.0.1 + port: 8072 + +eureka: + instance: + ip-address: ${server.address} + preferIpAddress: true + instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} + client: + register-with-eureka: true + fetch-registry: true + service-url: + default-zone: http://localhost:8761/eureka diff --git a/bpmn/.gitignore b/bpmn/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/bpmn/environments.json b/bpmn/environments.json new file mode 100644 index 0000000..d51db01 --- /dev/null +++ b/bpmn/environments.json @@ -0,0 +1,8 @@ +[ + { + "envName": "local", + "applicationUrl": "http://localhost:8071", + "authUrl": "https://ikoncloud-dev.keross.com/ikon-api", + "jobUrl": "http://localhost:8083" + } +] \ No newline at end of file diff --git a/bpmn/folder_structure.json b/bpmn/folder_structure.json new file mode 100644 index 0000000..00221b0 --- /dev/null +++ b/bpmn/folder_structure.json @@ -0,0 +1,9 @@ +[ + { + "id": "ed3d5e4f-1ea9-4008-92f9-6d09cec9e0ff", + "name": "src", + "path": "C:\\Projects\\project-management\\bpmn\\src_ed3d5e4f-1ea9-4008-92f9-6d09cec9e0ff", + "nodeType": "folder", + "children": null + } +] \ No newline at end of file diff --git a/bpmn/lib/readme.md b/bpmn/lib/readme.md new file mode 100644 index 0000000..b94cf1c --- /dev/null +++ b/bpmn/lib/readme.md @@ -0,0 +1,2 @@ +# lib +This will contain additional libraries for you to use \ No newline at end of file diff --git a/bpmn/package-lock.json b/bpmn/package-lock.json new file mode 100644 index 0000000..78b62a5 --- /dev/null +++ b/bpmn/package-lock.json @@ -0,0 +1,8 @@ +{ + "name": "projectmanagement", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + } +} diff --git a/bpmn/package.json b/bpmn/package.json new file mode 100644 index 0000000..5c5bb58 --- /dev/null +++ b/bpmn/package.json @@ -0,0 +1,12 @@ +{ + "name": "projectmanagement", + "version": "1.0.0", + "main": "./src/index.js", + "type": "module", + "scripts": { + "start": "node ./src/index.js" + }, + "author": "", + "license": "ISC", + "description": "" +} diff --git a/bpmn/project.json b/bpmn/project.json new file mode 100644 index 0000000..94fec8f --- /dev/null +++ b/bpmn/project.json @@ -0,0 +1,31 @@ +{ + "projectName": "projectmanagement", + "groups": [ + { + "id": "b3a6bf0c-19f1-49b8-beac-5ccabfcf8721", + "name": "Admins", + "description": "", + "active": true + } + ], + "roles": [ + { + "id": "18980c5d-fd55-4238-896c-57006a7fe372", + "name": "Admin", + "active": true, + "description": "", + "groups": [ + "b3a6bf0c-19f1-49b8-beac-5ccabfcf8721" + ] + }, + { + "id": "0867d509-aa6c-4c3a-9abf-1b2c584c16f8", + "name": "Project manager", + "active": true, + "description": "", + "groups": [ + "b3a6bf0c-19f1-49b8-beac-5ccabfcf8721" + ] + } + ] +} \ No newline at end of file diff --git a/bpmn/src_ed3d5e4f-1ea9-4008-92f9-6d09cec9e0ff/readme.md b/bpmn/src_ed3d5e4f-1ea9-4008-92f9-6d09cec9e0ff/readme.md new file mode 100644 index 0000000..2863edd --- /dev/null +++ b/bpmn/src_ed3d5e4f-1ea9-4008-92f9-6d09cec9e0ff/readme.md @@ -0,0 +1,3 @@ +# src +src will contain all of your src folders + diff --git a/dockerfiles.yaml b/dockerfiles.yaml new file mode 100644 index 0000000..ad59daf --- /dev/null +++ b/dockerfiles.yaml @@ -0,0 +1,9 @@ +images: + - name: project-management-frontend + path: ./frontend/Dockerfile + chart: frontend + + - name: project-management-backend + path: ./backend/Dockerfile + chart: backend + context: . \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..ef2eeb7 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,59 @@ +# ---- Stage 1: Install dependencies ---- +FROM node:22-alpine AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app + +COPY package.json package-lock.json* ./ + +RUN npm i --force + +# ---- Stage 2: Build ---- +FROM node:22-alpine AS builder +RUN apk add --no-cache libc6-compat +WORKDIR /app + +COPY --from=deps /app/node_modules ./node_modules +COPY . . + + +# Inject build-time environment variables +ENV BASE_PATH=/apps/project-management/v1 +ENV NEXT_PUBLIC_IKON_API_URL=https://holocron.keross.com/api +ENV NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL=https://holocron.keross.com/api/project-management/v1 +ENV NEXT_PUBLIC_IKON_LOGIN_PAGE_URL=https://holocron.keross.com/ikon-portal/login.html +ENV NEXT_PUBLIC_IKON_PLATFORM_UI_URL=https://holocron.keross.com/ikon-portal + + + + +RUN npm run build + +# ---- Stage 3: Runtime ---- +FROM node:22-alpine AS runner +RUN apk add --no-cache libc6-compat +WORKDIR /app + +ENV NODE_ENV=production + +# Runtime ENV (optional override) +ENV BASE_PATH=/apps/project-management/v1 +ENV NEXT_PUBLIC_IKON_API_URL=https://holocron.keross.com/api +ENV NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL=https://holocron.keross.com/api/project-management/v1 +ENV NEXT_PUBLIC_IKON_LOGIN_PAGE_URL=https://holocron.keross.com/ikon-portal/login.html +ENV NEXT_PUBLIC_IKON_PLATFORM_UI_URL=https://holocron.keross.com/ikon-portal + + +# Create non-root user +RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs + +COPY --from=builder --chown=nextjs:nodejs /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 +ENV PORT=3000 +ENV HOSTNAME=0.0.0.0 + +CMD ["node", "server.js"] diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/frontend/app/api/health/live/route.ts b/frontend/app/api/health/live/route.ts new file mode 100644 index 0000000..3cf5224 --- /dev/null +++ b/frontend/app/api/health/live/route.ts @@ -0,0 +1,5 @@ +import { NextResponse } from "next/server"; + +export async function GET() { + return NextResponse.json({ live: "ok" }, { status: 200 }); +} \ No newline at end of file diff --git a/frontend/app/api/health/ready/route.ts b/frontend/app/api/health/ready/route.ts new file mode 100644 index 0000000..f2a1165 --- /dev/null +++ b/frontend/app/api/health/ready/route.ts @@ -0,0 +1,5 @@ +import { NextResponse } from "next/server"; + +export async function GET() { + return NextResponse.json({ ready: "ok" }, { status: 200 }); +} \ No newline at end of file diff --git a/frontend/app/favicon.ico b/frontend/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 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 LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/frontend/app/globals.css b/frontend/app/globals.css new file mode 100644 index 0000000..5e13edb --- /dev/null +++ b/frontend/app/globals.css @@ -0,0 +1,15 @@ +/* Kendo UI Theme - local package install */ +@import "@progress/kendo-theme-default/dist/all.css"; + +@import "tailwindcss"; + +@import "ikoncomponents/dist/styles.css"; + +/* Prevent Tailwind preflight from stripping Kendo Gantt bar dimensions */ +.k-gantt .k-task-complete { + position: absolute !important; +} + +.k-gantt table { + width: 100%; +} \ No newline at end of file diff --git a/frontend/app/home/components/CTASection.tsx b/frontend/app/home/components/CTASection.tsx new file mode 100644 index 0000000..cb5935f --- /dev/null +++ b/frontend/app/home/components/CTASection.tsx @@ -0,0 +1,47 @@ +"use client"; +import { Button, Card } from "ikoncomponents"; +import { ArrowRight } from "lucide-react"; +import { useRouter } from "next/dist/client/components/navigation"; + +export function CTASection() { + const router = useRouter(); + const handleGetStarted = () => { + router.push("/main/overview/dashboard"); + }; + return ( +

+
+ + {/* Decorative radial glow */} +
+ +
+

+ Ready to Transform Your Projects? +

+

+ Join thousands of teams using AI to deliver projects on time and + under budget. +

+ +
+ + +
+
+ +
+
+ ); +} diff --git a/frontend/app/home/components/FeaturesSection.tsx b/frontend/app/home/components/FeaturesSection.tsx new file mode 100644 index 0000000..a7c3d9e --- /dev/null +++ b/frontend/app/home/components/FeaturesSection.tsx @@ -0,0 +1,210 @@ +"use client"; +import { Badge, Card } from "ikoncomponents"; +import { + Zap, + Users, + BarChart3, + FileText, + Layout, + Settings2, + Lock, + FolderKanban, + AlertTriangle, + RotateCcw, + Binary, + Link2, + Shield, + Brain, + TrendingUp, + Calendar, +} from "lucide-react"; + +const features = [ + { + title: "AI Health Scores", + desc: "Real-time project health monitoring powered by machine learning. Predict risks before they happen.", + icon: Brain, + bg: "bg-purple-600", + }, + { + title: "Predictive Analytics", + desc: "Forecast completion dates with confidence percentages. Know your slippage risk in advance.", + icon: TrendingUp, + bg: "bg-indigo-600", + }, + { + title: "AI Assessment Tool", + desc: "LLM-powered project planning wizard generating BRD, SRS, timeline, budget breakdown, and risk identification.", + icon: Zap, + bg: "bg-blue-600", + }, + { + title: "Project Management", + desc: "Complete project lifecycle management with Kanban boards, task tracking, and team collaboration.", + icon: Layout, + bg: "bg-cyan-600", + }, + { + title: "Task Management", + desc: "Create, assign, and track tasks with priorities, story points, and sprint integration.", + icon: Settings2, + bg: "bg-blue-600", + }, + { + title: "Sprint Planning", + desc: "Sprint velocity tracking, backlog grooming, and automated burndown charts for Agile teams..", + icon: Calendar, + bg: "bg-sky-600", + }, + { + title: "Analytics Dashboard", + desc: "Task distribution charts, project metrics, and financial analytics in one unified view.", + icon: BarChart3, + bg: "bg-emerald-600", + }, + { + title: "Reports & Downloads", + desc: "Generate downloadable reports filtered by time frame, projects, resources, and finances - export as CSV or PDF.", + icon: FileText, + bg: "bg-green-600", + }, + { + title: "Resource Management", + desc: "Full team member lifecycle with CRUD, CSV bulk import, onboard/offboard workflow, and FTE calculation.", + icon: Users, + bg: "bg-orange-600", + }, + { + title: "Project Access Control", + desc: "Request, grant, modify, and revoke resource access to projects with approval workflows.", + icon: Lock, + bg: "bg-amber-600", + }, + { + title: "Portfolio Management", + desc: "Department-level project grouping for strategic oversight and portfolio performance tracking.", + icon: FolderKanban, + bg: "bg-rose-600", + }, + { + title: "Risk Management", + desc: "Risk register with probability/impact scoring, severity levels, and mitigation tracking.", + icon: AlertTriangle, + bg: "bg-pink-600", + }, + { + title: "Change Management", + desc: "Variation orders with approval workflow, budget impact tracking, and schedule adjustments.", + icon: RotateCcw, + bg: "bg-pink-600", + }, + { + title: "No-Code Automation", + desc: "Create powerful If/Then triggers without writing code. Automate repetitive tasks instantly.", + icon: Binary, + bg: "bg-violet-600", + }, + { + title: "External Integrations", + desc: "Connect to HRMS, CRM, ERP systems via REST API, GraphQL, webhooks, or database probes.", + icon: Link2, + bg: "bg-indigo-600", + }, + { + title: "Enterprise Security", + desc: "Role-based access control, session management, and secure authentication for 8 stakeholder types.", + icon: Shield, + bg: "bg-orange-600", + }, +]; + +const categories = [ + { + label: "AI-Powered", + dot: "bg-fuchsia-500", + }, + { + label: "Core Features", + dot: "bg-cyan-500", + }, + { + label: "Analytics", + dot: "bg-emerald-500", + }, + { + label: "Resources", + dot: "bg-orange-500", + }, + { + label: "Management", + dot: "bg-sky-500", + }, + { + label: "Automation", + dot: "bg-violet-500", + }, + { + label: "Security", + dot: "bg-orange-500", + }, +] as const; + +export function FeaturesSection() { + return ( +
+
+ {/* Header */} +
+ + Complete Platform + + +

+ Everything You Need to Succeed +

+ +

+ A comprehensive suite of 16 powerful features designed for modern + project management. +

+
+ + {/* Categories */} +
+ {categories.map((cat) => ( + + ))} +
+ + {/* Features Grid */} +
+ {features.map((feature, idx) => ( + +
+ +
+ +

{feature.title}

+ +

+ {feature.desc} +

+
+ ))} +
+
+
+ ); +} \ No newline at end of file diff --git a/frontend/app/home/components/Footer.tsx b/frontend/app/home/components/Footer.tsx new file mode 100644 index 0000000..80bdead --- /dev/null +++ b/frontend/app/home/components/Footer.tsx @@ -0,0 +1,55 @@ +"use client"; +import { Brain} from "lucide-react"; + +const footerLinks = { + Product: ["Features", "Pricing", "Integrations", "API"], + Resources: ["Documentation", "Blog", "Support", "Community"], + Company: ["About", "Careers", "Privacy", "Terms"] +}; + +export function Footer() { + return ( +
+ ); +} \ No newline at end of file diff --git a/frontend/app/home/components/HeroSection.tsx b/frontend/app/home/components/HeroSection.tsx new file mode 100644 index 0000000..2eebe50 --- /dev/null +++ b/frontend/app/home/components/HeroSection.tsx @@ -0,0 +1,137 @@ +"use client"; + +import { Badge, Button, Card } from "ikoncomponents"; +import { ArrowRight, Brain, BrainCircuit } from "lucide-react"; +import { useRouter } from "next/dist/client/components/navigation"; + +export function HeroSection() { + const router = useRouter(); + + const handleStartTrial = () => { + router.push("/main/overview/dashboard"); + }; + + return ( +
+
+ {/* LEFT SECTION */} +
+ + + AI-Powered Platform + + +
+

+ Predictive Project
+ + Management + +

+ +

+ Transform reactive project tracking into proactive, predictive + management. Leverage AI and ML for executive-level insights into + financial health, resource optimization, and schedule + predictability. +

+
+ +
+ +
+ +
+
+
20%
+

+ Reduced Schedule Overruns +

+
+
+
85%
+

+ AI Prediction Accuracy +

+
+
+
+ + {/* RIGHT SECTION */} +
+ +
+
+
+
+
+
+ + + Live Preview + +
+ +
+
+

Enterprise Rollout

+

Phase 2 Active

+
+ +
+
+
92
+
+ AI Score +
+
+ +
+ +
+
+
+ +
+ + + +
+ +
+
+
+
+ 75% +
+ +
+
+
+ ); +} + +function StatBox({ + label, + value, + highlight, +}: { + label: string; + value: string; + highlight?: boolean; +}) { + return ( +
+
+ {value} +
+
{label}
+
+ ); +} diff --git a/frontend/app/home/components/IntegrationSection.tsx b/frontend/app/home/components/IntegrationSection.tsx new file mode 100644 index 0000000..942f32f --- /dev/null +++ b/frontend/app/home/components/IntegrationSection.tsx @@ -0,0 +1,61 @@ +"use client"; + +import { Badge, Card } from "ikoncomponents"; +import { Github, Slack, Code2 } from "lucide-react"; +import Image from "next/image"; + +const integrations = [ + { name: "Slack", icon: Slack, color: "text-purple-400" }, + { name: "GitHub", icon: Github, color: "text-gray-400" }, + { name: "Jira", image: "/jira.svg", color: "text-blue-400" }, + { name: "API", icon: Code2, color: "text-green-400" }, +]; + +export function IntegrationSection() { + return ( +
+
+ {/* Header */} +
+ + Ecosystem + +

+ Seamless Integrations +

+

+ Connect with your favorite tools through our RESTful API and + webhooks. +

+
+ + {/* Integration Grid */} +
+ {integrations.map((item) => ( + +
+ {item.icon ? ( + + ) : ( + {item.name} + )} +
+ + {item.name} + +
+ ))} +
+
+
+ ); +} diff --git a/frontend/app/home/components/MethodologySection.tsx b/frontend/app/home/components/MethodologySection.tsx new file mode 100644 index 0000000..28bdea5 --- /dev/null +++ b/frontend/app/home/components/MethodologySection.tsx @@ -0,0 +1,97 @@ +"use client"; + +import { Badge, Card } from "ikoncomponents"; +import { CheckCircle2, GitBranch, CalendarDays } from "lucide-react"; + +const methodologyData = [ + { + title: "Agile & Scrum", + description: + "Sprint planning, velocity tracking, and automated burndown charts.", + icon: GitBranch, + iconColor: "text-indigo-400", + iconBg: "bg-indigo-500/10", + features: [ + "Kanban Boards", + "Sprint Backlogs", + "Velocity Metrics", + "WIP Limits", + ], + }, + { + title: "Waterfall & Gantt", + description: "Dynamic Gantt charts with drag-and-drop dependency mapping.", + icon: CalendarDays, + iconColor: "text-blue-400", + iconBg: "bg-blue-500/10", + features: ["Timeline Views", "Dependencies", "Milestones", "Critical Path"], + }, +]; + +export function MethodologySection() { + return ( +
+
+ {/* Header */} +
+ + Flexible Workflows + + +

+ Your Methodology, Your Way +

+ +

+ Support diverse team workflows across Agile and Waterfall in one + unified interface. +

+
+ + {/* Cards Grid */} +
+ {methodologyData.map((item, idx) => ( + + {/* Top Section */} +
+
+ +
+ +
+

+ {item.title} +

+

+ {item.description} +

+
+
+ + {/* Features */} +
+ {item.features.map((feature) => ( +
+ + + {feature} + +
+ ))} +
+
+ ))} +
+
+
+ ); +} diff --git a/frontend/app/home/components/Navbar.tsx b/frontend/app/home/components/Navbar.tsx new file mode 100644 index 0000000..2887b5b --- /dev/null +++ b/frontend/app/home/components/Navbar.tsx @@ -0,0 +1,91 @@ +"use client"; + +import Link from "next/link"; +import { Button } from "ikoncomponents"; +import { useRouter } from "next/dist/client/components/navigation"; +import { Brain, Menu, X } from "lucide-react"; +import { useState } from "react"; + +export default function Navbar() { + const router = useRouter(); + const [open, setOpen] = useState(false); + + const handleStartTrial = () => { + router.push("/main/overview/dashboard"); + }; + + return ( +
+
+ {/* Logo */} +
+
+ +
+ ProjectAI +
+ + {/* Desktop Navigation */} + + + {/* Right Actions (Desktop) */} +
+ +
+ + {/* Mobile Menu Button */} + +
+ + {/* Mobile Navigation */} + {open && ( +
+ +
+ )} +
+ ); +} diff --git a/frontend/app/home/components/SecuritySection.tsx b/frontend/app/home/components/SecuritySection.tsx new file mode 100644 index 0000000..dba7483 --- /dev/null +++ b/frontend/app/home/components/SecuritySection.tsx @@ -0,0 +1,78 @@ +"use client"; + +import { Badge, Card } from "ikoncomponents"; +import { Lock, ShieldCheck, Globe } from "lucide-react"; + +const securityFeatures = [ + { + title: "SSO & MFA", + description: "Okta, Azure AD integration", + icon: Lock, + }, + { + title: "SOC2 & GDPR", + description: "Regulatory compliance", + icon: ShieldCheck, + }, + { + title: "Data Sovereignty", + description: "Regional data hosting", + icon: Globe, + }, +]; + +export function SecuritySection() { + return ( +
+
+ + {/* Header */} +
+ + Enterprise Grade + + +

+ Security & Compliance +

+ +

+ Built with enterprise security requirements in mind, ensuring your + data is protected at every level. +

+
+ + {/* Security Grid */} +
+ {securityFeatures.map((feature, idx) => ( + +
+ +
+ +

+ {feature.title} +

+ +

+ {feature.description} +

+
+ ))} +
+ +
+
+ ); +} diff --git a/frontend/app/home/components/VisibilitySection.tsx b/frontend/app/home/components/VisibilitySection.tsx new file mode 100644 index 0000000..ba16787 --- /dev/null +++ b/frontend/app/home/components/VisibilitySection.tsx @@ -0,0 +1,95 @@ +"use client"; + +import { Badge, Card } from "ikoncomponents"; +import { CheckCircle2 } from "lucide-react"; + +const visibilityPoints = [ + "AI Health Scores with confidence percentages", + "Real-time P/L and budget tracking", + "Resource utilization heatmaps", + "Portfolio-level performance metrics", +]; + +const dashboardStats = [ + { label: "Active Projects", value: "12" }, + { label: "Avg Health Score", value: "87%", color: "text-emerald-400" }, + { label: "Total Budget", value: "$4.2M" }, + { label: "At Risk", value: "3", color: "text-amber-500" }, +]; + +export function VisibilitySection() { + return ( +
+
+
+ + {/* Left Column */} +
+ + Executive Dashboard + + +
+

+ Complete Visibility
at a Glance +

+

+ A unified view of project health, financial metrics, and + predictive insights designed for strategic decision-making. +

+
+ +
+ {visibilityPoints.map((point) => ( +
+
+ +
+ {point} +
+ ))} +
+
+ + {/* Right Column */} +
+ {/* Background glow */} +
+ + +
+

+ Portfolio Overview +

+ + Healthy + +
+ +
+ {dashboardStats.map((stat) => ( +
+
+ {stat.value} +
+
+ {stat.label} +
+
+ ))} +
+
+
+ +
+
+
+ ); +} diff --git a/frontend/app/home/layout.tsx b/frontend/app/home/layout.tsx new file mode 100644 index 0000000..db5b922 --- /dev/null +++ b/frontend/app/home/layout.tsx @@ -0,0 +1,16 @@ +"use client"; + + +export default function HomeLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + <> + + + {children} + + ); +} diff --git a/frontend/app/home/page.tsx b/frontend/app/home/page.tsx new file mode 100644 index 0000000..b5ce7c1 --- /dev/null +++ b/frontend/app/home/page.tsx @@ -0,0 +1,22 @@ +"use client"; + +import { useEffect } from "react"; +import { useRouter } from "next/navigation"; + +// The marketing landing page (Hero + sections) is no longer used — opening the +// app should land directly on the dashboard. We keep the same auth check as the +// root page: send unauthenticated visitors to login, everyone else to the dashboard. +export default function page() { + const router = useRouter(); + + useEffect(() => { + const hasToken = document.cookie.includes("accessToken"); + if (!hasToken) { + window.location.href = "/login.html"; + } else { + router.replace("/main/overview/dashboard"); + } + }, [router]); + + return null; +} diff --git a/frontend/app/home/projects/layout.tsx b/frontend/app/home/projects/layout.tsx new file mode 100644 index 0000000..f6e0666 --- /dev/null +++ b/frontend/app/home/projects/layout.tsx @@ -0,0 +1,13 @@ +import React from "react"; + +export default function ProjectsLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( +
+ {children} +
+ ); +} diff --git a/frontend/app/home/projects/page.tsx b/frontend/app/home/projects/page.tsx new file mode 100644 index 0000000..fb22b80 --- /dev/null +++ b/frontend/app/home/projects/page.tsx @@ -0,0 +1,9 @@ +import { redirect } from "next/navigation"; + +export default function Project() { + return ( +
+

Project

+
+ ) +} \ No newline at end of file diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx new file mode 100644 index 0000000..3fc2315 --- /dev/null +++ b/frontend/app/layout.tsx @@ -0,0 +1,173 @@ +"use client"; +import "@progress/kendo-licensing"; +import "@progress/kendo-theme-default/dist/all.css"; +import React from "react"; + +import { ProviderWrapper } from "ikoncomponents"; + +import { Oswald, Outfit, Poppins } from "next/font/google"; +import "./globals.css"; +import { RenderSidebarNav } from "ikoncomponents/dist/ikoncomponents/main-layout/nav-main"; +import { SidebarNavItem } from "ikoncomponents/dist/ikoncomponents/main-layout/SidebarNavContext"; +import { AppCacheProvider } from "@/app/utils/context/AppCacheContext"; + +import { + Bot, + Files, + Home, + icons, + LayoutDashboard, + Settings, + User, +} from "lucide-react"; + +const poppins = Poppins({ + subsets: ["latin"], + weight: "400", + variable: "--font-poppins", +}); + +const outfit = Outfit({ + subsets: ["latin"], + weight: "400", + variable: "--font-outfit", +}); + +const oswald = Oswald({ + subsets: ["latin"], + weight: "400", + variable: "--font-oswald", +}); + +// export const metadata: Metadata = { +// title: "Create Next App", +// description: "Generated by create next app", +// }; + +const navMain: SidebarNavItem[] = [ + // { + // title: "Main", + // url: "/main", + // icon: Home, + // default: true, + // items: [ + // { + // title: "Dashboard", + // url: "/main/dashboard", + // icons: Home, + // }, + // { + // title: "Projects", + // url: "/main/projects", + // }, + + // { + // title: "Tasks", + // url: "/main/tasks", + // }, + // { + // title: "Sprints", + // url: "/main/sprints", + // }, + + + // ], + // }, + // { + // title: "Analytics", + // url: "/analytics", + // icon: Bot, + // default: true, + // items: [ + // { + // title: "Analytics", + // url: "/analytics/Analytics", + // }, + // { + // title: "Ai Insights", + // url: "/analytics/ai-insights", + // }, + + // { + // title: "Ai Assessment", + // url: "/analytics/ai-assessment", + // }, + // { + // title: "Reports", + // url: "/analytics/reports", + // }, + + // { + // title: "Resources", + // url: "/analytics/resources", + // }, + // { + // title: "Project Access", + // url: "/analytics/project-access", + // }, + // ], + // }, + + + // { + // title: "Management", + // url: "#", + // icon: Files, + // isActive: true, + // items: [ + // { + // title: "Portfolios", + // url: "/management/portfolios", + // }, + // { + // title: "Risks", + // url: "/management/risks", + // }, + + // { + // title: "Changes", + // url: "/management/changes", + // }, + // { + // title: "Automation", + // url: "/management/automation", + // }, + + // { + // title: "Integration", + // url: "/management/integration", + // }, + // { + // title: "settings", + // url: "/management/settings", + // }, + // ], + // }, + +]; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + + + + + + Project AI + + } /> + {children} + + + + ); +} diff --git a/frontend/app/main/configuration/company-data/components/grade-table/index.tsx b/frontend/app/main/configuration/company-data/components/grade-table/index.tsx new file mode 100644 index 0000000..ab9cd7f --- /dev/null +++ b/frontend/app/main/configuration/company-data/components/grade-table/index.tsx @@ -0,0 +1,146 @@ +"use client"; + +import { useEffect, useMemo, useRef, useState } from "react"; +import { Search, Award } from "lucide-react"; +import { + ColumnDef, + DataTableLayout, + Card, + Input, +} from "ikoncomponents"; +import { getAllGrade } from "@/app/utils/api/companyData/gradeApi.ts"; +import { GradeResponseDto } from "@/app/utils/api/companyData/gradeApi.ts/type"; + +function GradeDataTable() { + const [gradeTableData, setGradeTableData] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [search, setSearch] = useState(""); + + // DataTableLayout defaults to list view and has no prop to start in grid, so + // once mounted we click its built-in "Grid View" toggle once to default to cards. + const tableContainerRef = useRef(null); + const defaultedToGrid = useRef(false); + + const filteredGradeTableData = useMemo(() => { + if (!search.trim()) return gradeTableData; + return gradeTableData.filter((gradeData) => + gradeData.grade?.toLowerCase().includes(search.toLowerCase()), + ); + }, [gradeTableData, search]); + + const fetchGradeTableData = async () => { + setIsLoading(true); + try { + const gradeData = await getAllGrade(); + setGradeTableData(gradeData?.content || []); + } catch (error) { + console.error("Error fetching grade data:", error); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + fetchGradeTableData(); + }, []); + + // Switch DataTableLayout into grid (card) view as soon as it mounts, once. + useEffect(() => { + if (isLoading || defaultedToGrid.current) return; + const gridButton = + tableContainerRef.current?.querySelector( + 'button[title="Grid View"]', + ); + if (gridButton) { + gridButton.click(); + defaultedToGrid.current = true; + } + }, [isLoading]); + + // ikoncomponents passes the row object directly to cell(), not { row }. + const columns: ColumnDef[] = [ + { + accessorKey: "grade", + header: "Grade", + cell: (row) => {row.grade || "n/a"}, + }, + ]; + + return ( +
+ {/* Header */} +
+
+

Grades

+

+ {filteredGradeTableData.length} of {gradeTableData.length} grades +

+
+
+ +
+ row.id, + totalPages: 1, + currentPage: 1, + isLoading, + onReload: fetchGradeTableData, + actionNode: ( +
+ +
+ setSearch(e.target.value)} + /> +
+ ), + gridComponent: (data: GradeResponseDto[]) => ( +
+ {data.length > 0 ? ( + data.map((gradeItem) => ( + + {/* Left accent rail */} + +
+ +
+
+

+ Grade +

+

+ {gradeItem.grade || "-"} +

+
+
+ )) + ) : ( +
+ No grades found. +
+ )} +
+ ), + }} + /> +
+
+ ); +} + +export default GradeDataTable; diff --git a/frontend/app/main/configuration/company-data/components/role-table/index.tsx b/frontend/app/main/configuration/company-data/components/role-table/index.tsx new file mode 100644 index 0000000..fd6b745 --- /dev/null +++ b/frontend/app/main/configuration/company-data/components/role-table/index.tsx @@ -0,0 +1,150 @@ +"use client"; + +import { useEffect, useMemo, useRef, useState } from "react"; +import { Search, Briefcase } from "lucide-react"; +import { + ColumnDef, + DataTableLayout, + Card, + Input, +} from "ikoncomponents"; +import { getAllRoles } from "@/app/utils/api/companyData/roleApi.ts"; + +interface RoleData { + id: string; + role: string; +} + +function RoleDataTable() { + const [roleTableData, setRoleTableData] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [search, setSearch] = useState(""); + + // DataTableLayout defaults to list view and has no prop to start in grid, so + // once mounted we click its built-in "Grid View" toggle once to default to cards. + const tableContainerRef = useRef(null); + const defaultedToGrid = useRef(false); + + const filteredRoleTableData = useMemo(() => { + if (!search.trim()) return roleTableData; + return roleTableData.filter((roleData) => + roleData.role?.toLowerCase().includes(search.toLowerCase()), + ); + }, [roleTableData, search]); + + const fetchRoleTableData = async () => { + setIsLoading(true); + try { + const roleData = await getAllRoles(); + setRoleTableData(roleData || []); + } catch (error) { + console.error("Error fetching role data:", error); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + fetchRoleTableData(); + }, []); + + // Switch DataTableLayout into grid (card) view as soon as it mounts, once. + useEffect(() => { + if (isLoading || defaultedToGrid.current) return; + const gridButton = + tableContainerRef.current?.querySelector( + 'button[title="Grid View"]', + ); + if (gridButton) { + gridButton.click(); + defaultedToGrid.current = true; + } + }, [isLoading]); + + // ikoncomponents passes the row object directly to cell(), not { row }. + const columns: ColumnDef[] = [ + { + accessorKey: "role", + header: "Role", + cell: (row) => {row.role || "n/a"}, + }, + ]; + + return ( +
+ {/* Header */} +
+
+

Roles

+

+ {filteredRoleTableData.length} of {roleTableData.length} roles +

+
+
+ +
+ row.id, + totalPages: 1, + currentPage: 1, + isLoading, + onReload: fetchRoleTableData, + actionNode: ( +
+ +
+ setSearch(e.target.value)} + /> +
+ ), + gridComponent: (data: RoleData[]) => ( +
+ {data.length > 0 ? ( + data.map((roleItem) => ( + + {/* Left accent rail */} + +
+ +
+
+

+ Role +

+

+ {roleItem.role || "-"} +

+
+
+ )) + ) : ( +
+ No roles found. +
+ )} +
+ ), + }} + /> +
+
+ ); +} + +export default RoleDataTable; diff --git a/frontend/app/main/configuration/company-data/components/tabs/index.tsx b/frontend/app/main/configuration/company-data/components/tabs/index.tsx new file mode 100644 index 0000000..112b42a --- /dev/null +++ b/frontend/app/main/configuration/company-data/components/tabs/index.tsx @@ -0,0 +1,28 @@ +"use client"; + +import { CustomTabs, TabArray } from "ikoncomponents"; +import GradeDataTable from "../grade-table"; +import RoleDataTable from "../role-table"; + +const tabArray: TabArray[] = [ + { + tabName: "Role", + tabId: "tab-role", + default: true, + tabContent: , + }, + { + tabName: "Grade", + tabId: "tab-grade", + default: false, + tabContent: , + }, +]; + +export default function CompanyDataTab() { + return ( +
+ +
+ ); +} diff --git a/frontend/app/main/configuration/company-data/layout.tsx b/frontend/app/main/configuration/company-data/layout.tsx new file mode 100644 index 0000000..deb2f88 --- /dev/null +++ b/frontend/app/main/configuration/company-data/layout.tsx @@ -0,0 +1,15 @@ +"use client"; +import { RenderAppBreadcrumb } from "ikoncomponents"; + +export default function CompanyDataLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>){ + return ( + <> + + {children} + + ); +} \ No newline at end of file diff --git a/frontend/app/main/configuration/company-data/page.tsx b/frontend/app/main/configuration/company-data/page.tsx new file mode 100644 index 0000000..7dab6cc --- /dev/null +++ b/frontend/app/main/configuration/company-data/page.tsx @@ -0,0 +1,9 @@ +import CompanyDataTab from "./components/tabs"; + +export default async function CompanyData() { + return ( +
+ +
+ ); +} diff --git a/frontend/app/main/configuration/employee-data/components/employee-table/index.tsx b/frontend/app/main/configuration/employee-data/components/employee-table/index.tsx new file mode 100644 index 0000000..e2b70b6 --- /dev/null +++ b/frontend/app/main/configuration/employee-data/components/employee-table/index.tsx @@ -0,0 +1,172 @@ +"use client"; + +import { useState, useEffect, useCallback, useRef } from "react"; +import { ColumnDef, DataTableLayout } from "ikoncomponents"; +import { useSearchParams } from "next/navigation"; + +import { getEmployees } from "@/app/utils/api/employeeDetails"; + +interface EmployeeResponseDto { + accountId: string; + empId: string; + name: string; + email: string; + organizationEmail: string; + role: string; + grade: string; + active: boolean; +} + +interface RoleDto { + id: string; + accountId: string; + role: string; +} + +interface GradeDto { + id: string; + grade: string; +} + +interface ResolvedEmployee extends EmployeeResponseDto { + roleName: string; + gradeName: string; +} + +function EmployeePage({ + roleData, + gradeData, +}: { + roleData: RoleDto[]; + gradeData: GradeDto[]; +}) { + const [employees, setEmployees] = useState([]); + const [isLoading, setIsLoading] = useState(true); + + // This table is list-only, so hide DataTableLayout's built-in List/Grid toggle + // (it has no prop to disable it). Once mounted we find the grid button and hide + // the whole toggle group, so a lone list button isn't left dangling. + const tableContainerRef = useRef(null); + const hidGridToggle = useRef(false); + + const searchParams = useSearchParams(); + const currentSearch = (searchParams.get("search") || "").toLowerCase().trim(); + + const fetchEmployees = useCallback(async () => { + setIsLoading(true); + + try { + const data = await getEmployees(); + console.log("emp data", data); + + const empList: EmployeeResponseDto[] = data || []; + + const roleMap = new Map( + roleData?.map((role) => [role.id, role.role]) || [], + ); + + const gradeMap = new Map( + gradeData?.map((grade) => [grade.id, grade.grade]) || [], + ); + console.log("emp", empList, roleMap, gradeMap); + + const resolved: ResolvedEmployee[] = empList.map((emp) => ({ + ...emp, + roleName: roleMap.get(emp.role) || "n/a", + gradeName: gradeMap.get(emp.grade) || "n/a", + })); + console.log("emp data", resolved); + setEmployees(resolved); + } catch (error) { + console.error("Failed to fetch employees:", error); + } finally { + setIsLoading(false); + } + }, [roleData, gradeData]); + + useEffect(() => { + if (roleData && gradeData) { + fetchEmployees(); + } + }, [fetchEmployees, roleData, gradeData]); + + // Hide the List/Grid toggle once the table has mounted. + useEffect(() => { + if (isLoading || hidGridToggle.current) return; + const gridButton = + tableContainerRef.current?.querySelector( + 'button[title="Grid View"]', + ); + if (gridButton?.parentElement) { + gridButton.parentElement.style.display = "none"; + hidGridToggle.current = true; + } + }, [isLoading]); + + const filteredEmployees = currentSearch + ? employees.filter( + (emp) => + (emp.name || "").toLowerCase().includes(currentSearch) || + (emp.empId || "").toLowerCase().includes(currentSearch) || + (emp.email || "").toLowerCase().includes(currentSearch) || + (emp.roleName || "").toLowerCase().includes(currentSearch) || + (emp.gradeName || "").toLowerCase().includes(currentSearch), + ) + : employees; + + const columns: ColumnDef[] = [ + { + accessorKey: "empId", + header: "Employee ID", + cell: (row) => {row.empId || "n/a"}, + }, + { + accessorKey: "name", + header: "Employee Name", + cell: (row) => {row.name || "n/a"}, + }, + { + accessorKey: "roleName", + header: "Role", + cell: (row) => {row.roleName || "n/a"}, + }, + { + accessorKey: "gradeName", + header: "Grade", + cell: (row) => {row.gradeName || "n/a"}, + }, + { + accessorKey: "email", + header: "Email", + cell: (row) => {row.email || "n/a"}, + }, + { + accessorKey: "organizationEmail", + header: "Organization Email", + cell: (row) => {row.organizationEmail || "n/a"}, + }, + { + accessorKey: "active", + header: "Status", + cell: (row) => {row.active ? "Active" : "Inactive"}, + }, + ]; + + return ( +
+ row.empId, + totalPages: 1, + currentPage: 1, + isLoading, + onReload: fetchEmployees, + }} + /> +
+ ); +} + +export default EmployeePage; diff --git a/frontend/app/main/configuration/employee-data/components/employeeCard/index.tsx b/frontend/app/main/configuration/employee-data/components/employeeCard/index.tsx new file mode 100644 index 0000000..896711f --- /dev/null +++ b/frontend/app/main/configuration/employee-data/components/employeeCard/index.tsx @@ -0,0 +1,103 @@ +"use client"; + +import { + Card, + CardContent, + CardHeader, + Badge, + Avatar, + AvatarFallback, + Separator, +} from "ikoncomponents"; + +interface EmployeeResponseDto { + accountId: string; + empId: string; + name: string; + email: string; + organizationEmail: string; + role: string; + grade: string; + active: boolean; +} + +const EmployeeCard = ({ + empId, + name, + email, + organizationEmail, + role, + grade, + active, +}: EmployeeResponseDto) => { + const initials = name + ?.split(" ") + .map((n: string) => n[0]) + .join("") + .toUpperCase() + .slice(0, 2); + + return ( + + +
+
+ + + {initials} + + +
+

{name}

+

{empId}

+
+
+ +
+ + {active ? "Active" : "Inactive"} + +
+
+
+ + + + +
+
+

+ Role +

+

{role || "n/a"}

+
+
+

+ Grade +

+

{grade || "n/a"}

+
+
+ + + +
+
+

+ Personal Email +

+

{email || "n/a"}

+
+
+

+ Work Email +

+

{organizationEmail || "n/a"}

+
+
+
+
+ ); +}; + +export default EmployeeCard; \ No newline at end of file diff --git a/frontend/app/main/configuration/employee-data/layout.tsx b/frontend/app/main/configuration/employee-data/layout.tsx new file mode 100644 index 0000000..9118db3 --- /dev/null +++ b/frontend/app/main/configuration/employee-data/layout.tsx @@ -0,0 +1,21 @@ +"use client"; +import { RenderAppBreadcrumb } from "ikoncomponents"; + +export default function EmployeeDataLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + <> + + {children} + + ); +} diff --git a/frontend/app/main/configuration/employee-data/page.tsx b/frontend/app/main/configuration/employee-data/page.tsx new file mode 100644 index 0000000..32f68c0 --- /dev/null +++ b/frontend/app/main/configuration/employee-data/page.tsx @@ -0,0 +1,19 @@ +import { getAllGrade } from "@/app/utils/api/companyData/gradeApi.ts"; +import EmployeeDataTable from "./components/employee-table"; +import { getAllRoles } from "@/app/utils/api/companyData/roleApi.ts"; + +export const dynamic = "force-dynamic"; + +export default async function EmployeeData() { + const gradeData = await getAllGrade(); + const roleData = await getAllRoles(); + + return ( +
+ +
+ ); +} diff --git a/frontend/app/main/configuration/fx-rate/components/fx-rate-table/index.tsx b/frontend/app/main/configuration/fx-rate/components/fx-rate-table/index.tsx new file mode 100644 index 0000000..dfa3047 --- /dev/null +++ b/frontend/app/main/configuration/fx-rate/components/fx-rate-table/index.tsx @@ -0,0 +1,98 @@ +"use client"; + +import { useEffect, useMemo, useRef } from "react"; +import { ColumnDef, DataTableLayout } from "ikoncomponents"; +import { useAppCache } from "@/app/utils/context/AppCacheContext"; + +export interface FXRateData { + id: string; + year: string; + currency: string; + fxRate: number; + activeStatus: boolean; +} + +function FXRateDataTable() { + // FX rate data comes from the shared app-wide cache. + const { fxRateResponse, isLoading, refresh } = useAppCache(); + + const fxRateTableData = useMemo(() => { + const rows: FXRateData[] = []; + (fxRateResponse?.content || []).forEach((item: any) => { + const fxRateDetails = item.fxRateDetails || {}; + Object.values(fxRateDetails).forEach((yearGroup: any) => { + Object.values(yearGroup).forEach((detail: any) => { + rows.push({ + id: detail.id, + year: detail.year, + currency: detail.currency, + fxRate: detail.fxRate, + activeStatus: detail.activeStatus, + }); + }); + }); + }); + return rows; + }, [fxRateResponse]); + + // This table is list-only, so hide DataTableLayout's built-in List/Grid toggle + // (it has no prop to disable it). Once mounted we find the grid button and hide + // the whole toggle group, so a lone list button isn't left dangling. + const tableContainerRef = useRef(null); + const hidGridToggle = useRef(false); + + useEffect(() => { + if (isLoading || hidGridToggle.current) return; + const gridButton = + tableContainerRef.current?.querySelector( + 'button[title="Grid View"]', + ); + if (gridButton?.parentElement) { + gridButton.parentElement.style.display = "none"; + hidGridToggle.current = true; + } + }, [isLoading]); + + const columns: ColumnDef[] = [ + { + accessorKey: "year", + header: "Year", + cell: (row) => {row.year ?? "n/a"}, + }, + { + accessorKey: "currency", + header: "Currency", + cell: (row) => {row.currency ?? "n/a"}, + }, + { + accessorKey: "fxRate", + header: "FX Rate", + cell: (row) => {row.fxRate ?? "n/a"}, + }, + { + accessorKey: "activeStatus", + header: "Status", + cell: (row) => ( + {row.activeStatus ? "Active" : "Inactive"} + ), + }, + ]; + + return ( +
+ row.id, + totalPages: 1, + currentPage: 1, + isLoading, + onReload: refresh, + }} + /> +
+ ); +} + +export default FXRateDataTable; diff --git a/frontend/app/main/configuration/fx-rate/layout.tsx b/frontend/app/main/configuration/fx-rate/layout.tsx new file mode 100644 index 0000000..9e21ae3 --- /dev/null +++ b/frontend/app/main/configuration/fx-rate/layout.tsx @@ -0,0 +1,15 @@ +"use client"; +import { RenderAppBreadcrumb } from "ikoncomponents"; + +export default function FXRateLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>){ + return ( + <> + + {children} + + ); +} \ No newline at end of file diff --git a/frontend/app/main/configuration/fx-rate/page.tsx b/frontend/app/main/configuration/fx-rate/page.tsx new file mode 100644 index 0000000..54c5f2b --- /dev/null +++ b/frontend/app/main/configuration/fx-rate/page.tsx @@ -0,0 +1,9 @@ +import FXRateDataTable from "./components/fx-rate-table"; + +export default async function CompanyData() { + return ( +
+ +
+ ); +} diff --git a/frontend/app/main/configuration/integration/components/AddIntegrationModal.tsx b/frontend/app/main/configuration/integration/components/AddIntegrationModal.tsx new file mode 100644 index 0000000..0cb2008 --- /dev/null +++ b/frontend/app/main/configuration/integration/components/AddIntegrationModal.tsx @@ -0,0 +1,238 @@ +"use client"; + +import { X } from "lucide-react"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; + + +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + Button, + Form, + FormField, + FormItem, + FormLabel, + FormControl, + FormMessage, + Input, + Textarea, + Select, + SelectTrigger, + SelectValue, + SelectContent, + SelectItem, +} from "ikoncomponents"; + +/* ---------------- Schema ---------------- */ +const integrationSchema = z.object({ + name: z.string().min(1, "Integration name is required"), + systemType: z.string().min(1, "System type is required"), + connectionMethod: z.string().min(1, "Connection method is required"), + endpointUrl: z.string().url("Invalid URL").optional().or(z.literal("")), + description: z.string().optional(), +}); + +type IntegrationFormValues = z.infer; + +interface Props { + open: boolean; + onClose: () => void; + onSubmit: (data: IntegrationFormValues) => void; +} + +/* ---------------- Component ---------------- */ +export default function AddIntegrationModal({ + open, + onClose, + onSubmit, +}: Props) { + const form = useForm({ + resolver: zodResolver(integrationSchema), + defaultValues: { + name: "", + systemType: "", + connectionMethod: "", + endpointUrl: "", + description: "", + }, + }); + + const handleClose = () => { + form.reset(); + onClose(); + }; + + const handleCreateIntegration = (data: IntegrationFormValues) => { + console.log("Integration form data:", { + ...data, + }); + + onSubmit(data); // pass to parent if needed + handleClose(); // close + reset modal +}; + + + return ( + + + {/* Header */} + + Add External Integration + + + + + + {/* Form */} +
+ + {/* Integration Name */} + ( + + + Integration Name * + + + + + + + )} + /> + + {/* System Type */} + ( + + + System Type * + + + + + )} + /> + + {/* Connection Method */} + ( + + + Connection Method{" "} + * + + + + + )} + /> + + {/* Endpoint URL */} + ( + + Endpoint URL + + + + + + )} + /> + + {/* Description */} + ( + + Description + +