mirror of
https://github.com/Sea-Haven-Industries/seahaven-ap.git
synced 2026-10-04 18:21:58 +00:00
Merge branch 'feature/mock-column-fields' into feature/invoice-filter-toolbar
This commit is contained in:
commit
5838c6b1ab
2 changed files with 89 additions and 12 deletions
|
|
@ -67,6 +67,7 @@ describe("mocks module", () => {
|
||||||
expect(invoice.lastUpdateActorName.length).toBeGreaterThan(0);
|
expect(invoice.lastUpdateActorName.length).toBeGreaterThan(0);
|
||||||
expect(invoice.lastUpdateAt.length).toBeGreaterThan(0);
|
expect(invoice.lastUpdateAt.length).toBeGreaterThan(0);
|
||||||
expect(invoice.invoiceDate).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
expect(invoice.invoiceDate).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
||||||
|
expect(invoice.invoiceDate).not.toBe(invoice.dueDate);
|
||||||
expect(invoice.processingBegan).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
expect(invoice.processingBegan).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
||||||
expect(typeof invoice.tagging).toBe("string");
|
expect(typeof invoice.tagging).toBe("string");
|
||||||
expect(typeof invoice.fs).toBe("string");
|
expect(typeof invoice.fs).toBe("string");
|
||||||
|
|
@ -101,6 +102,8 @@ describe("mocks module", () => {
|
||||||
|
|
||||||
const updated = updateMockInvoicePayDate("inv-1", "2026-08-18");
|
const updated = updateMockInvoicePayDate("inv-1", "2026-08-18");
|
||||||
expect(updated.payDate).toBe("2026-08-18");
|
expect(updated.payDate).toBe("2026-08-18");
|
||||||
|
expect(updated.lastUpdateMessage).toBe("Pay date updated");
|
||||||
|
expect(updated.lastUpdateAt).not.toBe(before?.lastUpdateAt);
|
||||||
|
|
||||||
const after = getMockInvoices().find((invoice) => invoice.id === "inv-1");
|
const after = getMockInvoices().find((invoice) => invoice.id === "inv-1");
|
||||||
expect(after?.payDate).toBe("2026-08-18");
|
expect(after?.payDate).toBe("2026-08-18");
|
||||||
|
|
@ -148,6 +151,7 @@ describe("mocks module", () => {
|
||||||
authorUserId: "user-1",
|
authorUserId: "user-1",
|
||||||
authorName: "Alex Rivera",
|
authorName: "Alex Rivera",
|
||||||
body: "Need another look",
|
body: "Need another look",
|
||||||
|
createdAt: "2026-08-11T09:00:00.000Z",
|
||||||
});
|
});
|
||||||
expect(withComment.comments.some((comment) => comment.body === "Need another look")).toBe(true);
|
expect(withComment.comments.some((comment) => comment.body === "Need another look")).toBe(true);
|
||||||
|
|
||||||
|
|
@ -168,6 +172,23 @@ describe("mocks module", () => {
|
||||||
expect(getMockApprovals().find((item) => item.invoiceId === "inv-2")?.status).toBe("approved");
|
expect(getMockApprovals().find((item) => item.invoiceId === "inv-2")?.status).toBe("approved");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("refreshes last update from a comment and payment account from the method", () => {
|
||||||
|
const commented = addMockInvoiceComment("inv-1", {
|
||||||
|
authorUserId: "user-1",
|
||||||
|
authorName: "Alex Rivera",
|
||||||
|
body: "Checked the total",
|
||||||
|
createdAt: "2026-09-01T15:00:00.000Z",
|
||||||
|
});
|
||||||
|
expect(commented.lastUpdateAt).toBe("2026-09-01T15:00:00.000Z");
|
||||||
|
expect(commented.lastUpdate).toBe("2026-09-01");
|
||||||
|
expect(commented.lastUpdateMessage).toBe("Checked the total");
|
||||||
|
expect(commented.lastUpdateActorName).toBe("Alex Rivera");
|
||||||
|
|
||||||
|
const method = updateMockInvoiceHeader("inv-1", { paymentMethod: "ach" });
|
||||||
|
expect(method.paymentAccount).toBe("Operating ACH");
|
||||||
|
expect(getMockInvoice("inv-1")?.paymentAccount).toBe("Operating ACH");
|
||||||
|
});
|
||||||
|
|
||||||
it("refreshes description and rowCount when header or lines change", () => {
|
it("refreshes description and rowCount when header or lines change", () => {
|
||||||
const before = getMockInvoice("inv-1");
|
const before = getMockInvoice("inv-1");
|
||||||
expect(before?.rowCount).toBe(2);
|
expect(before?.rowCount).toBe(2);
|
||||||
|
|
|
||||||
|
|
@ -116,17 +116,46 @@ function actionLabelForStatus(status: MockInvoiceStatus, index: number): string
|
||||||
return NON_PENDING_ACTION_OPTIONS[index % NON_PENDING_ACTION_OPTIONS.length];
|
return NON_PENDING_ACTION_OPTIONS[index % NON_PENDING_ACTION_OPTIONS.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
function derivedActivityFields(invoice: Pick<MockInvoice, "activity" | "dueDate">) {
|
function derivedActivityFields(invoice: Pick<MockInvoice, "activity" | "comments" | "dueDate">) {
|
||||||
const latestActivity = invoice.activity[invoice.activity.length - 1];
|
const events = [
|
||||||
const lastUpdateAt = latestActivity?.createdAt ?? `${invoice.dueDate}T12:00:00.000Z`;
|
...invoice.activity.map((entry) => ({
|
||||||
|
at: entry.createdAt,
|
||||||
|
message: entry.message,
|
||||||
|
actor: entry.actorName,
|
||||||
|
})),
|
||||||
|
...invoice.comments.map((comment) => ({
|
||||||
|
at: comment.createdAt,
|
||||||
|
message: comment.body,
|
||||||
|
actor: comment.authorName,
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
const latest = events.reduce<(typeof events)[number] | undefined>((current, event) => {
|
||||||
|
if (!current || event.at > current.at) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}, undefined);
|
||||||
|
const lastUpdateAt = latest?.at ?? `${invoice.dueDate}T12:00:00.000Z`;
|
||||||
return {
|
return {
|
||||||
lastUpdate: lastUpdateAt.slice(0, 10),
|
lastUpdate: lastUpdateAt.slice(0, 10),
|
||||||
lastUpdateMessage: latestActivity?.message ?? "Invoice updated",
|
lastUpdateMessage: latest?.message ?? "Invoice updated",
|
||||||
lastUpdateActorName: latestActivity?.actorName ?? "System",
|
lastUpdateActorName: latest?.actor ?? "System",
|
||||||
lastUpdateAt,
|
lastUpdateAt,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function paymentAccountFor(paymentMethod: MockInvoice["paymentMethod"]): string {
|
||||||
|
return paymentMethod === "ach" ? "Operating ACH" : "Operating Check";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Invoice date is independent of the due date. Offset varies per seed. */
|
||||||
|
function invoiceDateBeforeDue(dueDate: string, index: number): string {
|
||||||
|
const [year, month, day] = dueDate.split("-").map(Number);
|
||||||
|
const date = new Date(Date.UTC(year, month - 1, day));
|
||||||
|
date.setUTCDate(date.getUTCDate() - (14 + index));
|
||||||
|
return date.toISOString().slice(0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
/** Keep catalog-derived fields in sync after mock mutations. */
|
/** Keep catalog-derived fields in sync after mock mutations. */
|
||||||
function withRefreshedCatalogFields(invoice: MockInvoice, index: number): MockInvoice {
|
function withRefreshedCatalogFields(invoice: MockInvoice, index: number): MockInvoice {
|
||||||
return {
|
return {
|
||||||
|
|
@ -134,6 +163,7 @@ function withRefreshedCatalogFields(invoice: MockInvoice, index: number): MockIn
|
||||||
actionLabel: actionLabelForStatus(invoice.status, index),
|
actionLabel: actionLabelForStatus(invoice.status, index),
|
||||||
...derivedActivityFields(invoice),
|
...derivedActivityFields(invoice),
|
||||||
description: invoice.memo,
|
description: invoice.memo,
|
||||||
|
paymentAccount: paymentAccountFor(invoice.paymentMethod),
|
||||||
rowCount: invoice.lines.length,
|
rowCount: invoice.lines.length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -150,14 +180,14 @@ function enrichInvoice(core: MockInvoiceCore, index: number): MockInvoice {
|
||||||
lastUpdateMessage: "",
|
lastUpdateMessage: "",
|
||||||
lastUpdateActorName: "",
|
lastUpdateActorName: "",
|
||||||
lastUpdateAt: "",
|
lastUpdateAt: "",
|
||||||
invoiceDate: core.dueDate,
|
invoiceDate: invoiceDateBeforeDue(core.dueDate, index),
|
||||||
processingBegan: core.activity[0]?.createdAt?.slice(0, 10) ?? core.dueDate,
|
processingBegan: core.activity[0]?.createdAt?.slice(0, 10) ?? core.dueDate,
|
||||||
tagging: index % 2 === 0 ? "Ops" : "",
|
tagging: index % 2 === 0 ? "Ops" : "",
|
||||||
fs: index % 2 === 0 ? "synced" : "",
|
fs: index % 2 === 0 ? "synced" : "",
|
||||||
description: core.memo,
|
description: core.memo,
|
||||||
invoiceType: "Standard",
|
invoiceType: "Standard",
|
||||||
location: "Ronkonkoma",
|
location: "Ronkonkoma",
|
||||||
paymentAccount: core.paymentMethod === "ach" ? "Operating ACH" : "Operating Check",
|
paymentAccount: paymentAccountFor(core.paymentMethod),
|
||||||
relatedInvoice: null,
|
relatedInvoice: null,
|
||||||
rowCount: core.lines.length,
|
rowCount: core.lines.length,
|
||||||
},
|
},
|
||||||
|
|
@ -549,7 +579,27 @@ export function updateMockInvoicePayDate(id: string, payDate: string | null): Mo
|
||||||
throw new Error(`Mock invoice not found: ${id}`);
|
throw new Error(`Mock invoice not found: ${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return replaceInvoice(index, { ...invoiceStore[index], payDate });
|
const current = invoiceStore[index];
|
||||||
|
return replaceInvoice(
|
||||||
|
index,
|
||||||
|
withRefreshedCatalogFields(
|
||||||
|
{
|
||||||
|
...current,
|
||||||
|
payDate,
|
||||||
|
activity: [
|
||||||
|
...current.activity,
|
||||||
|
{
|
||||||
|
id: `activity-pay-date-${Date.now()}`,
|
||||||
|
actorUserId: "user-1",
|
||||||
|
actorName: "System",
|
||||||
|
message: "Pay date updated",
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
index,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateMockInvoiceHeader(id: string, patch: MockInvoiceHeaderPatch): MockInvoice {
|
export function updateMockInvoiceHeader(id: string, patch: MockInvoiceHeaderPatch): MockInvoice {
|
||||||
|
|
@ -603,10 +653,16 @@ export function addMockInvoiceComment(
|
||||||
createdAt: comment.createdAt ?? new Date().toISOString(),
|
createdAt: comment.createdAt ?? new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return replaceInvoice(index, {
|
return replaceInvoice(
|
||||||
...current,
|
index,
|
||||||
comments: [...current.comments, nextComment],
|
withRefreshedCatalogFields(
|
||||||
});
|
{
|
||||||
|
...current,
|
||||||
|
comments: [...current.comments, nextComment],
|
||||||
|
},
|
||||||
|
index,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transitionMockInvoiceStatus(
|
export function transitionMockInvoiceStatus(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue