Skip to content

Commit

Permalink
Merge pull request #634 from code4romania/bugfix/438
Browse files Browse the repository at this point in the history
fix: [438] Bugfixing for Financial Information
  • Loading branch information
radulescuandrew authored Sep 3, 2024
2 parents 8f5239b + 3c6cc68 commit 7669c3f
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 6 deletions.
135 changes: 135 additions & 0 deletions backend/src/migrations/1725362133806-OrgViewUpdateAdminEmail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class OrgViewUpdateAdminEmail1725362133806
implements MigrationInterface
{
name = 'OrgViewUpdateAdminEmail1725362133806';

public async up(queryRunner: QueryRunner): Promise<void> {
// Drop the existing view and its metadata
await queryRunner.query(
`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`,
['VIEW', 'OrganizationView', 'public'],
);
await queryRunner.query(`DROP VIEW "OrganizationView"`);

// Create the updated view
// Changes:
// - "adminEmail" now uses "organization_general".contact_person->>'email' instead of "organization_general".email because we are interested in "Contact person in relation with ONGHub"
await queryRunner.query(`CREATE VIEW "OrganizationView" AS
SELECT
"organization".id AS "id",
"organization".status AS "status",
"organization".created_on AS "createdOn",
CASE
WHEN COUNT(DISTINCT CASE WHEN "organization_financial".status != 'Completed' AND "organization_financial".status IS NOT NULL THEN 1 END) > 0
OR COUNT(DISTINCT CASE WHEN "report".status != 'Completed' AND "report".status IS NOT NULL THEN 1 END) > 0
OR COUNT(DISTINCT CASE WHEN "partner".status != 'Completed' AND "partner".status IS NOT NULL THEN 1 END) > 0
OR COUNT(DISTINCT CASE WHEN "investor".status != 'Completed' AND "investor".status IS NOT NULL THEN 1 END) > 0
THEN 'Not Completed'
ELSE 'Completed'
END AS "completionStatus",
"organization_general".name AS "name",
"organization_general".alias AS "alias",
"organization_general".contact_person->>'email' AS "adminEmail",
COUNT(DISTINCT "user".id) AS "userCount",
"organization_general".logo AS "logo",
CASE
WHEN MAX(GREATEST(COALESCE("organization_financial".updated_on, '1970-01-01'), COALESCE("report".updated_on, '1970-01-01'), COALESCE("partner".updated_on, '1970-01-01'), COALESCE("investor".updated_on, '1970-01-01'))) = '1970-01-01'
THEN NULL
ELSE MAX(GREATEST(COALESCE("organization_financial".updated_on, '1970-01-01'), COALESCE("report".updated_on, '1970-01-01'), COALESCE("partner".updated_on, '1970-01-01'), COALESCE("investor".updated_on, '1970-01-01')))::text
END AS "updatedOn"
FROM
"organization" "organization"
LEFT JOIN "organization_general" "organization_general" ON "organization".organization_general_id = "organization_general".id
LEFT JOIN "user" "user" ON "user".organization_id = "organization".id
AND "user".deleted_on IS NULL
AND "user".ROLE = 'employee'
AND "user".status != 'pending'
LEFT JOIN "organization_financial" "organization_financial" ON "organization".id = "organization_financial"."organizationId"
LEFT JOIN "organization_report" "organization_report" ON "organization".organization_report_id = "organization_report".id
LEFT JOIN "report" "report" ON "organization_report".id = "report"."organizationReportId"
LEFT JOIN "partner" "partner" ON "organization_report".id = "partner"."organizationReportId"
LEFT JOIN "investor" "investor" ON "organization_report".id = "investor"."organizationReportId"
WHERE
"organization".status != 'pending'
GROUP BY
"organization".id,
"organization_general".id
`);

// Insert metadata for the new view
await queryRunner.query(
`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`,
[
'public',
'VIEW',
'OrganizationView',
'SELECT\n "organization".id AS "id",\n "organization".status AS "status",\n "organization".created_on AS "createdOn",\n \tCASE \n WHEN COUNT(DISTINCT CASE WHEN "organization_financial".status != \'Completed\' AND "organization_financial".status IS NOT NULL THEN 1 END) > 0\n OR COUNT(DISTINCT CASE WHEN "report".status != \'Completed\' AND "report".status IS NOT NULL THEN 1 END) > 0\n OR COUNT(DISTINCT CASE WHEN "partner".status != \'Completed\' AND "partner".status IS NOT NULL THEN 1 END) > 0\n OR COUNT(DISTINCT CASE WHEN "investor".status != \'Completed\' AND "investor".status IS NOT NULL THEN 1 END) > 0\n THEN \'Not Completed\'\n ELSE \'Completed\'\n \tEND AS "completionStatus",\n "organization_general".name AS "name",\n "organization_general".alias AS "alias",\n "organization_general".contact_person->>\'email\' AS "adminEmail",\n COUNT(DISTINCT "user".id) AS "userCount",\n "organization_general".logo AS "logo",\n CASE\n WHEN MAX(GREATEST(COALESCE("organization_financial".updated_on, \'1970-01-01\'), COALESCE("report".updated_on, \'1970-01-01\'), COALESCE("partner".updated_on, \'1970-01-01\'), COALESCE("investor".updated_on, \'1970-01-01\'))) = \'1970-01-01\'\n THEN NULL\n ELSE MAX(GREATEST(COALESCE("organization_financial".updated_on, \'1970-01-01\'), COALESCE("report".updated_on, \'1970-01-01\'), COALESCE("partner".updated_on, \'1970-01-01\'), COALESCE("investor".updated_on, \'1970-01-01\')))::text\n END AS "updatedOn"\n FROM\n "organization" "organization"\n LEFT JOIN "organization_general" "organization_general" ON "organization".organization_general_id = "organization_general".id\n LEFT JOIN "user" "user" ON "user".organization_id = "organization".id\n AND "user".deleted_on IS NULL\n AND "user".ROLE = \'employee\'\n AND "user".status != \'pending\'\n LEFT JOIN "organization_financial" "organization_financial" ON "organization".id = "organization_financial"."organizationId"\n LEFT JOIN "organization_report" "organization_report" ON "organization".organization_report_id = "organization_report".id\n LEFT JOIN "report" "report" ON "organization_report".id = "report"."organizationReportId"\n LEFT JOIN "partner" "partner" ON "organization_report".id = "partner"."organizationReportId"\n LEFT JOIN "investor" "investor" ON "organization_report".id = "investor"."organizationReportId"\n WHERE\n "organization".status != \'pending\'\n GROUP BY\n "organization".id,\n "organization_general".id',
],
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
// Drop the updated view and its metadata
await queryRunner.query(
`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`,
['VIEW', 'OrganizationView', 'public'],
);
await queryRunner.query(`DROP VIEW "OrganizationView"`);

// Recreate the original view
// Changes:
// - "adminEmail" now uses "organization_general".email instead of "organization_general".contact_person->>'email'
await queryRunner.query(`CREATE VIEW "OrganizationView" AS SELECT
"organization".id AS "id",
"organization".status AS "status",
"organization".created_on AS "createdOn",
CASE
WHEN COUNT(DISTINCT CASE WHEN "organization_financial".status != 'Completed' AND "organization_financial".status IS NOT NULL THEN 1 END) > 0
OR COUNT(DISTINCT CASE WHEN "report".status != 'Completed' AND "report".status IS NOT NULL THEN 1 END) > 0
OR COUNT(DISTINCT CASE WHEN "partner".status != 'Completed' AND "partner".status IS NOT NULL THEN 1 END) > 0
OR COUNT(DISTINCT CASE WHEN "investor".status != 'Completed' AND "investor".status IS NOT NULL THEN 1 END) > 0
THEN 'Not Completed'
ELSE 'Completed'
END AS "completionStatus",
"organization_general".name AS "name",
"organization_general".alias AS "alias",
"organization_general".email AS "adminEmail",
COUNT(DISTINCT "user".id) AS "userCount",
"organization_general".logo AS "logo",
CASE
WHEN MAX(GREATEST(COALESCE("organization_financial".updated_on, '1970-01-01'), COALESCE("report".updated_on, '1970-01-01'), COALESCE("partner".updated_on, '1970-01-01'), COALESCE("investor".updated_on, '1970-01-01'))) = '1970-01-01'
THEN NULL
ELSE MAX(GREATEST(COALESCE("organization_financial".updated_on, '1970-01-01'), COALESCE("report".updated_on, '1970-01-01'), COALESCE("partner".updated_on, '1970-01-01'), COALESCE("investor".updated_on, '1970-01-01')))::text
END AS "updatedOn"
FROM
"organization" "organization"
LEFT JOIN "organization_general" "organization_general" ON "organization".organization_general_id = "organization_general".id
LEFT JOIN "user" "user" ON "user".organization_id = "organization".id
AND "user".deleted_on IS NULL
AND "user".ROLE = 'employee'
AND "user".status != 'pending'
LEFT JOIN "organization_financial" "organization_financial" ON "organization".id = "organization_financial"."organizationId"
LEFT JOIN "organization_report" "organization_report" ON "organization".organization_report_id = "organization_report".id
LEFT JOIN "report" "report" ON "organization_report".id = "report"."organizationReportId"
LEFT JOIN "partner" "partner" ON "organization_report".id = "partner"."organizationReportId"
LEFT JOIN "investor" "investor" ON "organization_report".id = "investor"."organizationReportId"
WHERE
"organization".status != 'pending'
GROUP BY
"organization".id,
"organization_general".id`);

// Insert metadata for the original view
await queryRunner.query(
`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`,
[
'public',
'VIEW',
'OrganizationView',
'SELECT\n "organization".id AS "id",\n "organization".status AS "status",\n "organization".created_on AS "createdOn",\n \tCASE \n WHEN COUNT(DISTINCT CASE WHEN "organization_financial".status != \'Completed\' AND "organization_financial".status IS NOT NULL THEN 1 END) > 0\n OR COUNT(DISTINCT CASE WHEN "report".status != \'Completed\' AND "report".status IS NOT NULL THEN 1 END) > 0\n OR COUNT(DISTINCT CASE WHEN "partner".status != \'Completed\' AND "partner".status IS NOT NULL THEN 1 END) > 0\n OR COUNT(DISTINCT CASE WHEN "investor".status != \'Completed\' AND "investor".status IS NOT NULL THEN 1 END) > 0\n THEN \'Not Completed\'\n ELSE \'Completed\'\n \tEND AS "completionStatus",\n "organization_general".name AS "name",\n "organization_general".alias AS "alias",\n "organization_general".email AS "adminEmail",\n COUNT(DISTINCT "user".id) AS "userCount",\n "organization_general".logo AS "logo",\n CASE\n WHEN MAX(GREATEST(COALESCE("organization_financial".updated_on, \'1970-01-01\'), COALESCE("report".updated_on, \'1970-01-01\'), COALESCE("partner".updated_on, \'1970-01-01\'), COALESCE("investor".updated_on, \'1970-01-01\'))) = \'1970-01-01\'\n THEN NULL\n ELSE MAX(GREATEST(COALESCE("organization_financial".updated_on, \'1970-01-01\'), COALESCE("report".updated_on, \'1970-01-01\'), COALESCE("partner".updated_on, \'1970-01-01\'), COALESCE("investor".updated_on, \'1970-01-01\')))::text\n END AS "updatedOn"\n FROM\n "organization" "organization"\n LEFT JOIN "organization_general" "organization_general" ON "organization".organization_general_id = "organization_general".id\n LEFT JOIN "user" "user" ON "user".organization_id = "organization".id\n AND "user".deleted_on IS NULL\n AND "user".ROLE = \'employee\'\n AND "user".status != \'pending\'\n LEFT JOIN "organization_financial" "organization_financial" ON "organization".id = "organization_financial"."organizationId"\n LEFT JOIN "organization_report" "organization_report" ON "organization".organization_report_id = "organization_report".id\n LEFT JOIN "report" "report" ON "organization_report".id = "report"."organizationReportId"\n LEFT JOIN "partner" "partner" ON "organization_report".id = "partner"."organizationReportId"\n LEFT JOIN "investor" "investor" ON "organization_report".id = "investor"."organizationReportId"\n WHERE\n "organization".status != \'pending\'\n GROUP BY\n "organization".id,\n "organization_general".id',
],
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { OrganizationStatus } from '../enums/organization-status.enum';
END AS "completionStatus",
"organization_general".name AS "name",
"organization_general".alias AS "alias",
"organization_general".email AS "adminEmail",
"organization_general".contact_person->>'email' AS "adminEmail",
COUNT(DISTINCT "user".id) AS "userCount",
"organization_general".logo AS "logo",
CASE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,35 @@ export class OrganizationFinancialService {
return obj.indicator === 'I46';
});

// If any of the required indicators are undefined, it likely means
// the CUI is not for an NGO or the ANAF service structure has changed
if (
income === undefined ||
expense === undefined ||
employees === undefined
) {
const missingIndicators = [
income === undefined ? 'I38 (income)' : null,
expense === undefined ? 'I40 (expense)' : null,
employees === undefined ? 'I46 (employees)' : null,
]
.filter(Boolean)
.join(', ');

const sentryMessage = `ANAF data missing required indicators (${missingIndicators}) for CUI: ${cui}, Year: ${year}`;
Sentry.captureMessage(sentryMessage, {
level: 'warning',
extra: {
cui,
year,
anafData,
missingIndicators,
},
});
this.logger.warn(sentryMessage);
return null;
}

return {
numberOfEmployees: employees?.val_indicator,
totalExpense: expense?.val_indicator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,16 +237,27 @@ export class OrganizationReportService {
organization: Organization;
year: number;
}): Promise<void> {
const organizationReport = organization.organizationReport;
let organizationReport = organization.organizationReport;

if (!organizationReport) {
const newOrganizationReport =
await this.organizationReportRepository.save({
organization: { id: organization.id },
reports: [],
partners: [],
investors: [],
});
organizationReport = newOrganizationReport;
}

// Check if the given organizationId has already reports for the given year to avoid duplicating them
const hasReport = organizationReport.reports.find(
const hasReport = organizationReport?.reports.find(
(report) => report.year === year,
);
const hasPartners = organizationReport.partners.find(
const hasPartners = organizationReport?.partners.find(
(partner) => partner.year === year,
);
const hasInvestors = organizationReport.investors.find(
const hasInvestors = organizationReport?.investors.find(
(investor) => investor.year === year,
);

Expand All @@ -272,6 +283,7 @@ export class OrganizationReportService {
: {}),
});
} catch (err) {
console.log(err);
Sentry.captureException(err, {
extra: {
organization,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,24 @@ export class OrganizationService {
),
}
: {}),
// Initialize organizationReport based on whether the organization existed last year
...(organizationExistedLastYear
? {
// If the organization existed last year, create initial reports, partners, and investors for that year
organizationReport: {
reports: [{ year: lastYear }],
partners: [{ year: lastYear }],
investors: [{ year: lastYear }],
},
}
: {}),
: {
// If the organization is new, initialize empty arrays for reports, partners, and investors
organizationReport: {
reports: [],
partners: [],
investors: [],
},
}),
});

// upload logo
Expand Down

0 comments on commit 7669c3f

Please sign in to comment.