Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(application-system): New application - Work Accident Notification #16632

Open
wants to merge 77 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 74 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
53e5f91
initial application creation
Ballioli Aug 7, 2024
d55cb7d
Continued work setting up application
Ballioli Aug 9, 2024
6f38470
Further work setting up work accident notification application
Ballioli Aug 12, 2024
11fd388
Work on company screen in application
Ballioli Aug 14, 2024
182580f
skeleton work for page steps
Ballioli Aug 16, 2024
720ae52
mock data and further work on steps
Ballioli Aug 26, 2024
3e3a32e
Further development of work accident notificaion application
Ballioli Sep 6, 2024
c6d57ef
Creating a new client for slysaskraning
Ballioli Sep 10, 2024
06396de
starting client setup, getting open-api from VER
Ballioli Sep 10, 2024
ce2a549
Setting up client for slysaskraning
Ballioli Sep 11, 2024
540d265
clientConfig testing removed
Ballioli Sep 11, 2024
2ccde07
further progress of work accident notification
Ballioli Sep 20, 2024
41fe5a0
fixing broken component to not push broken code
Ballioli Sep 20, 2024
051b632
Working on consistant data going back and forth in screens
Ballioli Sep 23, 2024
1d23114
MultiSelect states/answers setup, added most serious option. Missing …
Ballioli Sep 24, 2024
9baa16b
multiselect work
berglindoma13 Sep 24, 2024
9c6c01e
minor fixes, adding attributes to data schema
Ballioli Sep 25, 2024
737fbcd
adding attributes to dataschema, still incomplete in terms of refinin…
Ballioli Sep 26, 2024
b6d982b
dev readme, delete later
Ballioli Sep 27, 2024
007c1c4
merging main
sigruntg Oct 3, 2024
51ec6f0
fixing some messeges and adding seeder script
sigruntg Oct 4, 2024
634f9d3
Merge remote-tracking branch 'origin/main' into feature/aosh-work-acc…
sigruntg Oct 4, 2024
9680ea0
multiselect finished
berglindoma13 Oct 7, 2024
4f2c597
Merge branch 'feature/aosh-work-accident-notification' of https://git…
berglindoma13 Oct 7, 2024
eb9570c
dev readme, delete later v2
Ballioli Oct 10, 2024
af094fb
adding create account mockup and submitapplication
sigruntg Oct 10, 2024
f4b109a
some changes
sigruntg Oct 10, 2024
696476b
Working on multiselect screens in tilkynning vinnuslyss
Ballioli Oct 14, 2024
864b7ca
removing comments, logs and addding a useEffect to setValue to formco…
Ballioli Oct 14, 2024
5cf6008
adding 2 new screens (typeOfInjury and injuredBodyParts), minor fixes…
Ballioli Oct 15, 2024
c7e6703
changes to submitapplication
sigruntg Oct 16, 2024
5f13260
starting to index starfsmadur and orsakir screens to allow for multip…
Ballioli Oct 16, 2024
21f1897
indexing for multiple employees, data schema update, moving announcem…
Ballioli Oct 18, 2024
c3958b2
overview
sigruntg Oct 18, 2024
2345e05
conflict
sigruntg Oct 18, 2024
b18f6c0
adding indexing to ids otherwise we get graphql validation errors
Ballioli Oct 18, 2024
94dc11b
overview company
sigruntg Oct 18, 2024
9d0f292
Merge branch 'feature/aosh-work-accident-notification' of github.com:…
sigruntg Oct 18, 2024
f91369a
commenting out atvinnugreinaflokkun, will remove once confirmed it sh…
Ballioli Oct 21, 2024
2f2358a
about accident
sigruntg Oct 21, 2024
4043702
Merge branch 'feature/aosh-work-accident-notification' of github.com:…
sigruntg Oct 21, 2024
7bfb772
adding conditional radio field to verkkaup, fixing code for major and…
Ballioli Oct 22, 2024
de27fbe
adding add employees button
sigruntg Oct 22, 2024
7e4108a
Merge branch 'feature/aosh-work-accident-notification' of github.com:…
sigruntg Oct 22, 2024
7b1582f
add employee button works
sigruntg Oct 23, 2024
69849f4
bunch of schema/required/validation added
Ballioli Oct 23, 2024
cf30c95
doesnotrequireanswer added
sigruntg Oct 23, 2024
e6b5e5a
fixing merge conflict
sigruntg Oct 23, 2024
d5a75ef
zod schema additions, required on component that should be required, …
Ballioli Oct 23, 2024
791942f
Fixing mount issue when going from employee 2 to employee 1 via back …
Ballioli Oct 23, 2024
44b5d7a
adding things to overview employees and few things to submit application
sigruntg Oct 24, 2024
be1e3f7
merge confic
sigruntg Oct 24, 2024
923bd35
forgot to save
sigruntg Oct 24, 2024
27ef79f
adding template name and institution
sigruntg Oct 24, 2024
40179fb
resolving conflicts
Ballioli Oct 25, 2024
3f7bff2
adding input values and some changes to submit app
sigruntg Oct 25, 2024
fcb19be
merginign
sigruntg Oct 25, 2024
d67f2b2
submit and conclusion
sigruntg Oct 28, 2024
8c76d8d
first commit of delete functionality, some todo cleanup
Ballioli Oct 28, 2024
02208fe
remove log
Ballioli Oct 28, 2024
4b4bac1
select checkbox design
sigruntg Oct 28, 2024
8983394
Merge branch 'feature/aosh-work-accident-notification' of github.com:…
sigruntg Oct 28, 2024
24cb399
adding delete button to overview screen
Ballioli Oct 28, 2024
1dfa270
feature flag added, mobile styling fixed in overview, data schema min…
Ballioli Oct 29, 2024
c94f5a6
merge main, conflict
Ballioli Oct 29, 2024
9dc0a54
merge conflict
Ballioli Oct 29, 2024
e7b5157
fixing config module after recent main changes
Ballioli Oct 29, 2024
d8135a9
Chaning minor texts, adding README, deleting dev_readme
Ballioli Oct 29, 2024
f88e963
update messages
Ballioli Oct 29, 2024
8ef2cae
adding date check
sigruntg Oct 29, 2024
f2c93ba
Merge branch 'feature/aosh-work-accident-notification' of github.com:…
sigruntg Oct 29, 2024
bb7045c
fixing submit
sigruntg Oct 30, 2024
8479bcf
merge conflict
Ballioli Oct 30, 2024
6056090
fixing minors things from PR suggestions etc.
Ballioli Oct 30, 2024
096092b
Using Locale type
Ballioli Oct 30, 2024
0c669f5
fixing spacing on Select inputs and adding a placeholder
Ballioli Oct 30, 2024
553c97a
placeholder and message changes
Ballioli Oct 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/api/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ import { CmsTranslationsModule } from '@island.is/cms-translations'
import { FileStorageConfig } from '@island.is/file-storage'
import { AuditModule } from '@island.is/nest/audit'
import { DocumentsClientV2Config } from '@island.is/clients/documents-v2'
import { WorkAccidentClientConfig } from '@island.is/clients/work-accident-ver'

import {
ConfigModule,
Expand Down Expand Up @@ -431,6 +432,7 @@ const environment = getConfig
CriminalRecordClientConfig,
HealthInsuranceV2ClientConfig,
UmbodsmadurSkuldaraClientConfig,
WorkAccidentClientConfig,
emailModuleConfig,
],
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Module } from '@nestjs/common'
import { SharedTemplateAPIModule } from '../../../shared'
import { WorkAccidentNotificationTemplateService } from './work-accident-notification.service'
import {
WorkAccidentClientConfig,
WorkAccidentClientModule,
} from '@island.is/clients/work-accident-ver'
import { ConfigModule } from '@nestjs/config'

@Module({
imports: [
SharedTemplateAPIModule,
WorkAccidentClientModule,
ConfigModule.forRoot({
isGlobal: true,
load: [WorkAccidentClientConfig],
}),
],
providers: [WorkAccidentNotificationTemplateService],
exports: [WorkAccidentNotificationTemplateService],
})
export class WorkAccidentNotificationTemplateModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import { Inject, Injectable } from '@nestjs/common'
import { ApplicationTypes } from '@island.is/application/types'
import { BaseTemplateApiService } from '../../../base-template-api.service'

import type { Logger } from '@island.is/logging'
import { LOGGER_PROVIDER } from '@island.is/logging'
import { TemplateApiModuleActionProps } from '../../../../types'
import { WorkAccidentNotification } from '@island.is/application/templates/aosh/work-accident-notification'
import {
DataDto,
WorkAccidentClientService,
} from '@island.is/clients/work-accident-ver'
import {
getDateAndTime,
getValueList,
} from './work-accident-notification.utils'
import { getValueViaPath } from '@island.is/application/core'
import { TemplateApiError } from '@island.is/nest/problem'

@Injectable()
export class WorkAccidentNotificationTemplateService extends BaseTemplateApiService {
constructor(
@Inject(LOGGER_PROVIDER) private logger: Logger,
private readonly workAccidentClientService: WorkAccidentClientService,
) {
super(ApplicationTypes.WORK_ACCIDENT_NOTIFICATION)
}

async getInputOptions({
currentUserLocale,
auth,
}: TemplateApiModuleActionProps): Promise<DataDto> {
const data = await this.workAccidentClientService
.getOptionsData(auth, currentUserLocale)
.catch(() => {
this.logger.warn(
'[work-accident-notification-service]: Error fetching data from AOSH',
)
throw new TemplateApiError(
{
summary:
'Ekki tókst að sækja gögn til VER, vinsamlegast reynið síðar',
title: 'Villa í umsókn',
},
400,
)
})

return data
}

async submitApplication({
application,
auth,
}: TemplateApiModuleActionProps): Promise<void> {
const answers = application.answers as unknown as WorkAccidentNotification

Comment on lines +56 to +57
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider safer type handling for application answers.

The type casting using unknown could be unsafe. Consider using type guards or validation:

-const answers = application.answers as unknown as WorkAccidentNotification
+const answers = this.validateAnswers(application.answers)

+private validateAnswers(answers: unknown): WorkAccidentNotification {
+  // Add type validation logic here
+  if (!this.isWorkAccidentNotification(answers)) {
+    throw new Error('Invalid answers format')
+  }
+  return answers
+}

Committable suggestion was skipped due to low confidence.

await this.workAccidentClientService
.createAccident(auth, {
accidentForCreationDto: {
companySSN: answers.companyInformation.nationalId,
sizeOfEnterprise: parseInt(
answers.companyInformation.numberOfEmployees,
10,
),
nameOfBranchOrDepartment:
answers.companyInformation.nameOfBranch ?? '1', // TODO: Vinnueftirlit will decide what number is default
address: answers.companyInformation.address,
postcode: answers.companyInformation.postnumber.slice(0, 3),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Validate postcode slicing.

The postcode slicing assumes a fixed format but lacks validation.

Apply this diff to add validation:

-postcode: answers.companyInformation.postnumber.slice(0, 3),
+postcode: answers.companyInformation.postnumber?.slice(0, 3) ?? '',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
postcode: answers.companyInformation.postnumber.slice(0, 3),
postcode: answers.companyInformation.postnumber?.slice(0, 3) ?? '',

workplaceHealthAndSafety:
answers.companyLaborProtection.workhealthAndSafetyOccupation?.map(
(code: string) => {
return parseInt(code, 10)
},
),
buyersSSN: answers.projectPurchase.nationalId ?? '',
dateAndTimeOfAccident: getDateAndTime(
answers.accident.date,
answers.accident.time.slice(0, 2),
answers.accident.time.slice(2, 4),
),
aoshCame: answers.accident.didAoshCome === 'yes',
policeCame: answers.accident.didPoliceCome === 'yes',
numberOfVictims: answers.employee.length,
municipalityWhereAccidentOccured: answers.accident.municipality,
specificLocationOfAccident: answers.accident.exactLocation,
detailedDescriptionOfAccident: answers.accident.wasDoing.concat(
'\n',
answers.accident.wentWrong,
'\n',
answers.accident.how,
),
workingEnvironment: answers.accident.accidentLocation.value,
victims: answers.employee.map((employee, index) => {
return {
victimsSSN: employee.nationalField.nationalId,
employmentStatusOfVictim: employee.employmentStatus
? parseInt(employee.employmentStatus, 10)
: 0,
employmentAgencySSN: employee.tempEmploymentSSN ?? '',
startedEmploymentForCompany: new Date(employee.startDate),
lengthOfEmployment: employee.employmentTime
? parseInt(employee.employmentTime, 10)
: 0,
percentageOfFullWorkTime: employee.employmentRate
? parseInt(employee.employmentRate, 10)
: 0,
workhourArrangement: employee.workhourArrangement
? parseInt(employee.workhourArrangement, 10)
: 0,
startOfWorkingDay: getDateAndTime(
employee.startOfWorkdayDate,
employee.startTime.slice(0, 2),
employee.startTime.slice(2, 4),
),
workStation: employee.workstation
? parseInt(employee.workstation, 10)
: 0,
victimsOccupation: employee.victimsOccupation.value,
absenceDueToAccident: answers.absence[index]
? parseInt(answers.absence[index], 10)
: 0,
specificPhysicalActivities: getValueList(
application.answers,
`circumstances[${index}].physicalActivities`,
),
specificPhysicalActivityMostSevere:
(getValueViaPath(
application.answers,
`circumstances[${index}].physicalActivitiesMostSerious`,
undefined,
) as string | undefined) ??
getValueList(
application.answers,
`circumstances[${index}].physicalActivities`,
)[0],
workDeviations: getValueList(
application.answers,
`deviations[${index}].workDeviations`,
),
workDeviationMostSevere:
(getValueViaPath(
application.answers,
`deviations[${index}].workDeviationsMostSerious`,
undefined,
) as string | undefined) ??
getValueList(
application.answers,
`deviations[${index}].workDeviations`,
)[0],
contactModeOfInjuries: getValueList(
application.answers,
`causeOfInjury[${index}].contactModeOfInjury`,
),
contactModeOfInjuryMostSevere:
(getValueViaPath(
application.answers,
`causeOfInjury[${index}].contactModeOfInjuryMostSerious`,
undefined,
) as string | undefined) ??
getValueList(
application.answers,
`causeOfInjury[${index}].contactModeOfInjury`,
)[0],
partsOfBodyInjured: getValueList(
application.answers,
`injuredBodyParts[${index}].partOfBodyInjured`,
),
partOfBodyInjuredMostSevere:
(getValueViaPath(
application.answers,
`injuredBodyParts[${index}].partOfBodyInjuredMostSerious`,
undefined,
) as string | undefined) ??
getValueList(
application.answers,
`injuredBodyParts[${index}].partOfBodyInjured`,
)[0],
typesOfInjury: getValueList(
application.answers,
`typeOfInjury[${index}].typeOfInjury`,
),
typeOfInjuryMostSevere:
(getValueViaPath(
application.answers,
`typeOfInjury[${index}].typeOfInjuryMostSerious`,
undefined,
) as string | undefined) ??
getValueList(
application.answers,
`typeOfInjury[${index}].typeOfInjury`,
)[0],
}
}),
userPhoneNumber: answers.companyInformation.phonenumber,
userEmail: answers.companyInformation.email,
},
})
.catch(() => {
this.logger.warn(
'[work-accident-notification-service]: Error submitting application to AOSH',
)
return {
success: false,
message: 'Villa í umsókn, ekki tókst að skila umsókn til VER.',
}
})
Comment on lines +199 to +207
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve error handling in catch block.

The catch block returns an object instead of throwing an error, which could lead to silent failures.

Apply this diff to maintain consistent error handling:

 .catch(() => {
   this.logger.warn(
     '[work-accident-notification-service]: Error submitting application to AOSH',
   )
-  return {
-    success: false,
-    message: 'Villa í umsókn, ekki tókst að skila umsókn til VER.',
-  }
+  throw new TemplateApiError(
+    {
+      title: 'Villa í umsókn',
+      summary: 'Ekki tókst að skila umsókn til VER.',
+    },
+    400,
+  )
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.catch(() => {
this.logger.warn(
'[work-accident-notification-service]: Error submitting application to AOSH',
)
return {
success: false,
message: 'Villa í umsókn, ekki tókst að skila umsókn til VER.',
}
})
.catch(() => {
this.logger.warn(
'[work-accident-notification-service]: Error submitting application to AOSH',
)
throw new TemplateApiError(
{
title: 'Villa í umsókn',
summary: 'Ekki tókst að skila umsókn til VER.',
},
400,
)
})

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { getValueViaPath } from '@island.is/application/core'
import { FormValue } from '@island.is/application/types'

export const getDateAndTime = (
date: string,
hours: string,
minutes: string,
): Date => {
const finalDate = new Date(date)
finalDate.setHours(
parseInt(hours, 10), // hours
parseInt(minutes, 10), // minutes
)
return finalDate
}

export const getValueList = (answers: FormValue, answer: string) => {
const objectList = getValueViaPath(answers, answer, {}) as object

return Object.values(objectList)
.map((values: { label: string; value: string }[]) => {
return values?.map(({ value }) => {
return value
})
})
.flat()
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ import { HealthInsuranceDeclarationModule } from './health-insurance-declaration
import { HealthInsuranceDeclarationService } from './health-insurance-declaration/health-insurance-declaration.service'
import { NewPrimarySchoolModule } from './new-primary-school/new-primary-school.module'
import { NewPrimarySchoolService } from './new-primary-school/new-primary-school.service'
import { WorkAccidentNotificationTemplateModule } from './aosh/work-accident-notification/work-accident-notification.module'
import { WorkAccidentNotificationTemplateService } from './aosh/work-accident-notification/work-accident-notification.service'

import { IdCardModule } from './id-card/id-card.module'
import { IdCardService } from './id-card/id-card.service'
import { ParliamentaryListCreationModule } from './signature-collection/parliamentary-list-creation/parliamentary-list-creation.module'
Expand Down Expand Up @@ -211,6 +214,7 @@ export const modules = [
IdCardModule,
HealthInsuranceDeclarationModule,
NewPrimarySchoolModule,
WorkAccidentNotificationTemplateModule,
ParliamentaryListCreationModule,
ParliamentaryListSigningModule,
ParentalLeaveModule,
Expand Down Expand Up @@ -288,6 +292,7 @@ export const services = [
IdCardService,
HealthInsuranceDeclarationService,
NewPrimarySchoolService,
WorkAccidentNotificationTemplateService,
ParliamentaryListCreationService,
ParliamentaryListSigningService,
]
2 changes: 2 additions & 0 deletions libs/application/template-loader/src/lib/templateLoaders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ const templates: Record<ApplicationTypes, () => Promise<unknown>> = {
import('@island.is/application/templates/aosh/street-registration'),
[ApplicationTypes.REQUEST_INSPECTION_FOR_MACHINE]: () =>
import('@island.is/application/templates/aosh/request-for-inspection'),
[ApplicationTypes.WORK_ACCIDENT_NOTIFICATION]: () =>
import('@island.is/application/templates/aosh/work-accident-notification'),
[ApplicationTypes.ID_CARD]: () =>
import('@island.is/application/templates/id-card'),
[ApplicationTypes.HEALTH_INSURANCE_DECLARATION]: () =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": ["plugin:@nx/react", "../../../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Work Accident Notification application for The Administration of Occupational Safety and Health

### Description

The Work Accident Notification application allows both individual users and users with company delegations to submit accident reports. Individual users may only submit reports for their sole proprietorships, while company submissions require an assigned delegation. The application flow is nearly identical for both user types, with only minor variations in input fields based on the user’s role.

### URLs

- [Local](http://localhost:4242/umsoknir/tilkynning-um-vinnuslys)
- [Dev](https://beta.dev01.devland.is/umsoknir/tilkynning-um-vinnuslys)
- [Production](https://island.is/umsoknir/tilkynning-um-vinnuslys)

### Clients and template-api-modules

- [Client]('https://github.com/island-is/island.is/tree/main/libs/clients/work-accident-ver/src/lib/workAccident.service.ts')
- [Template-api-module]('https://github.com/island-is/island.is/blob/main/libs/application/template-api-modules/src/lib/modules/templates/aosh/work-accident-notification/work-accident-notification.service.ts')

### States

#### Prerequisite

Data fetching from National Registry, User profile and The Administration of Occupational Safety and Health

#### Draft

In the Draft state, users input essential information for the accident report. This includes details about the company involved, specifics of the accident, and information on all injured employees. After entering this data, users can review an overview page, providing a chance to verify all inputs before final submission.

#### Completed

User recieves confirmation that reports has been successfully submitted and a PDF overview of the report

### Localisation

All localisation can be found on Contentful.

- [Work Accident Notification translation]('https://app.contentful.com/spaces/8k0h54kbe6bj/entries/aosh.wan.application')
- [Application system translations](https://app.contentful.com/spaces/8k0h54kbe6bj/entries/application.system)

### Test users

- **Gervimaður Færeyjar 010130-2399 and 65°ARKTIC ehf delegation**

### Codeowners

- [Origo]('https://github.com/orgs/island-is/teams/origo')
- [Baldur Óli]('https://github.com/Ballioli')
- [Sigrún Tinna]('https://github.com/sigruntg')
Loading
Loading