feat(web): add public commission request entrypoint
This commit is contained in:
@@ -2,9 +2,12 @@ import { beforeEach, describe, expect, it, vi } from "vitest"
|
||||
|
||||
const { mockDb } = vi.hoisted(() => ({
|
||||
mockDb: {
|
||||
$transaction: vi.fn(),
|
||||
customer: {
|
||||
create: vi.fn(),
|
||||
findFirst: vi.fn(),
|
||||
findMany: vi.fn(),
|
||||
update: vi.fn(),
|
||||
},
|
||||
commission: {
|
||||
create: vi.fn(),
|
||||
@@ -18,17 +21,29 @@ vi.mock("./client", () => ({
|
||||
db: mockDb,
|
||||
}))
|
||||
|
||||
import { createCommission, createCustomer, updateCommissionStatus } from "./commissions"
|
||||
import {
|
||||
createCommission,
|
||||
createCustomer,
|
||||
createPublicCommissionRequest,
|
||||
updateCommissionStatus,
|
||||
} from "./commissions"
|
||||
|
||||
describe("commissions service", () => {
|
||||
beforeEach(() => {
|
||||
for (const value of Object.values(mockDb)) {
|
||||
if (typeof value === "function") {
|
||||
value.mockReset()
|
||||
continue
|
||||
}
|
||||
|
||||
for (const fn of Object.values(value)) {
|
||||
if (typeof fn === "function") {
|
||||
fn.mockReset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mockDb.$transaction.mockImplementation(async (callback) => callback(mockDb))
|
||||
})
|
||||
|
||||
it("creates customer and commission payloads", async () => {
|
||||
@@ -51,6 +66,37 @@ describe("commissions service", () => {
|
||||
expect(mockDb.commission.create).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it("creates a public commission request with customer upsert behavior", async () => {
|
||||
mockDb.customer.findFirst.mockResolvedValue({
|
||||
id: "customer-existing",
|
||||
phone: null,
|
||||
instagram: null,
|
||||
})
|
||||
mockDb.customer.update.mockResolvedValue({
|
||||
id: "customer-existing",
|
||||
})
|
||||
mockDb.commission.create.mockResolvedValue({
|
||||
id: "commission-2",
|
||||
})
|
||||
|
||||
await createPublicCommissionRequest({
|
||||
customerName: "Grace Hopper",
|
||||
customerEmail: "GRACE@EXAMPLE.COM",
|
||||
customerPhone: "12345",
|
||||
title: "Landscape commission",
|
||||
description: "Oil painting request",
|
||||
budgetMin: 500,
|
||||
budgetMax: 900,
|
||||
})
|
||||
|
||||
expect(mockDb.customer.findFirst).toHaveBeenCalledWith({
|
||||
where: { email: "grace@example.com" },
|
||||
orderBy: { updatedAt: "desc" },
|
||||
})
|
||||
expect(mockDb.customer.update).toHaveBeenCalledTimes(1)
|
||||
expect(mockDb.commission.create).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it("updates commission status", async () => {
|
||||
mockDb.commission.update.mockResolvedValue({ id: "commission-1", status: "done" })
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
commissionStatusSchema,
|
||||
createCommissionInputSchema,
|
||||
createCustomerInputSchema,
|
||||
createPublicCommissionRequestInputSchema,
|
||||
updateCommissionStatusInputSchema,
|
||||
} from "@cms/content"
|
||||
|
||||
@@ -56,6 +57,63 @@ export async function createCommission(input: unknown) {
|
||||
})
|
||||
}
|
||||
|
||||
export async function createPublicCommissionRequest(input: unknown) {
|
||||
const payload = createPublicCommissionRequestInputSchema.parse(input)
|
||||
const normalizedEmail = payload.customerEmail.trim().toLowerCase()
|
||||
|
||||
return db.$transaction(async (tx) => {
|
||||
const existingCustomer = await tx.customer.findFirst({
|
||||
where: {
|
||||
email: normalizedEmail,
|
||||
},
|
||||
orderBy: {
|
||||
updatedAt: "desc",
|
||||
},
|
||||
})
|
||||
|
||||
const customer = existingCustomer
|
||||
? await tx.customer.update({
|
||||
where: { id: existingCustomer.id },
|
||||
data: {
|
||||
name: payload.customerName,
|
||||
phone: payload.customerPhone ?? existingCustomer.phone,
|
||||
instagram: payload.customerInstagram ?? existingCustomer.instagram,
|
||||
isRecurring: true,
|
||||
},
|
||||
})
|
||||
: await tx.customer.create({
|
||||
data: {
|
||||
name: payload.customerName,
|
||||
email: normalizedEmail,
|
||||
phone: payload.customerPhone,
|
||||
instagram: payload.customerInstagram,
|
||||
isRecurring: false,
|
||||
},
|
||||
})
|
||||
|
||||
return tx.commission.create({
|
||||
data: {
|
||||
title: payload.title,
|
||||
description: payload.description,
|
||||
status: "new",
|
||||
customerId: customer.id,
|
||||
budgetMin: payload.budgetMin,
|
||||
budgetMax: payload.budgetMax,
|
||||
},
|
||||
include: {
|
||||
customer: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
isRecurring: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateCommissionStatus(input: unknown) {
|
||||
const payload = updateCommissionStatusInputSchema.parse(input)
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ export {
|
||||
commissionKanbanOrder,
|
||||
createCommission,
|
||||
createCustomer,
|
||||
createPublicCommissionRequest,
|
||||
listCommissions,
|
||||
listCustomers,
|
||||
updateCommissionStatus,
|
||||
|
||||
Reference in New Issue
Block a user