feat(companies): add invoiceEmail field separate from contact email
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e308d86e93
commit
4cb927cbd0
7 changed files with 25 additions and 9 deletions
|
|
@ -15,6 +15,7 @@ const companySchema = z.object({
|
||||||
telephone: z.string().optional(),
|
telephone: z.string().optional(),
|
||||||
mobile: z.string().optional(),
|
mobile: z.string().optional(),
|
||||||
email: z.string().email("Invalid email").optional().or(z.literal("")),
|
email: z.string().email("Invalid email").optional().or(z.literal("")),
|
||||||
|
invoiceEmail: z.string().email("Invalid invoice email").optional().or(z.literal("")),
|
||||||
invoiceAddress: z.string().optional(),
|
invoiceAddress: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -31,13 +32,14 @@ export async function createCompany(formData: FormData): Promise<ActionResult> {
|
||||||
telephone: (formData.get("telephone") as string) || undefined,
|
telephone: (formData.get("telephone") as string) || undefined,
|
||||||
mobile: (formData.get("mobile") as string) || undefined,
|
mobile: (formData.get("mobile") as string) || undefined,
|
||||||
email: (formData.get("email") as string) || undefined,
|
email: (formData.get("email") as string) || undefined,
|
||||||
|
invoiceEmail: (formData.get("invoiceEmail") as string) || undefined,
|
||||||
invoiceAddress: (formData.get("invoiceAddress") as string) || undefined,
|
invoiceAddress: (formData.get("invoiceAddress") as string) || undefined,
|
||||||
});
|
});
|
||||||
if (!parsed.success) return { error: parsed.error.errors[0]?.message ?? "Validation failed" };
|
if (!parsed.success) return { error: parsed.error.errors[0]?.message ?? "Validation failed" };
|
||||||
|
|
||||||
const { name, gstNumber, address, telephone, mobile, email, invoiceAddress } = parsed.data;
|
const { name, gstNumber, address, telephone, mobile, email, invoiceEmail, invoiceAddress } = parsed.data;
|
||||||
await db.company.create({
|
await db.company.create({
|
||||||
data: { name, gstNumber: gstNumber ?? null, address: address ?? null, telephone: telephone ?? null, mobile: mobile ?? null, email: email || null, invoiceAddress: invoiceAddress ?? null },
|
data: { name, gstNumber: gstNumber ?? null, address: address ?? null, telephone: telephone ?? null, mobile: mobile ?? null, email: email || null, invoiceEmail: invoiceEmail || null, invoiceAddress: invoiceAddress ?? null },
|
||||||
});
|
});
|
||||||
revalidatePath("/admin/companies");
|
revalidatePath("/admin/companies");
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
|
|
@ -59,14 +61,15 @@ export async function updateCompany(formData: FormData): Promise<ActionResult> {
|
||||||
telephone: (formData.get("telephone") as string) || undefined,
|
telephone: (formData.get("telephone") as string) || undefined,
|
||||||
mobile: (formData.get("mobile") as string) || undefined,
|
mobile: (formData.get("mobile") as string) || undefined,
|
||||||
email: (formData.get("email") as string) || undefined,
|
email: (formData.get("email") as string) || undefined,
|
||||||
|
invoiceEmail: (formData.get("invoiceEmail") as string) || undefined,
|
||||||
invoiceAddress: (formData.get("invoiceAddress") as string) || undefined,
|
invoiceAddress: (formData.get("invoiceAddress") as string) || undefined,
|
||||||
});
|
});
|
||||||
if (!parsed.success) return { error: parsed.error.errors[0]?.message ?? "Validation failed" };
|
if (!parsed.success) return { error: parsed.error.errors[0]?.message ?? "Validation failed" };
|
||||||
|
|
||||||
const { name, gstNumber, address, telephone, mobile, email, invoiceAddress } = parsed.data;
|
const { name, gstNumber, address, telephone, mobile, email, invoiceEmail, invoiceAddress } = parsed.data;
|
||||||
await db.company.update({
|
await db.company.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { name, gstNumber: gstNumber ?? null, address: address ?? null, telephone: telephone ?? null, mobile: mobile ?? null, email: email || null, invoiceAddress: invoiceAddress ?? null },
|
data: { name, gstNumber: gstNumber ?? null, address: address ?? null, telephone: telephone ?? null, mobile: mobile ?? null, email: email || null, invoiceEmail: invoiceEmail || null, invoiceAddress: invoiceAddress ?? null },
|
||||||
});
|
});
|
||||||
revalidatePath("/admin/companies");
|
revalidatePath("/admin/companies");
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export type CompanyRow = {
|
||||||
telephone: string | null;
|
telephone: string | null;
|
||||||
mobile: string | null;
|
mobile: string | null;
|
||||||
email: string | null;
|
email: string | null;
|
||||||
|
invoiceEmail: string | null;
|
||||||
invoiceAddress: string | null;
|
invoiceAddress: string | null;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
};
|
};
|
||||||
|
|
@ -91,7 +92,8 @@ export function CompaniesTable({ companies }: { companies: CompanyRow[] }) {
|
||||||
{c.telephone && <p>☎ {c.telephone}</p>}
|
{c.telephone && <p>☎ {c.telephone}</p>}
|
||||||
{c.mobile && <p>📱 {c.mobile}</p>}
|
{c.mobile && <p>📱 {c.mobile}</p>}
|
||||||
{c.email && <p>✉ {c.email}</p>}
|
{c.email && <p>✉ {c.email}</p>}
|
||||||
{!c.telephone && !c.mobile && !c.email && <span className="italic text-neutral-400">—</span>}
|
{c.invoiceEmail && <p className="text-neutral-400">📄 {c.invoiceEmail}</p>}
|
||||||
|
{!c.telephone && !c.mobile && !c.email && !c.invoiceEmail && <span className="italic text-neutral-400">—</span>}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-3">
|
<td className="px-4 py-3">
|
||||||
<span className={`rounded-full px-2.5 py-0.5 text-xs font-medium ${c.isActive ? "bg-success-100 text-success-700" : "bg-neutral-100 text-neutral-500"}`}>
|
<span className={`rounded-full px-2.5 py-0.5 text-xs font-medium ${c.isActive ? "bg-success-100 text-success-700" : "bg-neutral-100 text-neutral-500"}`}>
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ type CompanyRow = {
|
||||||
telephone: string | null;
|
telephone: string | null;
|
||||||
mobile: string | null;
|
mobile: string | null;
|
||||||
email: string | null;
|
email: string | null;
|
||||||
|
invoiceEmail: string | null;
|
||||||
invoiceAddress: string | null;
|
invoiceAddress: string | null;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
};
|
};
|
||||||
|
|
@ -33,8 +34,12 @@ function CompanyFormFields({ company }: { company?: CompanyRow }) {
|
||||||
<input name="gstNumber" defaultValue={company?.gstNumber ?? ""} className={INPUT} placeholder="e.g. 27AAHCP5787B1Z6" />
|
<input name="gstNumber" defaultValue={company?.gstNumber ?? ""} className={INPUT} placeholder="e.g. 27AAHCP5787B1Z6" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className={LABEL}>Email</label>
|
<label className={LABEL}>Contact Email</label>
|
||||||
<input name="email" type="email" defaultValue={company?.email ?? ""} className={INPUT} placeholder="accounts@company.com" />
|
<input name="email" type="email" defaultValue={company?.email ?? ""} className={INPUT} placeholder="contact@company.com" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className={LABEL}>Invoice Email <span className="font-normal text-neutral-400">(shown on POs)</span></label>
|
||||||
|
<input name="invoiceEmail" type="email" defaultValue={company?.invoiceEmail ?? ""} className={INPUT} placeholder="accounts@company.com" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className={LABEL}>Telephone</label>
|
<label className={LABEL}>Telephone</label>
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ export default async function AdminCompaniesPage() {
|
||||||
telephone: c.telephone,
|
telephone: c.telephone,
|
||||||
mobile: c.mobile,
|
mobile: c.mobile,
|
||||||
email: c.email,
|
email: c.email,
|
||||||
|
invoiceEmail: c.invoiceEmail,
|
||||||
invoiceAddress: c.invoiceAddress,
|
invoiceAddress: c.invoiceAddress,
|
||||||
isActive: c.isActive,
|
isActive: c.isActive,
|
||||||
}))}
|
}))}
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,10 @@ export async function GET(request: NextRequest, { params }: Props) {
|
||||||
const CO_TEL = telParts.length > 0 ? telParts.join(" / ") : DEFAULT_CO_TEL;
|
const CO_TEL = telParts.length > 0 ? telParts.join(" / ") : DEFAULT_CO_TEL;
|
||||||
|
|
||||||
const INV_ADDR = co?.invoiceAddress ?? (co?.address ? `${co.name}, ${co.address}` : DEFAULT_INV_ADDR);
|
const INV_ADDR = co?.invoiceAddress ?? (co?.address ? `${co.name}, ${co.address}` : DEFAULT_INV_ADDR);
|
||||||
|
// invoiceEmail takes priority over general email for the Invoice Details line
|
||||||
|
const invoiceContactEmail = co?.invoiceEmail ?? co?.email ?? null;
|
||||||
const INV_GST = [
|
const INV_GST = [
|
||||||
co?.email ? `Email: ${co.email}` : null,
|
invoiceContactEmail ? `Email: ${invoiceContactEmail}` : null,
|
||||||
co?.gstNumber ? `GST NO: ${co.gstNumber}` : null,
|
co?.gstNumber ? `GST NO: ${co.gstNumber}` : null,
|
||||||
].filter(Boolean).join(" ") || DEFAULT_INV_GST;
|
].filter(Boolean).join(" ") || DEFAULT_INV_GST;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- Add invoiceEmail field to Company (separate from main contact email)
|
||||||
|
ALTER TABLE "Company" ADD COLUMN "invoiceEmail" TEXT;
|
||||||
|
|
@ -122,6 +122,7 @@ model Company {
|
||||||
telephone String?
|
telephone String?
|
||||||
mobile String?
|
mobile String?
|
||||||
email String?
|
email String?
|
||||||
|
invoiceEmail String?
|
||||||
invoiceAddress String?
|
invoiceAddress String?
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue