fix: the company rejection on the approved ones

This commit is contained in:
Nathnael
2026-07-09 11:27:33 +00:00
parent 3f7734fe16
commit a5bc9d8435
2 changed files with 97 additions and 4 deletions

View File

@@ -0,0 +1,88 @@
import { Repository } from "typeorm";
import { CompanyChangeRequestRepository } from "./company-change-request.repository";
import {
ChangeRequestStatus,
CompanyChangeRequest,
} from "./entities/company-change-request.entity";
type Row = Pick<CompanyChangeRequest, "id" | "status"> & { createdAt: Date };
const COMPANY_ID = "company-1";
/**
* Stands in for the TypeORM repository over a fixed set of rows, honouring the
* `where.status` filter and the `createdAt DESC` ordering findOne relies on.
*/
function mockRepositoryOver(rows: Row[]) {
return {
findOne: jest.fn(
({ where }: { where: Partial<Row> & { companyId: string } }) =>
Promise.resolve(
rows
.filter(
(row) =>
where.companyId === COMPANY_ID &&
(where.status === undefined || row.status === where.status),
)
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())[0] ??
null,
),
),
} as unknown as Repository<CompanyChangeRequest>;
}
function subject(rows: Row[]) {
return new CompanyChangeRequestRepository(mockRepositoryOver(rows));
}
describe("CompanyChangeRequestRepository.findLatestOpenByCompanyId", () => {
const rejected: Row = {
id: "rejected",
status: ChangeRequestStatus.Rejected,
createdAt: new Date("2026-01-01T00:00:00.000Z"),
};
it("returns the pending request when one is open", async () => {
const pending: Row = {
id: "pending",
status: ChangeRequestStatus.Pending,
createdAt: new Date("2026-01-02T00:00:00.000Z"),
};
const result = await subject([rejected, pending]).findLatestOpenByCompanyId(
COMPANY_ID,
);
expect(result?.id).toBe("pending");
});
it("returns the latest rejected request when nothing is pending", async () => {
const result = await subject([rejected]).findLatestOpenByCompanyId(
COMPANY_ID,
);
expect(result?.id).toBe("rejected");
});
it("returns null once a resubmit of a rejected request is approved", async () => {
const approved: Row = {
id: "approved",
status: ChangeRequestStatus.Approved,
createdAt: new Date("2026-01-02T00:00:00.000Z"),
};
const result = await subject([
rejected,
approved,
]).findLatestOpenByCompanyId(COMPANY_ID);
expect(result).toBeNull();
});
it("returns null when the company has no requests", async () => {
const result = await subject([]).findLatestOpenByCompanyId(COMPANY_ID);
expect(result).toBeNull();
});
});

View File

@@ -28,18 +28,23 @@ export class CompanyChangeRequestRepository extends BaseRepository<CompanyChange
/**
* The company's latest "open" request — pending (locks the customer) or the
* most recent rejected one (drives the reapply banner + prefill). Approved
* requests are terminal and ignored here.
* most recent rejected one (drives the reapply banner + prefill).
*
* Only the company's newest request may be open. A rejection is superseded the
* moment the customer resubmits: that resubmit opens a *new* request, so once
* it is approved the newest request is terminal and nothing is open — even
* though the older rejected row still sits in the table as history.
*/
async findLatestOpenByCompanyId(
companyId: string,
): Promise<CompanyChangeRequest | null> {
const pending = await this.findPendingByCompanyId(companyId);
if (pending) return pending;
return this.repository.findOne({
where: { companyId, status: ChangeRequestStatus.Rejected },
const latest = await this.repository.findOne({
where: { companyId },
order: { createdAt: "DESC" },
});
return latest?.status === ChangeRequestStatus.Rejected ? latest : null;
}
async findById(id: string): Promise<CompanyChangeRequest | null> {