refactor(wholesale): split monolithic wholesale.ts into focused modules
The wholesale action set was a single 887-line file mixing 8 distinct concerns: shared types, brand-scoping helpers, order CRUD, customer CRUD, product CRUD, settings, deposits, notifications, and webhooks. Split into a wholesale/ directory with one file per concern plus a barrel re-export for backwards compatibility. New structure: - wholesale/types.ts — type definitions (no "use server") - wholesale/scope.ts — resolveBrandId, enforceBrandScope helpers - wholesale/orders.ts — order CRUD + dashboard stats (127 lines) - wholesale/customers.ts — customer CRUD (94) - wholesale/products.ts — product CRUD (100) - wholesale/settings.ts — wholesale_settings + public read (86) - wholesale/deposits.ts — deposits + bulk actions (84) - wholesale/notifications.ts — email/SMS notification queue (88) - wholesale/webhooks.ts — outbound webhook settings + dispatch (90) - wholesale/index.ts — barrel re-export (77 lines) Each module is now under 155 lines and topically cohesive. Existing imports of `@/actions/wholesale` keep working unchanged because of the barrel. New code can import directly from the focused module to keep its dep graph smaller. Notable small cleanups inside the split: - Removed two private helpers that enqueued webhooks by calling the RPC directly; consolidated on the public enqueueWholesaleWebhook export from webhooks.ts so orders.ts and deposits.ts no longer need fire-and-forget duplication. - recordWholesaleDeposit now correctly accepts the brandId parameter (the original signature lacked it despite the docstring implying it). Verified: tsc clean, 175/175 tests pass, dev server still compiles all routes. /wholesale/portal returns 500 due to a pre-existing brand-scope.ts "server-only" issue in the Pages Router chain — not introduced by this commit.
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"use server";
|
||||
|
||||
import { pool } from "@/lib/db";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getActiveBrandId } from "@/lib/brand-scope";
|
||||
import type { NotificationRecipient, WholesaleSettings } from "./types";
|
||||
|
||||
export async function getWholesaleSettings(brandId?: string): Promise<WholesaleSettings | null> {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) return null;
|
||||
const bid = await getActiveBrandId(adminUser, brandId);
|
||||
if (!bid && adminUser.role !== "platform_admin") {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const { rows } = await pool.query<WholesaleSettings>(
|
||||
"SELECT * FROM get_wholesale_settings($1)",
|
||||
[bid]
|
||||
);
|
||||
return rows[0] ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getWholesaleSettingsPublic(brandId: string): Promise<{ invoice_business_address: string | null } | null> {
|
||||
try {
|
||||
const { rows } = await pool.query<{ invoice_business_address: string | null }>(
|
||||
"SELECT invoice_business_address FROM get_wholesale_settings($1)",
|
||||
[brandId]
|
||||
);
|
||||
return rows[0] ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveWholesaleSettings(params: {
|
||||
brandId: string;
|
||||
requireApproval?: boolean;
|
||||
minOrderAmount?: number;
|
||||
onlinePaymentEnabled?: boolean;
|
||||
wholesaleEnabled?: boolean;
|
||||
squareSyncEnabled?: boolean;
|
||||
pickupLocation?: string;
|
||||
fobLocation?: string;
|
||||
fromEmail?: string;
|
||||
invoiceBusinessName?: string;
|
||||
invoiceBusinessAddress?: string;
|
||||
invoiceBusinessPhone?: string;
|
||||
invoiceBusinessEmail?: string;
|
||||
invoiceBusinessWebsite?: string;
|
||||
notificationEmail?: string;
|
||||
notificationRecipients?: NotificationRecipient[];
|
||||
}): Promise<{ success: boolean; error?: string }> {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (!adminUser.can_manage_orders) return { success: false, error: "Not authorized" };
|
||||
|
||||
try {
|
||||
await pool.query(
|
||||
"SELECT upsert_wholesale_settings($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)",
|
||||
[
|
||||
params.brandId,
|
||||
params.requireApproval ?? null,
|
||||
params.minOrderAmount ?? null,
|
||||
params.onlinePaymentEnabled ?? null,
|
||||
params.wholesaleEnabled ?? null,
|
||||
params.pickupLocation ?? null,
|
||||
params.fobLocation ?? null,
|
||||
params.fromEmail ?? null,
|
||||
params.invoiceBusinessName ?? null,
|
||||
params.invoiceBusinessAddress ?? null,
|
||||
params.invoiceBusinessPhone ?? null,
|
||||
params.invoiceBusinessEmail ?? null,
|
||||
params.invoiceBusinessWebsite ?? null,
|
||||
params.notificationEmail ?? null,
|
||||
params.notificationRecipients ? JSON.stringify(params.notificationRecipients) : null,
|
||||
params.squareSyncEnabled ?? null,
|
||||
]
|
||||
);
|
||||
return { success: true };
|
||||
} catch {
|
||||
return { success: false, error: "Failed to save settings" };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user