From 71699ba75b47d077c0701d7562cd4ba11c4c508f Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 16:14:06 -0700 Subject: [PATCH 01/12] maintain original report to make sure that report history is intact --- .vscode/settings.json | 7 +- .../src/v1/routes/pay-transparency-routes.ts | 11 +- backend/src/v1/prisma/schema.prisma | 2 + .../routes/external-consumer-routes.spec.ts | 6 +- backend/src/v1/routes/report-routes.ts | 11 +- .../external-consumer-service.spec.ts | 107 ++++++++----- .../v1/services/external-consumer-service.ts | 130 ++++++++++------ .../src/v1/services/report-service.spec.ts | 42 +++-- backend/src/v1/services/report-service.ts | 145 ++++++++++++------ frontend/src/common/apiService.ts | 2 +- frontend/src/components/DraftReportPage.vue | 3 +- 11 files changed, 290 insertions(+), 176 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index d01044931..4fba2f0a4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,5 +2,8 @@ "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.formatOnPaste": true, - "eslint.enable": false -} \ No newline at end of file + "eslint.enable": false, + "[prisma]": { + "editor.defaultFormatter": "Prisma.prisma" + } +} diff --git a/backend-external/src/v1/routes/pay-transparency-routes.ts b/backend-external/src/v1/routes/pay-transparency-routes.ts index 59af1aa8e..302b35311 100644 --- a/backend-external/src/v1/routes/pay-transparency-routes.ts +++ b/backend-external/src/v1/routes/pay-transparency-routes.ts @@ -21,7 +21,7 @@ const router = express.Router(); * type: boolean * calculation_code: * type: string - * Report: + * ReportItem: * type: object * properties: * report_id: @@ -70,6 +70,15 @@ const router = express.Router(); * type: array * items: * $ref: "#/components/schemas/CalculatedData" + * Report: + * allOf: + * - $ref: "#/components/schemas/ReportItem" + * - type: object + * properties: + * history: + * type: array + * items: + * $ref: "#/components/schemas/ReportItem" * * PaginatedReports: * type: object diff --git a/backend/src/v1/prisma/schema.prisma b/backend/src/v1/prisma/schema.prisma index 0a2b1a7cf..07c66247a 100644 --- a/backend/src/v1/prisma/schema.prisma +++ b/backend/src/v1/prisma/schema.prisma @@ -128,6 +128,7 @@ model pay_transparency_report { employee_count_range employee_count_range @relation(fields: [employee_count_range_id], references: [employee_count_range_id], onDelete: NoAction, onUpdate: NoAction, map: "pay_transparency_report_employee_count_range_id_fk") pay_transparency_company pay_transparency_company @relation(fields: [company_id], references: [company_id], onDelete: NoAction, onUpdate: NoAction, map: "report_pt_company_id_fk") pay_transparency_user pay_transparency_user @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction, map: "report_pt_user_id_fk") + history report_history[] @@index([report_id, company_id]) @@index([create_date, report_status]) @@ -170,6 +171,7 @@ model report_history { reporting_year Decimal @db.Decimal calculated_data_history calculated_data_history[] pay_transparency_company pay_transparency_company @relation(fields: [company_id], references: [company_id], onDelete: NoAction, onUpdate: NoAction, map: "report_history_company_id_fk") + pay_transparency_report pay_transparency_report @relation(fields: [report_id], references: [report_id], onDelete: NoAction, onUpdate: NoAction) employee_count_range employee_count_range @relation(fields: [employee_count_range_id], references: [employee_count_range_id], onDelete: NoAction, onUpdate: NoAction, map: "report_history_employee_count_range_id_fk") naics_code_report_history_naics_codeTonaics_code naics_code @relation("report_history_naics_codeTonaics_code", fields: [naics_code], references: [naics_code], onDelete: NoAction, onUpdate: NoAction) pay_transparency_user pay_transparency_user @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction, map: "report_history_user_id_fk") diff --git a/backend/src/v1/routes/external-consumer-routes.spec.ts b/backend/src/v1/routes/external-consumer-routes.spec.ts index 08e4f85ee..c20acaead 100644 --- a/backend/src/v1/routes/external-consumer-routes.spec.ts +++ b/backend/src/v1/routes/external-consumer-routes.spec.ts @@ -55,9 +55,10 @@ const REPORT = { { value: faker.number.float(), is_suppressed: false, - calculation_code: `${faker.number.int()}`, + calculation_code: { calculation_code: `${faker.number.int()}` }, }, ], + history: [], }; describe('external-consumer-routes', () => { @@ -84,7 +85,7 @@ describe('external-consumer-routes', () => { { calculation_code: REPORT.pay_transparency_calculated_data[0] - .calculation_code, + .calculation_code.calculation_code, is_suppressed: REPORT.pay_transparency_calculated_data[0].is_suppressed, value: REPORT.pay_transparency_calculated_data[0].value, @@ -122,6 +123,7 @@ describe('external-consumer-routes', () => { revision: REPORT.revision, update_date: REPORT.update_date.toISOString(), user_comment: REPORT.user_comment, + history: [], }, ], totalRecords: 1, diff --git a/backend/src/v1/routes/report-routes.ts b/backend/src/v1/routes/report-routes.ts index 17e0fd98c..aa28b3627 100644 --- a/backend/src/v1/routes/report-routes.ts +++ b/backend/src/v1/routes/report-routes.ts @@ -86,7 +86,7 @@ reportRouter.put( return res.status(HttpStatus.INTERNAL_SERVER_ERROR).end(); } - const reportId: string = req.params.reportId; + let reportId: string = req.params.reportId; const report_to_publish = await reportService.getReportById( bceidBusinessGuid, reportId, @@ -105,15 +105,18 @@ reportRouter.put( } try { - await reportService.publishReport(report_to_publish); + reportId = await reportService.publishReport(report_to_publish); } catch (error) { logger.error(error); return res.status(HttpStatus.BAD_REQUEST).send(error.message); } try { - const reportHtml = await reportService.getReportHtml(req, reportId); - res.type('html').status(200).send(reportHtml); + const report = await reportService.getReportById( + bceidBusinessGuid, + reportId, + ); + res.status(200).send(report); } catch (e) { logger.error(e); return res.status(HttpStatus.INTERNAL_SERVER_ERROR).end(); diff --git a/backend/src/v1/services/external-consumer-service.spec.ts b/backend/src/v1/services/external-consumer-service.spec.ts index 530bfa01b..6c9805c11 100644 --- a/backend/src/v1/services/external-consumer-service.spec.ts +++ b/backend/src/v1/services/external-consumer-service.spec.ts @@ -51,9 +51,10 @@ const testData = { { value: faker.number.float(), is_suppressed: false, - calculation_code: `${faker.number.int()}`, + calculation_code: { calculation_code: `${faker.number.int()}` }, }, ], + history: [], }; describe('external-consumer-service', () => { @@ -66,67 +67,89 @@ describe('external-consumer-service', () => { mockFindMany.mockReturnValue([testData]); const results = await externalConsumerService.exportDataWithPagination(); expect(results.page).toBe(0); - expect(results.pageSize).toBe(1000), - expect(results.totalRecords).toBe(1); - expect(results.records[0]).toEqual({ - calculated_data: [ - { - calculation_code: testData.pay_transparency_calculated_data[0].calculation_code, - is_suppressed: testData.pay_transparency_calculated_data[0].is_suppressed, - value: testData.pay_transparency_calculated_data[0].value, - }, - ], - company_address_line1: testData.pay_transparency_company.address_line1, - company_address_line2: testData.pay_transparency_company.address_line2, - company_bceid_business_guid: testData.pay_transparency_company.bceid_business_guid, - company_city: testData.pay_transparency_company.city, - company_country: testData.pay_transparency_company.country, - company_id: testData.company_id, - company_name:testData.pay_transparency_company.company_name, - company_postal_code: testData.pay_transparency_company.postal_code, - company_province: testData.pay_transparency_company.province, - create_date: testData.create_date, - data_constraints: testData.data_constraints, - employee_count_range: testData.employee_count_range.employee_count_range, - naics_code: testData.naics_code_pay_transparency_report_naics_codeTonaics_code.naics_code, - naics_code_label: testData.naics_code_pay_transparency_report_naics_codeTonaics_code.naics_label, - report_end_date: testData.report_end_date, - report_id: testData.report_id, - report_start_date: testData.report_start_date, - report_status: testData.report_status, - revision: testData.revision, - update_date: testData.update_date, - user_comment: testData.user_comment, - }) + expect(results.pageSize).toBe(1000), expect(results.totalRecords).toBe(1); + expect(results.records[0]).toStrictEqual({ + calculated_data: [ + { + is_suppressed: + testData.pay_transparency_calculated_data[0].is_suppressed, + value: testData.pay_transparency_calculated_data[0].value, + calculation_code: + testData.pay_transparency_calculated_data[0].calculation_code + .calculation_code, + }, + ], + company_address_line1: testData.pay_transparency_company.address_line1, + company_address_line2: testData.pay_transparency_company.address_line2, + company_bceid_business_guid: + testData.pay_transparency_company.bceid_business_guid, + company_city: testData.pay_transparency_company.city, + company_country: testData.pay_transparency_company.country, + company_id: testData.company_id, + company_name: testData.pay_transparency_company.company_name, + company_postal_code: testData.pay_transparency_company.postal_code, + company_province: testData.pay_transparency_company.province, + create_date: testData.create_date, + data_constraints: testData.data_constraints, + employee_count_range: testData.employee_count_range.employee_count_range, + naics_code: + testData.naics_code_pay_transparency_report_naics_codeTonaics_code + .naics_code, + naics_code_label: + testData.naics_code_pay_transparency_report_naics_codeTonaics_code + .naics_label, + report_end_date: testData.report_end_date, + report_id: testData.report_id, + report_start_date: testData.report_start_date, + report_status: testData.report_status, + revision: testData.revision, + update_date: testData.update_date, + user_comment: testData.user_comment, + history: [], + }); }); it('should parse date strings', async () => { mockCount.mockReturnValue(1); mockFindMany.mockReturnValue([testData]); - const results = await externalConsumerService.exportDataWithPagination("2024-01-01", '2024-01-01', -1, -1); + const results = await externalConsumerService.exportDataWithPagination( + '2024-01-01', + '2024-01-01', + -1, + -1, + ); expect(results.page).toBe(0); - expect(results.pageSize).toBe(1000), - expect(results.totalRecords).toBe(1); + expect(results.pageSize).toBe(1000), expect(results.totalRecords).toBe(1); }); it('should fail parse invalid date strings', async () => { mockCount.mockReturnValue(1); mockFindMany.mockReturnValue([testData]); try { - await externalConsumerService.exportDataWithPagination("20241-01-01", '20241-01-01', -1, -1); + await externalConsumerService.exportDataWithPagination( + '20241-01-01', + '20241-01-01', + -1, + -1, + ); } catch (error) { - expect(error.message).toBe( - 'Failed to parse dates. Please use date format YYYY-MM-dd', - ); + expect(error.message).toBe( + 'Failed to parse dates. Please use date format YYYY-MM-dd', + ); } }); it('should fail when endDate is before the startDate', async () => { mockCount.mockReturnValue(1); mockFindMany.mockReturnValue([testData]); try { - await externalConsumerService.exportDataWithPagination("2024-01-01", '2023-01-01', -1, -1); + await externalConsumerService.exportDataWithPagination( + '2024-01-01', + '2023-01-01', + -1, + -1, + ); } catch (error) { - expect(error.message).toBe('Start date must be before the end date.'); + expect(error.message).toBe('Start date must be before the end date.'); } }); }); diff --git a/backend/src/v1/services/external-consumer-service.ts b/backend/src/v1/services/external-consumer-service.ts index 645c1bdf9..5446a8ba4 100644 --- a/backend/src/v1/services/external-consumer-service.ts +++ b/backend/src/v1/services/external-consumer-service.ts @@ -1,11 +1,57 @@ import prismaReadOnlyReplica from '../prisma/prisma-client-readonly-replica'; -import { - LocalDate, - convert, -} from '@js-joda/core'; +import { LocalDate, convert } from '@js-joda/core'; import pick from 'lodash/pick'; import { PayTransparencyUserError } from './file-upload-service'; +const denormalizeCompany = (company) => { + return { + company_name: company.company_name, + company_province: company.province, + company_bceid_business_guid: company.bceid_business_guid, + company_city: company.city, + company_country: company.country, + company_postal_code: company.postal_code, + company_address_line1: company.address_line1, + company_address_line2: company.address_line2, + }; +}; + +const denormalizeReport = ( + report, + getNaicsCode: (report) => { naics_code: string; naics_label: string }, + getCalculatedData: (report) => { + value: string; + is_suppressed: string; + calculation_code: any; + }[], +) => { + return { + ...pick(report, [ + 'report_id', + 'company_id', + 'naics_code', + 'create_date', + 'update_date', + 'data_constraints', + 'user_comment', + 'revision', + 'report_start_date', + 'report_end_date', + 'report_status', + 'reporting_year', + ]), + ...denormalizeCompany(report.pay_transparency_company), + employee_count_range: report.employee_count_range.employee_count_range, + naics_code: getNaicsCode(report).naics_code, + naics_code_label: getNaicsCode(report).naics_label, + calculated_data: getCalculatedData(report).map((data) => ({ + value: data.value, + is_suppressed: data.is_suppressed, + calculation_code: data.calculation_code.calculation_code, + })), + }; +}; + const externalConsumerService = { /** * This function returns a list of objects with pagination details to support the analytics team. @@ -27,8 +73,7 @@ const externalConsumerService = { offset?: number, limit?: number, ) { - let startDt = LocalDate.now() - .minusMonths(1); + let startDt = LocalDate.now().minusMonths(1); let endDt = LocalDate.now().plusDays(1); if (limit > 1000 || !limit || limit <= 0) { limit = 1000; @@ -87,6 +132,18 @@ const externalConsumerService = { }, }, pay_transparency_company: true, + history: { + include: { + naics_code_report_history_naics_codeTonaics_code: true, + employee_count_range: true, + calculated_data_history: { + include: { + calculation_code: true, + }, + }, + pay_transparency_company: true, + }, + }, }, skip: offset, take: limit, @@ -96,51 +153,22 @@ const externalConsumerService = { totalRecords: totalCount, page: offset, pageSize: limit, - records: results.map( - ({ - naics_code_pay_transparency_report_naics_codeTonaics_code, - pay_transparency_calculated_data, - employee_count_range, - pay_transparency_company, - ...report - }) => { - return { - ...pick(report, [ - 'report_id', - 'company_id', - 'naics_code', - 'create_date', - 'update_date', - 'data_constraints', - 'user_comment', - 'revision', - 'report_start_date', - 'report_end_date', - 'report_status', - 'reporting_year', - ]), - company_name: pay_transparency_company.company_name, - company_province: pay_transparency_company.province, - company_bceid_business_guid: - pay_transparency_company.bceid_business_guid, - company_city: pay_transparency_company.city, - company_country: pay_transparency_company.country, - company_postal_code: pay_transparency_company.postal_code, - company_address_line1: pay_transparency_company.address_line1, - company_address_line2: pay_transparency_company.address_line2, - employee_count_range: employee_count_range.employee_count_range, - naics_code: - naics_code_pay_transparency_report_naics_codeTonaics_code.naics_code, - naics_code_label: - naics_code_pay_transparency_report_naics_codeTonaics_code.naics_label, - calculated_data: pay_transparency_calculated_data.map((data) => ({ - value: data.value, - is_suppressed: data.is_suppressed, - calculation_code: data.calculation_code, - })), - }; - }, - ), + records: results.map((report) => { + return { + ...denormalizeReport( + report, + (r) => r.naics_code_pay_transparency_report_naics_codeTonaics_code, + (r) => r.pay_transparency_calculated_data, + ), + history: report.history.map((report) => { + return denormalizeReport( + report, + (r) => r.naics_code_report_history_naics_codeTonaics_code, + (r) => r.calculated_data_history, + ); + }), + }; + }), }; }, }; diff --git a/backend/src/v1/services/report-service.spec.ts b/backend/src/v1/services/report-service.spec.ts index c21d35481..002e35d7c 100644 --- a/backend/src/v1/services/report-service.spec.ts +++ b/backend/src/v1/services/report-service.spec.ts @@ -32,6 +32,7 @@ const actualMovePublishedReportToHistory = jest.mock('./utils-service'); const mockCompanyFindFirst = jest.fn(); const mockReportFindFirst = jest.fn(); +const mockReportFindUnique = jest.fn(); jest.mock('../prisma/prisma-client', () => { return { pay_transparency_company: { @@ -40,6 +41,7 @@ jest.mock('../prisma/prisma-client', () => { update: jest.fn(), }, pay_transparency_report: { + findUnique: (...args) => mockReportFindUnique(...args), findFirst: (...args) => mockReportFindFirst(...args), create: jest.fn(), update: jest.fn(), @@ -764,7 +766,7 @@ describe('publishReport', () => { it('throws an error', async () => { await expect( reportService.publishReport(mockPublishedReportInApi), - ).rejects.toThrow(); + ).rejects.toEqual('Only draft reports can be published'); }); }); @@ -809,6 +811,10 @@ describe('publishReport', () => { describe('if the given report has status=Draft, and there is an existing Published report', () => { it('archives the existing published report in history, and changes the status of the Draft to Published', async () => { mockReportFindFirst.mockResolvedValue(mockPublishedReportInDb); + mockReportFindUnique.mockResolvedValue({ + ...mockPublishedReportInDb, + pay_transparency_calculated_data: [], + }); jest .spyOn(reportServicePrivate, 'movePublishedReportToHistory') .mockReturnValueOnce(null); @@ -834,14 +840,8 @@ describe('publishReport', () => { // Expect only one record to be updated (the report that was passed to // publishReport(...) expect(updateStatement.where.report_id).toBe( - mockDraftReportInApi.report_id, + mockPublishedReportInDb.report_id, ); - - // Expect only one column to be updated (the report status_column) - expect(updateStatement.data).toStrictEqual({ - report_status: enumReportStatus.Published, - create_date: mockPublishedReportInDb.create_date, - }); }); }); describe('if the given report has status=Draft, and there is an existing Published and locked report', () => { @@ -850,17 +850,21 @@ describe('publishReport', () => { ...mockPublishedReportInDb, is_unlocked: false, }); + mockReportFindUnique.mockReturnValue({ + ...mockDraftReportInDb, + is_unlocked: false, + pay_transparency_calculated_data: [], + }); + jest .spyOn(reportServicePrivate, 'movePublishedReportToHistory') .mockReturnValueOnce(null); - try { - await reportService.publishReport(mockDraftReportInApi); - } catch (error) { - expect(error.message).toBe( - 'A report for this time period already exists and cannot be updated.', - ); - } + await expect( + reportService.publishReport(mockDraftReportInApi), + ).rejects.toEqual( + 'A report for this time period already exists and cannot be updated.', + ); }); }); }); @@ -926,14 +930,6 @@ describe('movePublishedReportToHistory', () => { expect(deleteCalcData.where.report_id).toBe( mockPublishedReportInDb.report_id, ); - - // Confirm that the original report was deleted from the reports table - expect(prisma.pay_transparency_report.delete).toHaveBeenCalledTimes(1); - const deleteReport = (prisma.pay_transparency_report.delete as jest.Mock) - .mock.calls[0][0]; - expect(deleteReport.where.report_id).toBe( - mockPublishedReportInDb.report_id, - ); }); }); }); diff --git a/backend/src/v1/services/report-service.ts b/backend/src/v1/services/report-service.ts index c15085669..b598aa60e 100644 --- a/backend/src/v1/services/report-service.ts +++ b/backend/src/v1/services/report-service.ts @@ -5,7 +5,7 @@ import { convert, nativeJs, } from '@js-joda/core'; -import type { pay_transparency_report } from '@prisma/client'; +import type { Prisma, pay_transparency_report } from '@prisma/client'; import { config } from '../../config'; import { DISPLAY_REPORT_DATE_FORMAT, @@ -17,6 +17,8 @@ import prisma from '../prisma/prisma-client'; import { REPORT_STATUS } from './file-upload-service'; import { CALCULATION_CODES, CalculatedAmount } from './report-calc-service'; import { utils } from './utils-service'; +import omit from 'lodash/omit'; +import { report } from '../routes/code-routes'; const GENERIC_CHART_SUPPRESSED_MSG = 'This measure cannot be displayed because there is insufficient data to meet disclosure requirements.'; @@ -417,13 +419,6 @@ const reportServicePrivate = { report_id: report.report_id, }, }); - - // Delete the original report - await tx.pay_transparency_report.delete({ - where: { - report_id: report.report_id, - }, - }); }, /** @@ -1170,51 +1165,103 @@ const reportService = { return reportsAdjusted; }, - async publishReport(report_to_publish: Report) { + async publishReport(report_to_publish: Report): Promise { // Check preconditions if (report_to_publish.report_status != enumReportStatus.Draft) { - throw new Error('Only draft reports can be published'); + return Promise.reject('Only draft reports can be published'); } - await prisma.$transaction(async (tx) => { - // Check if there is an existing published report that - // corresponds to the same company_id and reporting year as - // the draft "report_to_publish". (Should be 1 published at most.) - const existing_published_report = - await tx.pay_transparency_report.findFirst({ - where: { - company_id: report_to_publish.company_id, - reporting_year: report_to_publish.reporting_year, - report_status: enumReportStatus.Published, - }, - }); - - if (existing_published_report && !existing_published_report.is_unlocked) { - throw new Error( - 'A report for this time period already exists and cannot be updated.', - ); - } - - // If there is an existing Published report, move it into - // report_history - if (existing_published_report) { - await reportServicePrivate.movePublishedReportToHistory( - tx, - existing_published_report, - ); - } - - // Change report's status to Published - await tx.pay_transparency_report.update({ - where: { - report_id: report_to_publish.report_id, - }, - data: { - report_status: enumReportStatus.Published, - create_date: - existing_published_report?.create_date || - report_to_publish.create_date, - }, + return new Promise(async (resolve, reject) => { + await prisma.$transaction(async (tx) => { + // Check if there is an existing published report that + // corresponds to the same company_id and reporting year as + // the draft "report_to_publish". (Should be 1 published at most.) + + const existing_published_report = + await tx.pay_transparency_report.findFirst({ + where: { + company_id: report_to_publish.company_id, + reporting_year: report_to_publish.reporting_year, + report_status: enumReportStatus.Published, + }, + }); + + if ( + existing_published_report && + !existing_published_report.is_unlocked + ) { + return reject( + 'A report for this time period already exists and cannot be updated.', + ); + } + + // If there is an existing Published report, move it into + // report_history + if (existing_published_report) { + const full_report_to_publish = + await tx.pay_transparency_report.findUnique({ + where: { report_id: report_to_publish.report_id }, + include: { + pay_transparency_calculated_data: { + select: { + calculation_code_id: true, + value: true, + is_suppressed: true, + create_date: true, + update_date: true, + create_user: true, + update_user: true, + }, + }, + }, + }); + await reportServicePrivate.movePublishedReportToHistory( + tx, + existing_published_report, + ); + + // Update existing report + await tx.pay_transparency_report.update({ + where: { report_id: existing_published_report.report_id }, + data: { + naics_code_pay_transparency_report_naics_codeTonaics_code: { + connect: { + naics_code: full_report_to_publish.naics_code, + }, + }, + employee_count_range: { + connect: { + employee_count_range_id: + full_report_to_publish.employee_count_range_id, + }, + }, + report_start_date: full_report_to_publish.report_start_date, + report_end_date: full_report_to_publish.report_end_date, + user_comment: full_report_to_publish.user_comment, + data_constraints: full_report_to_publish.data_constraints, + pay_transparency_calculated_data: { + createMany: { + data: full_report_to_publish.pay_transparency_calculated_data, + }, + }, + }, + }); + resolve(existing_published_report.report_id); + } else { + // Change report's status to Published + await tx.pay_transparency_report.update({ + where: { + report_id: report_to_publish.report_id, + }, + data: { + report_status: enumReportStatus.Published, + create_date: + existing_published_report?.create_date || + report_to_publish.create_date, + }, + }); + resolve(report_to_publish.report_id); + } }); }); }, diff --git a/frontend/src/common/apiService.ts b/frontend/src/common/apiService.ts index 833b8fcb5..92a43c580 100644 --- a/frontend/src/common/apiService.ts +++ b/frontend/src/common/apiService.ts @@ -261,7 +261,7 @@ export default { * Change the status of an existing report from Draft to Published. * @param {string} reportId The id of a Draft report that should be Published */ - async publishReport(reportId: string): Promise { + async publishReport(reportId: string): Promise { try { const resp = await apiAxios.put(`${ApiRoutes.REPORT}/${reportId}`); if (resp?.data) { diff --git a/frontend/src/components/DraftReportPage.vue b/frontend/src/components/DraftReportPage.vue index d13f8e295..2d6b97136 100644 --- a/frontend/src/components/DraftReportPage.vue +++ b/frontend/src/components/DraftReportPage.vue @@ -164,7 +164,8 @@ async function tryGenerateReport() { if (shouldGenerateReport) { isProcessing.value = true; try { - await ApiService.publishReport(ReportStepperStore.reportId ?? ''); + const reportData = await ApiService.publishReport(ReportStepperStore.reportId ?? ''); + await ReportStepperStore.setReportInfo(reportData); NotificationService.pushNotificationSuccess( 'You have created a pay transparency report.', ); From 3098a6b95538cdcf67a01b8f08735545c8605d53 Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 16:31:15 -0700 Subject: [PATCH 02/12] wait for report to publish --- frontend/e2e/pages/report.ts | 3 ++- frontend/e2e/report-generation.spec.ts | 7 +------ frontend/e2e/utils/generate-report.ts | 4 ++-- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/frontend/e2e/pages/report.ts b/frontend/e2e/pages/report.ts index 6fe605de0..410545d93 100644 --- a/frontend/e2e/pages/report.ts +++ b/frontend/e2e/pages/report.ts @@ -111,9 +111,10 @@ export class DraftReportPage extends BaseReportPage { await expect(confirmTitle).not.toBeVisible(); } const finalize = await finalizeReportResponse; - await finalize.text(); + const reportData = await finalize.json(); await this.instance.waitForTimeout(5000); await this.instance.waitForURL(PagePaths.VIEW_REPORT); + return reportData; } async validateCanGoBack(generateReportPage: GenerateReportPage) { diff --git a/frontend/e2e/report-generation.spec.ts b/frontend/e2e/report-generation.spec.ts index 23d7564b9..b0742a7f9 100644 --- a/frontend/e2e/report-generation.spec.ts +++ b/frontend/e2e/report-generation.spec.ts @@ -1,9 +1,4 @@ -import { expect, test } from '@playwright/test'; -import { DashboardPage } from './pages/dashboard'; -import { GenerateReportPage } from './pages/generate-report'; -import { PagePaths } from './utils'; -import { DraftReportPage, PublishedReportPage } from './pages/report'; -import { waitForApiResponses, waitForUserAndReports } from './utils/report'; +import { test } from '@playwright/test'; import { generateReport } from './utils/generate-report'; import { checkDashboardReports } from './utils/check-dashboard-reports'; import { editReport } from './utils/edit-report'; diff --git a/frontend/e2e/utils/generate-report.ts b/frontend/e2e/utils/generate-report.ts index 2284263b1..47d1dfe49 100644 --- a/frontend/e2e/utils/generate-report.ts +++ b/frontend/e2e/utils/generate-report.ts @@ -28,8 +28,8 @@ export const generateReport = async (page: Page) => { await draftReportPage.verifyEmployeerDetails(user, reportDetails); await draftReportPage.validateCanGoBack(generateReportPage); - await draftReportPage.finalizedReport(reportDetails.report_id); + const report = await draftReportPage.finalizedReport(reportDetails.report_id); const publishedReportPage = new PublishedReportPage(page, user); await publishedReportPage.setup(); - await publishedReportPage.verifyEmployeerDetails(user, reportDetails); + await publishedReportPage.verifyEmployeerDetails(user, report); } \ No newline at end of file From a8301b064e480a80cee8594ee97f62a6226df6ed Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 16:32:34 -0700 Subject: [PATCH 03/12] draft: limit to one browser --- .github/workflows/.e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/.e2e.yml b/.github/workflows/.e2e.yml index a07e3d792..39bb9aaff 100644 --- a/.github/workflows/.e2e.yml +++ b/.github/workflows/.e2e.yml @@ -57,7 +57,7 @@ jobs: strategy: max-parallel: 3 matrix: - project: [chromium, Google Chrome, firefox, safari, Microsoft Edge] + project: [chromium] #, Google Chrome, firefox, safari, Microsoft Edge] steps: - uses: actions/checkout@v4 name: Checkout From 01ba08b01b76b46d7a31a638f11a144454c98267 Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 16:47:00 -0700 Subject: [PATCH 04/12] draft: limit to one browser --- frontend/e2e/pages/report.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/e2e/pages/report.ts b/frontend/e2e/pages/report.ts index 410545d93..daa740470 100644 --- a/frontend/e2e/pages/report.ts +++ b/frontend/e2e/pages/report.ts @@ -80,8 +80,11 @@ export class DraftReportPage extends BaseReportPage { } async finalizedReport(reportId: string) { + const publishReportRequest = this.instance.waitForResponse(res => + res.url().includes('/api/v1/report') && && res.request().method().toLowerCase() === 'put' + ) const finalizeReportResponse = this.instance.waitForResponse((res) => - res.url().includes(`/api/v1/report/${reportId}`), + res.url().includes(`/api/v1/report/${reportId}`) && res.request().method().toLowerCase() === 'get', ); const getReportsRequest = this.instance.waitForResponse( (res) => @@ -110,8 +113,10 @@ export class DraftReportPage extends BaseReportPage { await yesButton.click(); await expect(confirmTitle).not.toBeVisible(); } + const publishReportResponse = await publishReportRequest; const finalize = await finalizeReportResponse; - const reportData = await finalize.json(); + await finalize.text(); + const reportData = await publishReportResponse.json(); await this.instance.waitForTimeout(5000); await this.instance.waitForURL(PagePaths.VIEW_REPORT); return reportData; From dd9782dbff0d4c7ade105377f55236c6f7fe3f43 Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 16:47:17 -0700 Subject: [PATCH 05/12] draft: limit to one browser --- frontend/e2e/pages/report.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/e2e/pages/report.ts b/frontend/e2e/pages/report.ts index daa740470..31bd41005 100644 --- a/frontend/e2e/pages/report.ts +++ b/frontend/e2e/pages/report.ts @@ -81,7 +81,7 @@ export class DraftReportPage extends BaseReportPage { async finalizedReport(reportId: string) { const publishReportRequest = this.instance.waitForResponse(res => - res.url().includes('/api/v1/report') && && res.request().method().toLowerCase() === 'put' + res.url().includes('/api/v1/report') && res.request().method().toLowerCase() === 'put' ) const finalizeReportResponse = this.instance.waitForResponse((res) => res.url().includes(`/api/v1/report/${reportId}`) && res.request().method().toLowerCase() === 'get', From bc7591920fb824b9ace6b0fe0a139bc3c6bbf6c5 Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 17:19:17 -0700 Subject: [PATCH 06/12] fix tests --- .github/workflows/.e2e.yml | 2 +- .../external-consumer-service.spec.ts | 84 ++++++++++++++++++- frontend/e2e/pages/report.ts | 3 +- frontend/e2e/utils/edit-report.ts | 4 +- 4 files changed, 87 insertions(+), 6 deletions(-) diff --git a/.github/workflows/.e2e.yml b/.github/workflows/.e2e.yml index 39bb9aaff..a07e3d792 100644 --- a/.github/workflows/.e2e.yml +++ b/.github/workflows/.e2e.yml @@ -57,7 +57,7 @@ jobs: strategy: max-parallel: 3 matrix: - project: [chromium] #, Google Chrome, firefox, safari, Microsoft Edge] + project: [chromium, Google Chrome, firefox, safari, Microsoft Edge] steps: - uses: actions/checkout@v4 name: Checkout diff --git a/backend/src/v1/services/external-consumer-service.spec.ts b/backend/src/v1/services/external-consumer-service.spec.ts index 6c9805c11..952fb4b88 100644 --- a/backend/src/v1/services/external-consumer-service.spec.ts +++ b/backend/src/v1/services/external-consumer-service.spec.ts @@ -54,7 +54,45 @@ const testData = { calculation_code: { calculation_code: `${faker.number.int()}` }, }, ], - history: [], + history: [ + { + report_id: faker.string.uuid(), + company_id: faker.string.uuid(), + naics_code: '11', + create_date: faker.date.past(), + update_date: faker.date.past(), + data_constraints: faker.lorem.sentence(), + user_comment: faker.lorem.sentence(), + revision: '12', + report_start_date: faker.date.past(), + report_end_date: faker.date.past(), + report_status: 'Published', + pay_transparency_company: { + company_name: faker.company.name(), + province: faker.location.state(), + bceid_business_guid: faker.string.uuid(), + country: faker.location.country(), + city: faker.location.city(), + postal_code: faker.location.zipCode(), + address_line1: faker.location.streetAddress(), + address_line2: faker.location.streetAddress(), + }, + employee_count_range: { + employee_count_range: '50-299', + }, + naics_code_report_history_naics_codeTonaics_code: { + naics_code: '11', + naics_label: faker.lorem.words(3), + }, + calculated_data_history: [ + { + value: faker.number.float(), + is_suppressed: false, + calculation_code: { calculation_code: `${faker.number.int()}` }, + }, + ], + }, + ], }; describe('external-consumer-service', () => { @@ -105,7 +143,49 @@ describe('external-consumer-service', () => { revision: testData.revision, update_date: testData.update_date, user_comment: testData.user_comment, - history: [], + history: [ + { + calculated_data: [ + { + is_suppressed: + testData.history[0].calculated_data_history[0].is_suppressed, + value: testData.history[0].calculated_data_history[0].value, + calculation_code: + testData.history[0].calculated_data_history[0].calculation_code + .calculation_code, + }, + ], + company_address_line1: + testData.history[0].pay_transparency_company.address_line1, + company_address_line2: + testData.history[0].pay_transparency_company.address_line2, + company_bceid_business_guid: + testData.history[0].pay_transparency_company.bceid_business_guid, + company_city: testData.history[0].pay_transparency_company.city, + company_country: testData.history[0].pay_transparency_company.country, + company_id: testData.history[0].company_id, + company_name: testData.history[0].pay_transparency_company.company_name, + company_postal_code: testData.history[0].pay_transparency_company.postal_code, + company_province: testData.history[0].pay_transparency_company.province, + create_date: testData.history[0].create_date, + data_constraints: testData.history[0].data_constraints, + employee_count_range: + testData.history[0].employee_count_range.employee_count_range, + naics_code: + testData.history[0].naics_code_report_history_naics_codeTonaics_code + .naics_code, + naics_code_label: + testData.history[0].naics_code_report_history_naics_codeTonaics_code + .naics_label, + report_end_date: testData.history[0].report_end_date, + report_id: testData.history[0].report_id, + report_start_date: testData.history[0].report_start_date, + report_status: testData.history[0].report_status, + revision: testData.history[0].revision, + update_date: testData.history[0].update_date, + user_comment: testData.history[0].user_comment, + }, + ], }); }); diff --git a/frontend/e2e/pages/report.ts b/frontend/e2e/pages/report.ts index 31bd41005..f8b64082a 100644 --- a/frontend/e2e/pages/report.ts +++ b/frontend/e2e/pages/report.ts @@ -88,7 +88,7 @@ export class DraftReportPage extends BaseReportPage { ); const getReportsRequest = this.instance.waitForResponse( (res) => - res.url().includes('/api/v1/report/?reporting_year=') && + res.url().includes('reporting_year=') && res.status() === 200, ); await this.finalReportCheckBox.scrollIntoViewIfNeeded(); @@ -117,6 +117,7 @@ export class DraftReportPage extends BaseReportPage { const finalize = await finalizeReportResponse; await finalize.text(); const reportData = await publishReportResponse.json(); + console.log(reportData) await this.instance.waitForTimeout(5000); await this.instance.waitForURL(PagePaths.VIEW_REPORT); return reportData; diff --git a/frontend/e2e/utils/edit-report.ts b/frontend/e2e/utils/edit-report.ts index 498bcaf0d..a5b1515ce 100644 --- a/frontend/e2e/utils/edit-report.ts +++ b/frontend/e2e/utils/edit-report.ts @@ -28,12 +28,12 @@ export const editReport = async (page: Page) => { await formPage.checkDefaultFormValues(reportDetails); // edit form and submit form - const report = await formPage.editReportAndSubmit(reportDetails); + let report = await formPage.editReportAndSubmit(reportDetails); const draftReportPage = new DraftReportPage(formPage.instance, user); await draftReportPage.setup(); await draftReportPage.verifyEmployeerDetails(user, null); - await draftReportPage.finalizedReport(report.report_id); + report = await draftReportPage.finalizedReport(reportId); const publishedReportPage = new PublishedReportPage(page, user); await publishedReportPage.setup(); From 4aa4afd439d5498e712bd76b6735033c46aec5b1 Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 18:00:37 -0700 Subject: [PATCH 07/12] fix sonar issues --- .../src/v1/services/report-service.spec.ts | 6 +- backend/src/v1/services/report-service.ts | 165 +++++++++--------- 2 files changed, 83 insertions(+), 88 deletions(-) diff --git a/backend/src/v1/services/report-service.spec.ts b/backend/src/v1/services/report-service.spec.ts index 002e35d7c..1f0b007ef 100644 --- a/backend/src/v1/services/report-service.spec.ts +++ b/backend/src/v1/services/report-service.spec.ts @@ -766,7 +766,7 @@ describe('publishReport', () => { it('throws an error', async () => { await expect( reportService.publishReport(mockPublishedReportInApi), - ).rejects.toEqual('Only draft reports can be published'); + ).rejects.toEqual(new Error('Only draft reports can be published')); }); }); @@ -862,9 +862,9 @@ describe('publishReport', () => { await expect( reportService.publishReport(mockDraftReportInApi), - ).rejects.toEqual( + ).rejects.toEqual(new Error( 'A report for this time period already exists and cannot be updated.', - ); + )); }); }); }); diff --git a/backend/src/v1/services/report-service.ts b/backend/src/v1/services/report-service.ts index b598aa60e..83585da58 100644 --- a/backend/src/v1/services/report-service.ts +++ b/backend/src/v1/services/report-service.ts @@ -5,7 +5,7 @@ import { convert, nativeJs, } from '@js-joda/core'; -import type { Prisma, pay_transparency_report } from '@prisma/client'; +import type { pay_transparency_report } from '@prisma/client'; import { config } from '../../config'; import { DISPLAY_REPORT_DATE_FORMAT, @@ -17,8 +17,6 @@ import prisma from '../prisma/prisma-client'; import { REPORT_STATUS } from './file-upload-service'; import { CALCULATION_CODES, CalculatedAmount } from './report-calc-service'; import { utils } from './utils-service'; -import omit from 'lodash/omit'; -import { report } from '../routes/code-routes'; const GENERIC_CHART_SUPPRESSED_MSG = 'This measure cannot be displayed because there is insufficient data to meet disclosure requirements.'; @@ -1168,102 +1166,99 @@ const reportService = { async publishReport(report_to_publish: Report): Promise { // Check preconditions if (report_to_publish.report_status != enumReportStatus.Draft) { - return Promise.reject('Only draft reports can be published'); + throw new Error('Only draft reports can be published'); } - return new Promise(async (resolve, reject) => { - await prisma.$transaction(async (tx) => { - // Check if there is an existing published report that - // corresponds to the same company_id and reporting year as - // the draft "report_to_publish". (Should be 1 published at most.) - - const existing_published_report = - await tx.pay_transparency_report.findFirst({ - where: { - company_id: report_to_publish.company_id, - reporting_year: report_to_publish.reporting_year, - report_status: enumReportStatus.Published, - }, - }); + let reportId = report_to_publish.user_id; + await prisma.$transaction(async (tx) => { + // Check if there is an existing published report that + // corresponds to the same company_id and reporting year as + // the draft "report_to_publish". (Should be 1 published at most.) + + const existing_published_report = + await tx.pay_transparency_report.findFirst({ + where: { + company_id: report_to_publish.company_id, + reporting_year: report_to_publish.reporting_year, + report_status: enumReportStatus.Published, + }, + }); - if ( - existing_published_report && - !existing_published_report.is_unlocked - ) { - return reject( + if (existing_published_report && !existing_published_report.is_unlocked) { + throw new Error( 'A report for this time period already exists and cannot be updated.', ); - } - - // If there is an existing Published report, move it into - // report_history - if (existing_published_report) { - const full_report_to_publish = - await tx.pay_transparency_report.findUnique({ - where: { report_id: report_to_publish.report_id }, - include: { - pay_transparency_calculated_data: { - select: { - calculation_code_id: true, - value: true, - is_suppressed: true, - create_date: true, - update_date: true, - create_user: true, - update_user: true, - }, - }, - }, - }); - await reportServicePrivate.movePublishedReportToHistory( - tx, - existing_published_report, - ); + } - // Update existing report - await tx.pay_transparency_report.update({ - where: { report_id: existing_published_report.report_id }, - data: { - naics_code_pay_transparency_report_naics_codeTonaics_code: { - connect: { - naics_code: full_report_to_publish.naics_code, - }, - }, - employee_count_range: { - connect: { - employee_count_range_id: - full_report_to_publish.employee_count_range_id, - }, - }, - report_start_date: full_report_to_publish.report_start_date, - report_end_date: full_report_to_publish.report_end_date, - user_comment: full_report_to_publish.user_comment, - data_constraints: full_report_to_publish.data_constraints, + // If there is an existing Published report, move it into + // report_history + if (existing_published_report) { + const full_report_to_publish = + await tx.pay_transparency_report.findUnique({ + where: { report_id: report_to_publish.report_id }, + include: { pay_transparency_calculated_data: { - createMany: { - data: full_report_to_publish.pay_transparency_calculated_data, + select: { + calculation_code_id: true, + value: true, + is_suppressed: true, + create_date: true, + update_date: true, + create_user: true, + update_user: true, }, }, }, }); - resolve(existing_published_report.report_id); - } else { - // Change report's status to Published - await tx.pay_transparency_report.update({ - where: { - report_id: report_to_publish.report_id, + await reportServicePrivate.movePublishedReportToHistory( + tx, + existing_published_report, + ); + + // Update existing report + await tx.pay_transparency_report.update({ + where: { report_id: existing_published_report.report_id }, + data: { + naics_code_pay_transparency_report_naics_codeTonaics_code: { + connect: { + naics_code: full_report_to_publish.naics_code, + }, + }, + employee_count_range: { + connect: { + employee_count_range_id: + full_report_to_publish.employee_count_range_id, + }, }, - data: { - report_status: enumReportStatus.Published, - create_date: - existing_published_report?.create_date || - report_to_publish.create_date, + report_start_date: full_report_to_publish.report_start_date, + report_end_date: full_report_to_publish.report_end_date, + user_comment: full_report_to_publish.user_comment, + data_constraints: full_report_to_publish.data_constraints, + pay_transparency_calculated_data: { + createMany: { + data: full_report_to_publish.pay_transparency_calculated_data, + }, }, - }); - resolve(report_to_publish.report_id); - } - }); + }, + }); + reportId = existing_published_report.report_id; + } else { + // Change report's status to Published + await tx.pay_transparency_report.update({ + where: { + report_id: report_to_publish.report_id, + }, + data: { + report_status: enumReportStatus.Published, + create_date: + existing_published_report?.create_date || + report_to_publish.create_date, + }, + }); + } }); + + return reportId; }, /** From ca0a1eefd5e6fc0fb4c51eb3835ac28b49ff3f59 Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 19:20:43 -0700 Subject: [PATCH 08/12] get schema using db pull --- .vscode/settings.json | 3 ++ backend/src/v1/prisma/schema.prisma | 15 +++--- .../routes/external-consumer-routes.spec.ts | 2 +- .../external-consumer-service.spec.ts | 50 +++++++++---------- .../v1/services/external-consumer-service.ts | 4 +- .../src/v1/services/report-service.spec.ts | 1 + 6 files changed, 41 insertions(+), 34 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4fba2f0a4..b043ade4f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,8 @@ "eslint.enable": false, "[prisma]": { "editor.defaultFormatter": "Prisma.prisma" + }, + "[sql]": { + "editor.defaultFormatter": "inferrinizzard.prettier-sql-vscode" } } diff --git a/backend/src/v1/prisma/schema.prisma b/backend/src/v1/prisma/schema.prisma index 07c66247a..cee3a2601 100644 --- a/backend/src/v1/prisma/schema.prisma +++ b/backend/src/v1/prisma/schema.prisma @@ -121,19 +121,21 @@ model pay_transparency_report { revision Decimal @db.Decimal data_constraints String? @db.VarChar(3000) is_unlocked Boolean @default(true) - report_unlock_date DateTime? @db.Timestamp(6) reporting_year Decimal @db.Decimal + report_unlock_date DateTime? @db.Timestamp(6) pay_transparency_calculated_data pay_transparency_calculated_data[] naics_code_pay_transparency_report_naics_codeTonaics_code naics_code @relation("pay_transparency_report_naics_codeTonaics_code", fields: [naics_code], references: [naics_code], onDelete: NoAction, onUpdate: NoAction, map: "pay_transparency_report_naics_code_fk") employee_count_range employee_count_range @relation(fields: [employee_count_range_id], references: [employee_count_range_id], onDelete: NoAction, onUpdate: NoAction, map: "pay_transparency_report_employee_count_range_id_fk") pay_transparency_company pay_transparency_company @relation(fields: [company_id], references: [company_id], onDelete: NoAction, onUpdate: NoAction, map: "report_pt_company_id_fk") pay_transparency_user pay_transparency_user @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction, map: "report_pt_user_id_fk") - history report_history[] + report_history report_history[] + @@unique([company_id, user_id, reporting_year, report_status], map: "pay_transparency_report_uk") @@index([report_id, company_id]) @@index([create_date, report_status]) - @@index([company_id, report_start_date, report_end_date, report_status]) - @@index([company_id, create_date, report_start_date, report_end_date, report_status]) + @@index([company_id, create_date, reporting_year, report_status], map: "pay_transparency_report_company_id_create_date_report_year_idx") + @@index([company_id, reporting_year, report_status], map: "pay_transparency_report_company_id_reporting_year_report_idx") + @@index([report_unlock_date, is_unlocked]) } model pay_transparency_user { @@ -166,14 +168,15 @@ model report_history { naics_code String @db.VarChar(5) data_constraints String? @db.VarChar(3000) revision Decimal @db.Decimal - report_unlock_date DateTime? @db.Timestamp(6) is_unlocked Boolean @default(true) reporting_year Decimal @db.Decimal + report_lock_date DateTime? @db.Timestamp(6) + report_unlock_date DateTime? @db.Timestamp(6) calculated_data_history calculated_data_history[] pay_transparency_company pay_transparency_company @relation(fields: [company_id], references: [company_id], onDelete: NoAction, onUpdate: NoAction, map: "report_history_company_id_fk") - pay_transparency_report pay_transparency_report @relation(fields: [report_id], references: [report_id], onDelete: NoAction, onUpdate: NoAction) employee_count_range employee_count_range @relation(fields: [employee_count_range_id], references: [employee_count_range_id], onDelete: NoAction, onUpdate: NoAction, map: "report_history_employee_count_range_id_fk") naics_code_report_history_naics_codeTonaics_code naics_code @relation("report_history_naics_codeTonaics_code", fields: [naics_code], references: [naics_code], onDelete: NoAction, onUpdate: NoAction) + pay_transparency_report pay_transparency_report @relation(fields: [report_id], references: [report_id], onDelete: NoAction, onUpdate: NoAction, map: "report_history_report_id") pay_transparency_user pay_transparency_user @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction, map: "report_history_user_id_fk") } diff --git a/backend/src/v1/routes/external-consumer-routes.spec.ts b/backend/src/v1/routes/external-consumer-routes.spec.ts index c20acaead..051196f67 100644 --- a/backend/src/v1/routes/external-consumer-routes.spec.ts +++ b/backend/src/v1/routes/external-consumer-routes.spec.ts @@ -58,7 +58,7 @@ const REPORT = { calculation_code: { calculation_code: `${faker.number.int()}` }, }, ], - history: [], + report_history: [], }; describe('external-consumer-routes', () => { diff --git a/backend/src/v1/services/external-consumer-service.spec.ts b/backend/src/v1/services/external-consumer-service.spec.ts index 952fb4b88..9cdf46f8f 100644 --- a/backend/src/v1/services/external-consumer-service.spec.ts +++ b/backend/src/v1/services/external-consumer-service.spec.ts @@ -54,7 +54,7 @@ const testData = { calculation_code: { calculation_code: `${faker.number.int()}` }, }, ], - history: [ + report_history: [ { report_id: faker.string.uuid(), company_id: faker.string.uuid(), @@ -148,42 +148,42 @@ describe('external-consumer-service', () => { calculated_data: [ { is_suppressed: - testData.history[0].calculated_data_history[0].is_suppressed, - value: testData.history[0].calculated_data_history[0].value, + testData.report_history[0].calculated_data_history[0].is_suppressed, + value: testData.report_history[0].calculated_data_history[0].value, calculation_code: - testData.history[0].calculated_data_history[0].calculation_code + testData.report_history[0].calculated_data_history[0].calculation_code .calculation_code, }, ], company_address_line1: - testData.history[0].pay_transparency_company.address_line1, + testData.report_history[0].pay_transparency_company.address_line1, company_address_line2: - testData.history[0].pay_transparency_company.address_line2, + testData.report_history[0].pay_transparency_company.address_line2, company_bceid_business_guid: - testData.history[0].pay_transparency_company.bceid_business_guid, - company_city: testData.history[0].pay_transparency_company.city, - company_country: testData.history[0].pay_transparency_company.country, - company_id: testData.history[0].company_id, - company_name: testData.history[0].pay_transparency_company.company_name, - company_postal_code: testData.history[0].pay_transparency_company.postal_code, - company_province: testData.history[0].pay_transparency_company.province, - create_date: testData.history[0].create_date, - data_constraints: testData.history[0].data_constraints, + testData.report_history[0].pay_transparency_company.bceid_business_guid, + company_city: testData.report_history[0].pay_transparency_company.city, + company_country: testData.report_history[0].pay_transparency_company.country, + company_id: testData.report_history[0].company_id, + company_name: testData.report_history[0].pay_transparency_company.company_name, + company_postal_code: testData.report_history[0].pay_transparency_company.postal_code, + company_province: testData.report_history[0].pay_transparency_company.province, + create_date: testData.report_history[0].create_date, + data_constraints: testData.report_history[0].data_constraints, employee_count_range: - testData.history[0].employee_count_range.employee_count_range, + testData.report_history[0].employee_count_range.employee_count_range, naics_code: - testData.history[0].naics_code_report_history_naics_codeTonaics_code + testData.report_history[0].naics_code_report_history_naics_codeTonaics_code .naics_code, naics_code_label: - testData.history[0].naics_code_report_history_naics_codeTonaics_code + testData.report_history[0].naics_code_report_history_naics_codeTonaics_code .naics_label, - report_end_date: testData.history[0].report_end_date, - report_id: testData.history[0].report_id, - report_start_date: testData.history[0].report_start_date, - report_status: testData.history[0].report_status, - revision: testData.history[0].revision, - update_date: testData.history[0].update_date, - user_comment: testData.history[0].user_comment, + report_end_date: testData.report_history[0].report_end_date, + report_id: testData.report_history[0].report_id, + report_start_date: testData.report_history[0].report_start_date, + report_status: testData.report_history[0].report_status, + revision: testData.report_history[0].revision, + update_date: testData.report_history[0].update_date, + user_comment: testData.report_history[0].user_comment, }, ], }); diff --git a/backend/src/v1/services/external-consumer-service.ts b/backend/src/v1/services/external-consumer-service.ts index 5446a8ba4..0450c6a37 100644 --- a/backend/src/v1/services/external-consumer-service.ts +++ b/backend/src/v1/services/external-consumer-service.ts @@ -132,7 +132,7 @@ const externalConsumerService = { }, }, pay_transparency_company: true, - history: { + report_history: { include: { naics_code_report_history_naics_codeTonaics_code: true, employee_count_range: true, @@ -160,7 +160,7 @@ const externalConsumerService = { (r) => r.naics_code_pay_transparency_report_naics_codeTonaics_code, (r) => r.pay_transparency_calculated_data, ), - history: report.history.map((report) => { + history: report.report_history.map((report) => { return denormalizeReport( report, (r) => r.naics_code_report_history_naics_codeTonaics_code, diff --git a/backend/src/v1/services/report-service.spec.ts b/backend/src/v1/services/report-service.spec.ts index 1f0b007ef..042417013 100644 --- a/backend/src/v1/services/report-service.spec.ts +++ b/backend/src/v1/services/report-service.spec.ts @@ -149,6 +149,7 @@ const mockPublishedReportInApi: Report = const mockHistoryReport: report_history = { report_history_id: '567', + report_lock_date: new Date(), ...mockPublishedReportInDb, }; From 63c00032363b3dfbcd6463fc9285e86597e85a4f Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 19:20:50 -0700 Subject: [PATCH 09/12] get schema using db pull --- backend/db/migrations/V1.0.22__report_id_fk_in_history.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 backend/db/migrations/V1.0.22__report_id_fk_in_history.sql diff --git a/backend/db/migrations/V1.0.22__report_id_fk_in_history.sql b/backend/db/migrations/V1.0.22__report_id_fk_in_history.sql new file mode 100644 index 000000000..565725dd6 --- /dev/null +++ b/backend/db/migrations/V1.0.22__report_id_fk_in_history.sql @@ -0,0 +1,4 @@ +SET + search_path TO pay_transparency; + +ALTER TABLE report_history ADD CONSTRAINT report_history_report_id FOREIGN KEY (report_id) REFERENCES pay_transparency_report (report_id); \ No newline at end of file From 570acd8e8807539670e3ebb7d08da329f0a18e8c Mon Sep 17 00:00:00 2001 From: goemen Date: Wed, 17 Apr 2024 19:43:40 -0700 Subject: [PATCH 10/12] fix schema --- backend/src/v1/prisma/schema.prisma | 1 - backend/src/v1/services/report-service.spec.ts | 1 - frontend/e2e/pages/report.ts | 1 - 3 files changed, 3 deletions(-) diff --git a/backend/src/v1/prisma/schema.prisma b/backend/src/v1/prisma/schema.prisma index cee3a2601..7e4309607 100644 --- a/backend/src/v1/prisma/schema.prisma +++ b/backend/src/v1/prisma/schema.prisma @@ -170,7 +170,6 @@ model report_history { revision Decimal @db.Decimal is_unlocked Boolean @default(true) reporting_year Decimal @db.Decimal - report_lock_date DateTime? @db.Timestamp(6) report_unlock_date DateTime? @db.Timestamp(6) calculated_data_history calculated_data_history[] pay_transparency_company pay_transparency_company @relation(fields: [company_id], references: [company_id], onDelete: NoAction, onUpdate: NoAction, map: "report_history_company_id_fk") diff --git a/backend/src/v1/services/report-service.spec.ts b/backend/src/v1/services/report-service.spec.ts index 042417013..1f0b007ef 100644 --- a/backend/src/v1/services/report-service.spec.ts +++ b/backend/src/v1/services/report-service.spec.ts @@ -149,7 +149,6 @@ const mockPublishedReportInApi: Report = const mockHistoryReport: report_history = { report_history_id: '567', - report_lock_date: new Date(), ...mockPublishedReportInDb, }; diff --git a/frontend/e2e/pages/report.ts b/frontend/e2e/pages/report.ts index f8b64082a..fce6bcf27 100644 --- a/frontend/e2e/pages/report.ts +++ b/frontend/e2e/pages/report.ts @@ -117,7 +117,6 @@ export class DraftReportPage extends BaseReportPage { const finalize = await finalizeReportResponse; await finalize.text(); const reportData = await publishReportResponse.json(); - console.log(reportData) await this.instance.waitForTimeout(5000); await this.instance.waitForURL(PagePaths.VIEW_REPORT); return reportData; From f8e989bb1fbb0bc9a751a646b4be4b969e917139 Mon Sep 17 00:00:00 2001 From: goemen Date: Thu, 18 Apr 2024 09:02:21 -0700 Subject: [PATCH 11/12] add more report publish update fields --- backend/src/v1/services/report-service.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/src/v1/services/report-service.ts b/backend/src/v1/services/report-service.ts index 83585da58..6dfa796bc 100644 --- a/backend/src/v1/services/report-service.ts +++ b/backend/src/v1/services/report-service.ts @@ -1234,6 +1234,9 @@ const reportService = { report_end_date: full_report_to_publish.report_end_date, user_comment: full_report_to_publish.user_comment, data_constraints: full_report_to_publish.data_constraints, + revision: parseInt(existing_published_report.revision as any) + 1, + update_date: full_report_to_publish.update_date, + update_user: full_report_to_publish.update_user, pay_transparency_calculated_data: { createMany: { data: full_report_to_publish.pay_transparency_calculated_data, From bbc9d1cabb3ec7f2badb4ac14939769ad4cd7ec8 Mon Sep 17 00:00:00 2001 From: goemen Date: Thu, 18 Apr 2024 09:46:51 -0700 Subject: [PATCH 12/12] set correct report id --- backend/src/v1/services/report-service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/v1/services/report-service.ts b/backend/src/v1/services/report-service.ts index 6dfa796bc..e58bae407 100644 --- a/backend/src/v1/services/report-service.ts +++ b/backend/src/v1/services/report-service.ts @@ -1169,7 +1169,7 @@ const reportService = { throw new Error('Only draft reports can be published'); } - let reportId = report_to_publish.user_id; + let reportId = report_to_publish.report_id; await prisma.$transaction(async (tx) => { // Check if there is an existing published report that // corresponds to the same company_id and reporting year as