Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3e6f8ce
Move name to claims
thomas-young1 Dec 1, 2025
49cc8d5
Return line items with claim data
thomas-young1 Dec 1, 2025
9adca95
Generic icons/UI
thomas-young1 Dec 1, 2025
823e507
Add linking endpoints
thomas-young1 Dec 1, 2025
95bba90
Disaster info page
thomas-young1 Dec 1, 2025
88ea441
Clean up personal info page
thomas-young1 Dec 1, 2025
3592af8
Business info step
thomas-young1 Dec 1, 2025
cfbd63a
Fix progress names
thomas-young1 Dec 1, 2025
9682a62
Insurance page
thomas-young1 Dec 1, 2025
b8d3578
Fix frontend lock
thomas-young1 Dec 1, 2025
b8ad3da
Fix tests
thomas-young1 Dec 1, 2025
bdb2385
Fix lints
thomas-young1 Dec 1, 2025
9c0b97d
Restore hasData check
thomas-young1 Dec 2, 2025
d3b00fa
Make insurance optional
thomas-young1 Dec 2, 2025
a7bdd06
Make locations editable
thomas-young1 Dec 2, 2025
66591ca
save and close button
thomas-young1 Dec 2, 2025
60aa09e
extend existing insurance card
thomas-young1 Dec 2, 2025
a626feb
Generate PDFs
thomas-young1 Dec 2, 2025
96c2112
use react-icons
thomas-young1 Dec 2, 2025
62c979e
pdf creation issues
jacktoncelli Dec 3, 2025
601cae7
renaming claim pdfs
jacktoncelli Dec 3, 2025
5c854ab
fixed submitting document
ZainabImadulla Dec 3, 2025
8881792
Merge branch 'feature/claim-frontend-reworks' of https://github.com/G…
ZainabImadulla Dec 3, 2025
e0684fa
fixing pdf styling and data
jacktoncelli Dec 3, 2025
7d85984
fixed end date error
ZainabImadulla Dec 3, 2025
755147f
Merge branch 'main' into feature/claim-frontend-reworks
jacktoncelli Dec 3, 2025
9a872b6
merge and lint
jacktoncelli Dec 3, 2025
c609739
lint
jacktoncelli Dec 3, 2025
2f207ad
incorrect optional field
jacktoncelli Dec 3, 2025
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
3 changes: 2 additions & 1 deletion backend/src/database/factories/claim.factory.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { setSeederFactory } from "typeorm-extension";
import { ClaimStatusType } from "../../types/ClaimStatusType";
import { Claim } from "../../entities/Claim";
import { ClaimStatusType } from "../../types/ClaimStatusType";

export default setSeederFactory(Claim, (faker) => {
const claim = new Claim();
claim.id = faker.string.uuid();
claim.name = faker.string.sample(10);
claim.companyId = faker.string.uuid(); // This should be set to actual company IDs in tests to work
claim.status = faker.helpers.enumValue(ClaimStatusType);
claim.createdAt = faker.date.past();
Expand Down
5 changes: 5 additions & 0 deletions backend/src/database/seeds/claim.seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const seededClaims = [
{
// Claim 1 - NEU to Disaster 1
id: "4b3a2f1e-0d9c-8b7a-6f5e-4d3c2b1a0f9e",
name: "Claim 1",
createdAt: new Date(),
updatedAt: new Date(),
companyId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
Expand All @@ -16,6 +17,7 @@ const seededClaims = [
{
// Claim 2 - NEU to Disaster 4
id: "7e8f9a0b-1c2d-3e4f-5a6b-7c8d9e0f1a2b",
name: "Claim 2",
createdAt: new Date(),
updatedAt: new Date(),
companyId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
Expand All @@ -25,6 +27,7 @@ const seededClaims = [
{
// Claim 3 - Big Corp to Disaster 5
id: "0c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
name: "Claim 3",
createdAt: new Date(),
updatedAt: new Date(),
companyId: "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
Expand All @@ -34,6 +37,7 @@ const seededClaims = [
{
// Claim 4 - Small LLC to Disaster 3
id: "3f4e5d6c-7b8a-9f0e-1d2c-3b4a5f6e7d8c",
name: "Claim 4",
createdAt: new Date(),
updatedAt: new Date(),
companyId: "0b6d17e5-37fa-4fe6-bca5-1a18051ae222",
Expand All @@ -43,6 +47,7 @@ const seededClaims = [
{
// Claim 5 - Business to Disaster 3
id: "bdf8bcfe-23e1-41b6-ba4f-e846efbaaebe",
name: "Claim 5",
createdAt: new Date(),
updatedAt: new Date(),
companyId: "7f8e9d0c-1b2a-3c4d-5e6f-7a8b9c0d1e2f",
Expand Down
2 changes: 0 additions & 2 deletions backend/src/database/seeds/selfDisaster.seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import { seededCompanies } from "./company.seed";
export const seededSelfDisasters: Partial<SelfDeclaredDisaster>[] = [
{
id: "ba5735c4-fbd1-4f7d-97c1-bf5af2a3f533",
name: "Test Disaster 1",
companyId: seededCompanies[0].id,
description: "Hello world",
startDate: new Date("01/01/2025"),
},
{
id: "bf2b32dd-c927-440b-8002-84906db3c783",
name: "Test Disaster 2",
companyId: seededCompanies[0].id,
description: "Hello world",
startDate: new Date("06/20/2025"),
Expand Down
29 changes: 16 additions & 13 deletions backend/src/entities/Claim.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import type { Relation } from "typeorm";
import {
Entity,
PrimaryGeneratedColumn,
Check,
Column,
ManyToOne,
JoinColumn,
Unique,
CreateDateColumn,
UpdateDateColumn,
OneToMany,
Check,
Entity,
JoinColumn,
JoinTable,
ManyToMany,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
Unique,
UpdateDateColumn,
} from "typeorm";
import type { Relation } from "typeorm";
import { Company } from "./Company.js";
import { FemaDisaster } from "./FemaDisaster.js";
import { ClaimStatusType } from "../types/ClaimStatusType.js";
import { ClaimLocation } from "./ClaimLocation.js";
import { SelfDeclaredDisaster } from "./SelfDisaster.js";
import { PurchaseLineItem } from "./PurchaseLineItem.js";
import { Company } from "./Company.js";
import { FemaDisaster } from "./FemaDisaster.js";
import { InsurancePolicy } from "./InsurancePolicy.js";
import { PurchaseLineItem } from "./PurchaseLineItem.js";
import { SelfDeclaredDisaster } from "./SelfDisaster.js";

@Unique(["companyId", "femaDisasterId", "selfDisasterId"])
@Check(
Expand All @@ -30,6 +30,9 @@ export class Claim {
@PrimaryGeneratedColumn("uuid")
id!: string;

@Column()
name!: string;

@Column({
type: "enum",
enum: ClaimStatusType,
Expand Down
11 changes: 4 additions & 7 deletions backend/src/entities/SelfDisaster.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import type { Relation } from "typeorm";
import {
Entity,
Column,
CreateDateColumn,
Entity,
JoinColumn,
ManyToOne,
CreateDateColumn,
UpdateDateColumn,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from "typeorm";
import type { Relation } from "typeorm";
import { Company } from "./Company";

@Entity("self_declared_disaster")
export class SelfDeclaredDisaster {
@PrimaryGeneratedColumn("uuid")
id!: string;

@Column()
name!: string;

@Column()
companyId!: string;

Expand Down
15 changes: 15 additions & 0 deletions backend/src/migrations/1764537345824-Claims.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from "typeorm";

export class Claims1764537345824 implements MigrationInterface {
name = "Claims1764537345824";

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "self_declared_disaster" DROP COLUMN "name"`);
await queryRunner.query(`ALTER TABLE "claim" ADD "name" character varying NOT NULL`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "claim" DROP COLUMN "name"`);
await queryRunner.query(`ALTER TABLE "self_declared_disaster" ADD "name" character varying NOT NULL`);
}
}
2 changes: 1 addition & 1 deletion backend/src/modules/claim/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export class ClaimController {
async (ctx: Context): ControllerResponse<TypedResponse<ClaimPDFGenerationResponse, 200>> => {
const userId = ctx.get("userId");
const claimId = ctx.req.param("id");
const companyId = ctx.req.param("companyId");
const companyId = ctx.get("companyId");

if (!validate(claimId)) {
return ctx.json({ error: "Invalid claim Id format" }, 400);
Expand Down
4 changes: 3 additions & 1 deletion backend/src/modules/claim/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { ClaimController, IClaimController } from "./controller";
import { DocumentTransaction, IDocumentTransaction } from "../documents/transaction";
import { ClaimService, IClaimService } from "./service";
import { ClaimTransaction, IClaimTransaction } from "./transaction";
import { CompanyTransaction, ICompanyTransaction } from "../company/transaction";

export const claimRoutes = (db: DataSource): Hono => {
const claim = new Hono();

const claimTransaction: IClaimTransaction = new ClaimTransaction(db);
const documentTransaction: IDocumentTransaction = new DocumentTransaction(db);
const claimService: IClaimService = new ClaimService(claimTransaction, documentTransaction, db);
const companyTransaction: ICompanyTransaction = new CompanyTransaction(db);
const claimService: IClaimService = new ClaimService(claimTransaction, documentTransaction, companyTransaction, db);
const claimController: IClaimController = new ClaimController(claimService);

claim.get("/company", (ctx) => claimController.getClaimByCompanyId(ctx));
Expand Down
11 changes: 8 additions & 3 deletions backend/src/modules/claim/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { DataSource } from "typeorm";
import { DocumentTypes } from "../../types/S3Types";
import { IDocumentTransaction } from "../documents/transaction";
import { generatePdfToBuffer } from "./utilities/react-pdf-handler";
import { ICompanyTransaction } from "../company/transaction";

export interface IClaimService {
createClaim(payload: CreateClaimDTO, companyId: string): Promise<CreateClaimResponse>;
Expand All @@ -45,11 +46,13 @@ export interface IClaimService {
export class ClaimService implements IClaimService {
private claimTransaction: IClaimTransaction;
private documentTransaction: IDocumentTransaction;
private companyTransaction: ICompanyTransaction;
private db: DataSource;

constructor(claimTransaction: IClaimTransaction, documentTransaction: IDocumentTransaction, db: DataSource) {
constructor(claimTransaction: IClaimTransaction, documentTransaction: IDocumentTransaction, companyTransaction: ICompanyTransaction, db: DataSource) {
this.claimTransaction = claimTransaction;
this.documentTransaction = documentTransaction;
this.companyTransaction = companyTransaction;
this.db = db;
}

Expand Down Expand Up @@ -154,9 +157,11 @@ export class ClaimService implements IClaimService {

const pdfBuffer = await generatePdfToBuffer(claimData);

const company = await this.companyTransaction.getCompanyById({id: companyId});

const s3 = new S3Service(this.db, this.documentTransaction);
const timestamp = new Date().toISOString();
const documentId = `${claimId}-${timestamp}`;
const timestamp = new Date().toISOString().split('T')[0];
const documentId = `${company?.name}-Claim_Export-${timestamp}.pdf`;
const key = `claims/${companyId}/${claimId}/${documentId}`;
const uploadResponseUrl = await s3.getPresignedUploadUrl(key);
await s3.uploadBufferToS3(uploadResponseUrl, pdfBuffer);
Expand Down
28 changes: 27 additions & 1 deletion backend/src/modules/claim/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,13 @@ export class ClaimTransaction implements IClaimTransaction {
claimLocations: {
locationAddress: true,
},
purchaseLineItems: true,
},
});

return result.map((claim) => ({
id: claim.id,
name: claim.name,
status: claim.status,
createdAt: claim.createdAt.toISOString(),
updatedAt: claim.updatedAt?.toISOString(),
Expand Down Expand Up @@ -230,6 +232,7 @@ export class ClaimTransaction implements IClaimTransaction {
claimLocations: claim.claimLocations
?.map((cl) => cl.locationAddress)
.filter((loc) => loc !== null && loc !== undefined),
purchaseLineItemIds: claim.purchaseLineItems?.map((item) => item.id) ?? [],
}));
} catch (error) {
logMessageToFile(`Transaction error: ${error}`);
Expand All @@ -255,6 +258,19 @@ export class ClaimTransaction implements IClaimTransaction {

async linkClaimToLineItem(payload: LinkClaimToLineItemDTO): Promise<LinkClaimToLineItemResponse | null> {
try {
const existingLink = await this.db.manager
.createQueryBuilder()
.from("claim_purchase_line_items", "bridge")
.where("bridge.claimId = :claimId", { claimId: payload.claimId })
.andWhere("bridge.purchaseLineItemId = :purchaseLineItemId", {
purchaseLineItemId: payload.purchaseLineItemId,
})
.getRawOne();

if (existingLink) {
return payload;
}

await this.db.manager
.createQueryBuilder()
.relation(Claim, "purchaseLineItems")
Expand Down Expand Up @@ -352,6 +368,7 @@ export class ClaimTransaction implements IClaimTransaction {
claimLocations: {
locationAddress: true,
},
purchaseLineItems: true,
},
});
if (claim) {
Expand Down Expand Up @@ -386,7 +403,8 @@ export class ClaimTransaction implements IClaimTransaction {
: undefined,
claimLocations: claim.claimLocations
?.map((cl) => cl.locationAddress)
.filter((loc): loc is NonNullable<typeof loc> => loc !== null && loc !== undefined),
.filter((loc) => loc !== null && loc !== undefined),
purchaseLineItemIds: claim.purchaseLineItems?.map((item) => item.id) ?? [],
};
}
return null;
Expand All @@ -403,6 +421,7 @@ export class ClaimTransaction implements IClaimTransaction {
locationAddress: true,
},
purchaseLineItems: true,
insurancePolicy: true,
},
});

Expand Down Expand Up @@ -454,6 +473,7 @@ export class ClaimTransaction implements IClaimTransaction {
averageIncome: incomeLastThreeYears / 3,
pastRevenues: revenues,
pastPurchases: purchases,
insuranceInfo: claimInfo.insurancePolicy || undefined
};
}

Expand All @@ -468,6 +488,7 @@ export class ClaimTransaction implements IClaimTransaction {
claimLocations: {
locationAddress: true,
},
purchaseLineItems: true,
},
});

Expand All @@ -477,6 +498,7 @@ export class ClaimTransaction implements IClaimTransaction {

return {
id: claim.id,
name: claim.name,
status: claim.status,
createdAt: claim.createdAt.toISOString(),
updatedAt: claim.updatedAt?.toISOString(),
Expand Down Expand Up @@ -507,6 +529,7 @@ export class ClaimTransaction implements IClaimTransaction {
claimLocations: claim.claimLocations
?.map((cl) => cl.locationAddress)
.filter((loc) => loc !== null && loc !== undefined),
purchaseLineItemIds: claim.purchaseLineItems?.map((item) => item.id) ?? [],
};
} catch (error) {
logMessageToFile(`Transaction error: ${error}`);
Expand All @@ -526,6 +549,7 @@ export class ClaimTransaction implements IClaimTransaction {
femaDisaster: true,
selfDisaster: true,
insurancePolicy: true,
purchaseLineItems: true,
},
});

Expand Down Expand Up @@ -562,6 +586,7 @@ export class ClaimTransaction implements IClaimTransaction {

return {
id: result.id,
name: result.name,
status: result.status,
createdAt: result.createdAt.toISOString(),
updatedAt: result.updatedAt?.toISOString(),
Expand Down Expand Up @@ -592,6 +617,7 @@ export class ClaimTransaction implements IClaimTransaction {
claimLocations: result.claimLocations
?.map((cl) => cl.locationAddress)
.filter((loc) => loc !== null && loc !== undefined),
purchaseLineItemIds: result.purchaseLineItems?.map((item) => item.id) ?? [],
};
} catch (error) {
logMessageToFile(`Transaction error: ${error}`);
Expand Down
Loading