Skip to content

Commit

Permalink
Merge branch 'j-s/civil-claimant-data-structure' of https://github.co…
Browse files Browse the repository at this point in the history
…m/island-is/island.is into j-s/civil-claimant-data-structure
  • Loading branch information
unakb committed Sep 18, 2024
2 parents 5487ba2 + 2b5064c commit 1e8c24a
Show file tree
Hide file tree
Showing 21 changed files with 243 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ import {
SignatureConfirmationResponse,
} from '../case'
import { CaseListEntry } from '../case-list'
import { Defendant, DeleteDefendantResponse } from '../defendant'
import { CivilClaimant } from '../defendant/models/civilClaimant.model'
import { DeleteCivilClaimantResponse } from '../defendant/models/deleteCivilClaimant.response'
import {
CivilClaimant,
Defendant,
DeleteCivilClaimantResponse,
DeleteDefendantResponse,
} from '../defendant'
import { CreateEventLogInput } from '../event-log'
import {
CaseFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ import {
UserRole,
} from '@island.is/judicial-system/types'

import { Defendant } from '../../defendant'
import { CivilClaimant } from '../../defendant/models/civilClaimant.model'
import { CivilClaimant, Defendant } from '../../defendant'
import { EventLog } from '../../event-log'
import { CaseFile } from '../../file'
import { IndictmentCount } from '../../indictment-count'
Expand Down
2 changes: 2 additions & 0 deletions apps/judicial-system/api/src/app/modules/defendant/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { Defendant } from './models/defendant.model'
export { DeleteDefendantResponse } from './models/delete.response'
export { CivilClaimant } from './models/civilClaimant.model'
export { DeleteCivilClaimantResponse } from './models/deleteCivilClaimant.response'
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ import {
} from '../../formatters'
import { AwsS3Service } from '../aws-s3'
import { CourtService } from '../court'
import { Defendant, DefendantService } from '../defendant'
import { CivilClaimant } from '../defendant/models/civilClaimant.model'
import { CivilClaimant, Defendant, DefendantService } from '../defendant'
import { EventService } from '../event'
import { EventLog, EventLogService } from '../event-log'
import { CaseFile, FileService } from '../file'
Expand Down Expand Up @@ -396,6 +395,7 @@ export const caseListInclude: Includeable[] = [

export const listOrder: OrderItem[] = [
[{ model: Defendant, as: 'defendants' }, 'created', 'ASC'],
[{ model: CivilClaimant, as: 'civilClaimants' }, 'created', 'ASC'],
[{ model: DateLog, as: 'dateLogs' }, 'created', 'DESC'],
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ import {
UserRole,
} from '@island.is/judicial-system/types'

import { Defendant } from '../../defendant'
import { CivilClaimant } from '../../defendant/models/civilClaimant.model'
import { CivilClaimant, Defendant } from '../../defendant'
import { EventLog } from '../../event-log'
import { CaseFile } from '../../file'
import { IndictmentCount } from '../../indictment-count'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { Defendant } from './models/defendant.model'
export { DefendantService } from './defendant.service'
export { CivilClaimant } from './models/civilClaimant.model'
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = {
up: async (queryInterface, Sequelize) => {
// Add the 'endorsement_count' column to 'endorsement_list' table
await queryInterface.addColumn('endorsement_list', 'endorsement_count', {
type: Sequelize.INTEGER,
allowNull: false,
defaultValue: 0,
})

// Add composite index on 'endorsement_count' and 'counter'
await queryInterface.addIndex(
'endorsement_list',
['endorsement_count', 'counter'],
{
name: 'idx_endorsement_count_counter',
},
)
},

down: async (queryInterface, Sequelize) => {
// Remove the composite index on 'endorsement_count' and 'counter'
await queryInterface.removeIndex(
'endorsement_list',
'idx_endorsement_count_counter',
)

// Remove the 'endorsement_count' column from 'endorsement_list' table
await queryInterface.removeColumn('endorsement_list', 'endorsement_count')
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,50 @@ export class EndorsementService {
private readonly awsService: AwsService,
) {}

async onModuleInit() {
this.logger.info(
'Updating endorsement counts for all lists onModuleInit...',
)
try {
await this.updateCountsForAllLists()
} catch (error) {
this.logger.error(
'Error updating endorsement counts for all lists',
error,
)
}
}

async updateCountsForAllLists(): Promise<void> {
const allLists = await this.endorsementListModel.findAll()
for (const list of allLists) {
await this.updateEndorsementCountOnList(list.id)
}
this.logger.info('All endorsement counts have been updated.')
}

async updateEndorsementCountOnList(listId: string): Promise<void> {
const count = await this.endorsementModel.count({
where: { endorsementListId: listId },
})
const [affectedRows, updatedList] = await this.endorsementListModel.update(
{ endorsementCount: count },
{
where: { id: listId },
returning: true,
},
)
if (affectedRows > 0 && updatedList[0].endorsementCount === count) {
this.logger.info(
`Successfully updated endorsement count for list "${listId}" to ${count}`,
)
} else {
this.logger.warn(
`Failed to update endorsement count for list "${listId}". The count was not updated correctly.`,
)
}
}

async findEndorsements({ listId }: FindEndorsementsInput, query: any) {
this.logger.info(`Finding endorsements by list id "${listId}"`)

Expand Down Expand Up @@ -111,7 +155,6 @@ export class EndorsementService {
return { hasEndorsed: true }
}

// FIXME: Find a way to combine with create bulk endorsements
async createEndorsementOnList({
endorsementList,
nationalId,
Expand All @@ -136,20 +179,20 @@ export class EndorsementService {
},
}

return this.endorsementModel.create(endorsement).catch((error) => {
// map meaningful sequelize errors to custom errors, else return error
switch (error.constructor) {
case UniqueConstraintError: {
this.logger.warn('Endorsement already exists in list')
throw new MethodNotAllowedException([
'Endorsement already exists in list',
])
}
default: {
throw error
}
try {
const createdEndorsement = await this.endorsementModel.create(endorsement)
await this.updateEndorsementCountOnList(endorsementList.id)
return createdEndorsement
} catch (error) {
if (error instanceof UniqueConstraintError) {
this.logger.warn('Endorsement already exists in list')
throw new MethodNotAllowedException([
'Endorsement already exists in list',
])
} else {
throw error
}
})
}
}

async deleteFromListByNationalId({
Expand Down Expand Up @@ -182,5 +225,6 @@ export class EndorsementService {
)
throw new NotFoundException(["This endorsement doesn't exist"])
}
await this.updateEndorsementCountOnList(endorsementList.id)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,20 @@ export class EndorsementListDto {
@IsObject()
meta = {}

@ApiProperty({ type: Date })
@ApiProperty({ type: Date, default: new Date() }) // default today
@Type(() => Date)
@IsDate()
closedDate!: Date
openedDate!: Date

@ApiProperty({ type: Date })
@ApiProperty({
type: Date,
default: new Date(new Date().setMonth(new Date().getMonth() + 1)),
}) // default month from today
@Type(() => Date)
@IsDate()
openedDate!: Date
closedDate!: Date

@ApiProperty({ type: Boolean })
@ApiProperty({ type: Boolean, default: false })
@IsBoolean()
adminLock!: boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,15 @@ export class EndorsementList extends Model {
})
@UpdatedAt
readonly modified!: Date

@ApiProperty({
type: Number,
description: 'The number of endorsements in the list',
})
@Column({
type: DataType.INTEGER,
allowNull: false,
defaultValue: 0,
})
endorsementCount!: number
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import {
Injectable,
NotFoundException,
BadRequestException,
ForbiddenException,
} from '@nestjs/common'
import { InjectModel } from '@nestjs/sequelize'
import { col, Op, Sequelize } from 'sequelize'
import { Op } from 'sequelize'
import type { Logger } from '@island.is/logging'
import { LOGGER_PROVIDER } from '@island.is/logging'
import { EndorsementList } from './endorsementList.model'
Expand Down Expand Up @@ -74,7 +73,6 @@ export class EndorsementListService {
}
}

// generic reusable query with pagination defaults
async findListsGenericQuery(query: any, where: any = {}) {
this.logger.info(`Finding endorsement lists`)
return await paginate({
Expand All @@ -83,28 +81,8 @@ export class EndorsementListService {
after: query.after,
before: query.before,
primaryKeyField: 'counter',
orderOption: [
['endorsementCounter', 'DESC'],
['counter', 'DESC'],
],
orderOption: [['endorsementCount', 'DESC']],
where: where,
attributes: {
include: [
[
Sequelize.fn('COUNT', Sequelize.col('endorsements.id')),
'endorsementCounter',
],
],
},
include: [
{
model: Endorsement,
required: false, // Required false for left outer join so that counts come for 0 as well
duplicating: false,
attributes: [],
},
],
group: ['EndorsementList.id'],
})
}

Expand All @@ -127,8 +105,6 @@ export class EndorsementListService {
}

async findSingleList(listId: string, user?: User, check?: boolean) {
// Check variable needed since finAll function in Endorsement controller uses this function twice
// on the second call it passes nationalID of user but does not go throught the get list pipe
const isAdmin = user && check ? this.hasAdminScope(user) : false
this.logger.info(`Finding single endorsement lists by id "${listId}"`)
const result = await this.endorsementListModel.findOne({
Expand Down Expand Up @@ -259,15 +235,13 @@ export class EndorsementListService {
this.logger.info(`Creating endorsement list: ${list.title}`)
const endorsementList = await this.endorsementListModel.create({ ...list })

console.log('process.env.NODE_ENV', process.env.NODE_ENV)
if (process.env.NODE_ENV === 'production') {
await this.emailCreated(endorsementList)
}

return endorsementList
}

// generic get open lists
async findOpenListsTaggedGeneralPetition(query: any) {
const dateOb = new Date()
try {
Expand Down Expand Up @@ -305,9 +279,6 @@ export class EndorsementListService {
}

async getOwnerInfo(listId: string, owner?: string) {
// Is used by both unauthenticated users, authenticated users and admin
// Admin needs to access locked lists and can not use the EndorsementListById pipe
// Since the endpoint is not authenticated
this.logger.info(`Finding single endorsement lists by id "${listId}"`)
if (!owner) {
const endorsementList = await this.endorsementListModel.findOne({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,9 @@ export const OrganizationHeader: React.FC<
/>
)
case 'utlendingastofnun':
return (
return n('usingDefaultHeader', false) ? (
<DefaultHeader {...defaultProps} />
) : (
<UtlendingastofnunHeader
organizationPage={organizationPage}
logoAltText={logoAltText}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict'

module.exports = {
async up(queryInterface) {
return queryInterface.sequelize.query(`
BEGIN;
-- 1. Drop the existing unique constraint on (domain_name, from_national_id, to_national_id)
ALTER TABLE delegation
DROP CONSTRAINT IF EXISTS unique_domain_from_to;
-- 2. Alter the domain_name column to allow NULL and remove the default value
ALTER TABLE delegation
ALTER COLUMN domain_name DROP DEFAULT,
ALTER COLUMN domain_name DROP NOT NULL;
-- 3. Create a new unique index to enforce uniqueness where NULL is treated as a value
CREATE UNIQUE INDEX unique_domain_from_to_index
ON delegation (COALESCE(domain_name, 'NULL'), from_national_id, to_national_id);
COMMIT;
`)
},

async down(queryInterface) {
return queryInterface.sequelize.query(`
BEGIN;
-- 1. Drop the unique index created with COALESCE
DROP INDEX IF EXISTS unique_domain_from_to_index;
-- 2. Alter the domain_name column to make it NOT NULL again and add the default value
ALTER TABLE delegation
ALTER COLUMN domain_name SET DEFAULT '@island.is',
ALTER COLUMN domain_name SET NOT NULL;
-- 3. Recreate the original unique constraint on (domain_name, from_national_id, to_national_id)
ALTER TABLE delegation ADD CONSTRAINT unique_domain_from_to
UNIQUE (domain_name, from_national_id, to_national_id);
COMMIT;
`)
},
}
Loading

0 comments on commit 1e8c24a

Please sign in to comment.