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

Devex 1187: Penalty #4152

Merged
merged 6 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 13 additions & 18 deletions shared/src/business/entities/Penalty.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,20 @@ import { applicationContext } from '../test/createTestApplicationContext';

describe('Penalty', () => {
describe('validation', () => {
let statisticId;
beforeAll(() => {
statisticId = '5666ad04-4814-4b0c-8090-ba01683917ac';
});
let mockStatisticId = '5666ad04-4814-4b0c-8090-ba01683917ac';

it('should fail if name is undefined', () => {
const penalty = new Penalty(
{
irsPenaltyAmount: 100.0,
name: undefined,
statisticId,
statisticId: mockStatisticId,
},
{ applicationContext },
);

expect(penalty.isValid()).toBeFalsy();
expect(Object.keys(penalty.getFormattedValidationErrors())).toContain(
'name',
);
expect(Object.keys(penalty.getValidationErrors()!)).toContain('name');
});

it('should fail if penaltyAmount is undefined', () => {
Expand All @@ -31,13 +26,13 @@ describe('Penalty', () => {
name: 'Penalty 1 (IRS)',
penaltyAmount: undefined,
penaltyType: PENALTY_TYPES.IRS_PENALTY_AMOUNT,
statisticId,
statisticId: mockStatisticId,
},
{ applicationContext },
);

expect(penalty.isValid()).toBe(false);
expect(Object.keys(penalty.getFormattedValidationErrors())).toContain(
expect(Object.keys(penalty.getValidationErrors()!)).toContain(
'penaltyAmount',
);
});
Expand All @@ -48,13 +43,13 @@ describe('Penalty', () => {
name: 'Penalty 1 (IRS)',
penaltyAmount: 'something',
penaltyType: PENALTY_TYPES.IRS_PENALTY_AMOUNT,
statisticId,
statisticId: mockStatisticId,
},
{ applicationContext },
);

expect(penalty.isValid()).toBe(false);
expect(Object.keys(penalty.getFormattedValidationErrors())).toContain(
expect(Object.keys(penalty.getValidationErrors()!)).toContain(
'penaltyAmount',
);
});
Expand All @@ -65,13 +60,13 @@ describe('Penalty', () => {
name: 'Penalty 1 (IRS)',
penaltyAmount: 100.0,
penaltyType: undefined,
statisticId,
statisticId: mockStatisticId,
},
{ applicationContext },
);

expect(penalty.isValid()).toBe(false);
expect(Object.keys(penalty.getFormattedValidationErrors())).toContain(
expect(Object.keys(penalty.getValidationErrors()!)).toContain(
'penaltyType',
);
});
Expand All @@ -88,7 +83,7 @@ describe('Penalty', () => {
);

expect(penalty.isValid()).toBe(false);
expect(Object.keys(penalty.getFormattedValidationErrors())).toContain(
expect(Object.keys(penalty.getValidationErrors()!)).toContain(
'statisticId',
);
});
Expand All @@ -99,7 +94,7 @@ describe('Penalty', () => {
name: 'Penalty 1 (IRS)',
penaltyAmount: 100.0,
penaltyType: PENALTY_TYPES.IRS_PENALTY_AMOUNT,
statisticId,
statisticId: mockStatisticId,
},
{ applicationContext },
);
Expand All @@ -113,7 +108,7 @@ describe('Penalty', () => {
name: 'Penalty 1 (Court)',
penaltyAmount: 100.0,
penaltyType: PENALTY_TYPES.DETERMINATION_PENALTY_AMOUNT,
statisticId,
statisticId: mockStatisticId,
},
{ applicationContext },
);
Expand All @@ -127,7 +122,7 @@ describe('Penalty', () => {
name: 'Penalty 1 (IRS)',
penaltyAmount: -422.68,
penaltyType: PENALTY_TYPES.IRS_PENALTY_AMOUNT,
statisticId,
statisticId: mockStatisticId,
},
{ applicationContext },
);
Expand Down
37 changes: 14 additions & 23 deletions shared/src/business/entities/Penalty.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { JoiValidationConstants } from './JoiValidationConstants';
import { JoiValidationEntity } from './JoiValidationEntity';
import { JoiValidationEntity_New } from '@shared/business/entities/joiValidationEntity/JoiValidationEntity_New';
import { PENALTY_TYPES } from './EntityConstants';
import joi from 'joi';

export class Penalty extends JoiValidationEntity {
export class Penalty extends JoiValidationEntity_New {
public name: string;
public penaltyType: string;
public penaltyAmount: string;
public penaltyId: string;
public penaltyType: string;
public statisticId: string;

constructor(rawProps, { applicationContext }) {
super('Penalty');

if (!applicationContext) {
throw new TypeError('applicationContext must be defined');
}
Expand All @@ -23,42 +24,32 @@ export class Penalty extends JoiValidationEntity {
this.statisticId = rawProps.statisticId;
}

static VALIDATION_ERROR_MESSAGES = {
name: 'Penalty name is required.',
penaltyAmount: 'Enter penalty amount.',
penaltyType: 'Penalty type is required.',
statisticId: 'Statistic ID is required.',
};

static VALIDATION_RULES = joi.object().keys({
entityName: JoiValidationConstants.STRING.valid('Penalty').required(),
name: JoiValidationConstants.STRING.max(50)
.required()
.description('Penalty name.'),
.description('Penalty name.')
.messages({ '*': 'Penalty name is required.' }),
penaltyAmount: joi
.number()
.required()
.description('The dollar amount of the penalty.'),
.description('The dollar amount of the penalty.')
.messages({ '*': 'Enter penalty amount.' }),
penaltyId: JoiValidationConstants.UUID.required().description(
'Unique Penalty ID only used by the system.',
),
penaltyType: JoiValidationConstants.STRING.required()
.valid(...Object.values(PENALTY_TYPES))
.description('The type of penalty (IRS or Court Determination).'),
statisticId: JoiValidationConstants.UUID.required().description(
'Unique statistic ID only used by the system.',
),
.description('The type of penalty (IRS or Court Determination).')
.messages({ '*': 'Penalty type is required.' }),
statisticId: JoiValidationConstants.UUID.required()
.description('Unique statistic ID only used by the system.')
.messages({ '*': 'Statistic ID is required.' }),
});

getValidationRules() {
return Penalty.VALIDATION_RULES;
}

getErrorToMessageMap() {
return Penalty.VALIDATION_ERROR_MESSAGES;
}
}

declare global {
type RawPenalty = ExcludeMethods<Penalty>;
}
export type RawPenalty = ExcludeMethods<Penalty>;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { applicationContext } from '../test/createTestApplicationContext';
import { validatePenaltiesInteractor } from './validatePenaltiesInteractor';

describe('validatePenaltiesInteractor', () => {
it('runs validation on a Penalty with no invalid properties', () => {
it('should not return validation erros when the penalty is valid', () => {
const mockPenalty = {
name: 'Penalty 1(IRS)',
penaltyAmount: 100.0,
Expand All @@ -15,10 +15,10 @@ describe('validatePenaltiesInteractor', () => {
rawPenalty: mockPenalty,
});

expect(errors).toBeUndefined();
expect(errors).toEqual(null);
});

it('runs validation on a penalty with invalid properties', () => {
it('should return validation errors when the penalty is NOT valid', () => {
const invalidMockPenalty = {
name: 5, // must be a string to be valid
penaltyAmount: '', // invalid due to expecting a numerical input
Expand Down
17 changes: 3 additions & 14 deletions shared/src/business/useCases/validatePenaltiesInteractor.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
import { Penalty } from '../entities/Penalty';
import { isEmpty } from 'lodash';

/**
* validatePenaltiesInteractor
*
* @param {object} applicationContext the application context
* @param {object} providers the providers object
* @param {object} providers.rawPenalty the penalty to validate
* @returns {object} errors (undefined if no errors)
*/
export const validatePenaltiesInteractor = (
applicationContext: IApplicationContext,
{ rawPenalty }: { rawPenalty: object },
) => {
const penaltyErrors = new Penalty(rawPenalty, {
): Record<string, string> | null => {
return new Penalty(rawPenalty, {
applicationContext,
}).getFormattedValidationErrors();

return !isEmpty(penaltyErrors) ? penaltyErrors : undefined;
}).getValidationErrors();
};
Loading