From 43364249f3a92795b530aed9196141bf0968d610 Mon Sep 17 00:00:00 2001 From: bkristmundsson Date: Mon, 16 Dec 2024 12:55:35 +0000 Subject: [PATCH] TS-936 Municipality --- apps/skilavottord/web/i18n/locales/en.json | 4 +-- apps/skilavottord/web/i18n/locales/is.json | 3 +- .../screens/AccessControl/AccessControl.tsx | 3 +- .../AccessControlCreate.tsx | 5 +-- .../web/screens/Overview/Overview.tsx | 18 ++-------- .../RecyclingCompanyCreate.tsx | 7 ++-- .../RecyclingCompanyUpdate.tsx | 34 +++++++++---------- .../RecyclingFund/Overview/Overview.tsx | 10 ++---- apps/skilavottord/web/utils/accessUtils.ts | 6 ++-- ...columns-recycling-partners-municipality.js | 4 +-- .../accessControl/accessControl.resolver.ts | 9 ++++- .../recyclingPartner.input.ts | 2 +- .../recyclingPartner.resolver.ts | 23 +++++++++---- .../recyclingPartner.service.ts | 8 +++-- .../recyclingRequest.service.ts | 2 +- .../app/modules/vehicle/vehicle.resolver.ts | 1 - .../app/modules/vehicle/vehicle.service.ts | 20 +++++++---- 17 files changed, 86 insertions(+), 73 deletions(-) diff --git a/apps/skilavottord/web/i18n/locales/en.json b/apps/skilavottord/web/i18n/locales/en.json index 7a6c7430bb3a..bdb953fd87f9 100644 --- a/apps/skilavottord/web/i18n/locales/en.json +++ b/apps/skilavottord/web/i18n/locales/en.json @@ -650,14 +650,14 @@ "view": { "title": "Municipality", "breadcrumb": "View", - "info": "Þú getur annaðhvort uppfært eða eytt móttökuaðila. Vinsamlegast staðfestið að upplýsingar fyrirtækis séu rétt slegnar inn.", + "info": "You can update the municipality. Please confirm that the information are correct.", "updated": "Updated", "deleted": "Deleted" }, "add": { "title": "Add municipality", "breadcrumb": "Add new", - "info": "Þegar nýju sveitarfélagi er bætt við, verður hann aðgengilegur í aðgangsstýringu. Vinsamlegast staðfestið að upplýsingar fyrirtækis séu rétt slegnar inn.", + "info": "Adding a new municipality will make it available to access control. Please verify that the municipality information is correct.", "added": "Added" } } diff --git a/apps/skilavottord/web/i18n/locales/is.json b/apps/skilavottord/web/i18n/locales/is.json index ea0c90f89e9e..b21a598e2c5b 100644 --- a/apps/skilavottord/web/i18n/locales/is.json +++ b/apps/skilavottord/web/i18n/locales/is.json @@ -485,7 +485,8 @@ }, "municipality": { "label": "Sveitarfélag", - "placeholder": "Sveitarfélag" + "placeholder": "Sveitarfélag", + "required": "Skylda að fylla út sveitarfélag" } }, "buttons": { diff --git a/apps/skilavottord/web/screens/AccessControl/AccessControl.tsx b/apps/skilavottord/web/screens/AccessControl/AccessControl.tsx index 6d2f96643c37..e9ec6cf77ae6 100644 --- a/apps/skilavottord/web/screens/AccessControl/AccessControl.tsx +++ b/apps/skilavottord/web/screens/AccessControl/AccessControl.tsx @@ -208,7 +208,8 @@ const AccessControl: FC> = () => { recyclingPartnerLoading || accessControlsLoading || recyclingPartnerByIdLoading - const isData = !!recyclingPartnerData || !!accessControlsData + const isData = + !!recyclingPartnerData || !!recyclingPartnerByIdData || !!accessControlsData const { t: { accessControl: t, routes }, diff --git a/apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx b/apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx index 0d17f13e3ab9..159661a3f682 100644 --- a/apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx +++ b/apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx @@ -83,8 +83,9 @@ export const AccessControlCreate: FC< control={control} errors={errors} partnerIdRequired={ - watch('role')?.value === Role.recyclingCompanyAdmin || - watch('role')?.value === Role.recyclingCompany + (watch('role')?.value === Role.recyclingCompanyAdmin || + watch('role')?.value === Role.recyclingCompany) ?? + false } /> ) diff --git a/apps/skilavottord/web/screens/Overview/Overview.tsx b/apps/skilavottord/web/screens/Overview/Overview.tsx index 50360b2caf65..908a6a925081 100644 --- a/apps/skilavottord/web/screens/Overview/Overview.tsx +++ b/apps/skilavottord/web/screens/Overview/Overview.tsx @@ -1,27 +1,15 @@ -import React, { FC } from 'react' +import gql from 'graphql-tag' import Link from 'next/link' import { useRouter } from 'next/router' -import { useQuery } from '@apollo/client' -import gql from 'graphql-tag' +import React, { FC } from 'react' import { Box, - Stack, - Text, BreadcrumbsDeprecated as Breadcrumbs, - SkeletonLoader, - Button, } from '@island.is/island-ui/core' -import { PageLayout, InlineError } from '@island.is/skilavottord-web/components' +import { PageLayout } from '@island.is/skilavottord-web/components' import { useI18n } from '@island.is/skilavottord-web/i18n' -import { Query } from '@island.is/skilavottord-web/graphql/schema' - -import { filterCarsByStatus } from '@island.is/skilavottord-web/utils' -import { BASE_PATH } from '@island.is/skilavottord/consts' - -import { ActionCardContainer, ProgressCardContainer } from './components' -import { RecycleActionTypes } from './types' const SkilavottordVehiclesQuery = gql` query skilavottordVehiclesQuery { diff --git a/apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx b/apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx index a8d1c9659bbf..975e006a6abe 100644 --- a/apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx +++ b/apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx @@ -78,10 +78,9 @@ const RecyclingCompanyCreate: FC> = () => { formState: { errors }, } = useForm({ mode: 'onChange', - defaultValues: { - isMunicipality: isMunicipalityPage, - municipalityId: partnerId, - }, + defaultValues: isMunicipalityPage + ? { isMunicipalityPage } + : { isMunicipalityPage, municipalityId: partnerId }, }) const [createSkilavottordRecyclingPartner] = useMutation( diff --git a/apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx b/apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx index 35715dc492fc..aa2889870733 100644 --- a/apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx +++ b/apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx @@ -60,6 +60,7 @@ const UpdateSkilavottordRecyclingPartnerMutation = gql` website phone active + municipalityId } } ` @@ -148,36 +149,35 @@ const RecyclingCompanyUpdate: FC> = () => { return } + const navigateToBaseRoute = () => { + const route = isMunicipalityPage + ? routes.municipalities.baseRoute + : routes.recyclingCompanies.baseRoute + return router.push(route) + } + const handleUpdateRecyclingPartner = handleSubmit(async (input) => { // Not needed to be sent to the backend, causes error if it is sent delete input.__typename - if (typeof input.municipalityId !== 'string') { - input.municipalityId = input.municipalityId?.value || '' - } + const municipalityId = input.municipalityId + input.municipalityId = + typeof municipalityId === 'object' && municipalityId?.value + ? municipalityId.value + : (municipalityId as string) || '' const { errors } = await updateSkilavottordRecyclingPartner({ variables: { input }, }) if (!errors) { - if (isMunicipalityPage) { - router.push(routes.municipalities.baseRoute).then(() => { - toast.success(t.recyclingCompany.view.updated) - }) - } else { - router.push(routes.recyclingCompanies.baseRoute).then(() => { - toast.success(t.recyclingCompany.view.updated) - }) - } + navigateToBaseRoute().then(() => { + toast.success(t.recyclingCompany.view.updated) + }) } }) const handleCancel = () => { - if (isMunicipalityPage) { - router.push(routes.municipalities.baseRoute) - } else { - router.push(routes.recyclingCompanies.baseRoute) - } + navigateToBaseRoute() } return ( diff --git a/apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx b/apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx index 52aa74e794d2..80396cecf43e 100644 --- a/apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx +++ b/apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx @@ -26,12 +26,8 @@ import PageHeader from '@island.is/skilavottord-web/components/PageHeader/PageHe import { CarsTable } from './components' export const SkilavottordVehiclesQuery = gql` - query skilavottordVehiclesQuery($after: String!, $municipalityId: String!) { - skilavottordAllDeregisteredVehicles( - first: 20 - after: $after - municipalityId: $municipalityId - ) { + query skilavottordVehiclesQuery($after: String!) { + skilavottordAllDeregisteredVehicles(first: 20, after: $after) { pageInfo { endCursor hasNextPage @@ -61,7 +57,7 @@ const Overview: FC> = () => { SkilavottordVehiclesQuery, { notifyOnNetworkStatusChange: true, - variables: { after: '', municipalityId: '601' }, + variables: { after: '' }, }, ) const { pageInfo, items: vehicles } = diff --git a/apps/skilavottord/web/utils/accessUtils.ts b/apps/skilavottord/web/utils/accessUtils.ts index 315516e19a41..3cf3c09c4300 100644 --- a/apps/skilavottord/web/utils/accessUtils.ts +++ b/apps/skilavottord/web/utils/accessUtils.ts @@ -3,8 +3,8 @@ import { Role, SkilavottordUser } from '../graphql/schema' export const getPartnerId = ( user: SkilavottordUser | undefined, - municipalityId: string, - partnerId: string, + municipalityId: string | null, + partnerId: string | null, role: Role, ) => { // If the user has municipality role, then he can only create a new access under the same municipality @@ -13,5 +13,5 @@ export const getPartnerId = ( } // If selected role is municipality, use municipalityId, else use partnerId - return hasMunicipalityRole(role) ? municipalityId : partnerId || null + return hasMunicipalityRole(role) ? municipalityId ?? null : partnerId ?? null } diff --git a/apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js b/apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js index b9d686d35053..8ecf28740219 100644 --- a/apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js +++ b/apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js @@ -3,8 +3,8 @@ module.exports = { up: (queryInterface) => { return queryInterface.sequelize.query(` BEGIN; - ALTER TABLE recycling_partner ADD COLUMN is_municipality BOOLEAN; - ALTER TABLE recycling_partner ADD COLUMN municipality_id VARCHAR; + ALTER TABLE recycling_partner ADD COLUMN is_municipality BOOLEAN NOT NULL DEFAULT FALSE + ALTER TABLE recycling_partner ADD COLUMN municipality_id VARCHAR(50) CREATE INDEX idx_recycling_partner_is_municipality ON recycling_partner(is_municipality); COMMIT; `) diff --git a/apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts b/apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts index 5a767b3f98e4..8eb1b2081e75 100644 --- a/apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts +++ b/apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts @@ -67,7 +67,14 @@ export class AccessControlResolver { const isDeveloper = user.role === Role.developer if (user.role === Role.municipality) { - return this.accessControlService.findByRecyclingPartner(user.partnerId) + try { + return this.accessControlService.findByRecyclingPartner(user.partnerId) + } catch (error) { + throw new ApolloError( + 'Failed to fetch municipality access controls', + 'MUNICIPALITY_ACCESS_ERROR', + ) + } } return this.accessControlService.findAll(isDeveloper) diff --git a/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts b/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts index 59919ed6a956..645cbbfe50a4 100644 --- a/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts +++ b/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts @@ -77,7 +77,7 @@ export class UpdateRecyclingPartnerInput { @Field() email?: string - @Field() + @Field({ nullable: true }) isMunicipality?: boolean @Field({ nullable: true }) diff --git a/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts b/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts index 27c7fe6f10c1..e78186fc61df 100644 --- a/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts +++ b/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts @@ -1,4 +1,9 @@ -import { ConflictException, NotFoundException } from '@nestjs/common' +import { + BadRequestException, + ConflictException, + InternalServerErrorException, + NotFoundException, +} from '@nestjs/common' import { Args, Mutation, Query, Resolver } from '@nestjs/graphql' import { Authorize, Role } from '../auth' @@ -32,16 +37,22 @@ export class RecyclingPartnerResolver { @Query(() => [RecyclingPartnerModel], { name: 'skilavottordRecyclingPartners', }) - async getRecyclingPartners( + async skilavottordRecyclingPartners( @Args('isMunicipalityPage', { type: () => Boolean, nullable: true }) isMunicipalityPage: boolean, @Args('municipalityId', { type: () => String, nullable: true }) municipalityId: string | null, ): Promise { - return this.recyclingPartnerService.findRecyclingPartners( - isMunicipalityPage, - municipalityId, - ) + try { + return this.recyclingPartnerService.findRecyclingPartners( + isMunicipalityPage, + municipalityId, + ) + } catch (error) { + throw new InternalServerErrorException( + `Failed to fetch recycling partners: ${error.message}`, + ) + } } @Query(() => [RecyclingPartnerModel]) diff --git a/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts b/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts index fd39f982e616..b565dff3cfe8 100644 --- a/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts +++ b/apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts @@ -83,11 +83,15 @@ export class RecyclingPartnerService { * @param companyId * @returns */ - async getGetPayingPartnerId(companyId: string): Promise { + async getPayingPartnerId(companyId: string): Promise { const partner = await this.recyclingPartnerModel.findOne({ where: { companyId }, }) - return partner.municipalityId || partner.companyId + if (!partner) { + throw new Error(`Partner not found for company ID: ${companyId}`) + } + + return partner.municipalityId ?? partner.companyId } } diff --git a/apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts b/apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts index 249fe5b4819e..630c8b496f40 100644 --- a/apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts +++ b/apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts @@ -49,7 +49,7 @@ export class RecyclingRequestService { vehicle: VehicleModel, ) { const disposalStationId = - await this.recyclingPartnerService.getGetPayingPartnerId(disposalStation) + await this.recyclingPartnerService.getPayingPartnerId(disposalStation) try { const { restAuthUrl, restDeRegUrl, restUsername, restPassword } = diff --git a/apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts b/apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts index 36851cd4d7d9..ef376ec07be1 100644 --- a/apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts +++ b/apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts @@ -24,7 +24,6 @@ export class VehicleResolver { @CurrentUser() user: User, @Args('first', { type: () => Int }) first: number, @Args('after') after: string, - @Args('municipalityId') municipalityId: string, ): Promise { const { pageInfo, totalCount, data } = await this.vehicleService.findAllByFilter(first, after, { diff --git a/apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts b/apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts index c2ffd0ddddcb..6a610366d3d1 100644 --- a/apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts +++ b/apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts @@ -29,14 +29,20 @@ export class VehicleService { // else get all if (filter.partnerId) { // Get all sub recycling partners of the municipality - const subRecyclingPartners = await RecyclingPartnerModel.findAll({ - where: { municipalityId: filter.partnerId }, - }) + try { + const subRecyclingPartners = await RecyclingPartnerModel.findAll({ + where: { municipalityId: filter.partnerId }, + attributes: ['companyId'], + }) - partnerIds = [ - filter.partnerId, - ...subRecyclingPartners.map((partner) => partner.companyId), - ] + partnerIds = [ + filter.partnerId, + ...subRecyclingPartners.map((partner) => partner.companyId), + ] + } catch (error) { + this.logger.error('Failed to fetch sub-partners:', error) + throw new Error('Failed to process municipality partners') + } } else { partnerIds = null }