Lambda-based serverless backend with Google SSO, purchase orders, invoices, and X12 810 EDI generation for Amazon Payee Central. Includes bill-to/ship-to address support from Coupa purchase-orders table. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
60 lines
2.7 KiB
JavaScript
60 lines
2.7 KiB
JavaScript
// lambdas/settings/index.js
|
|
// User settings CRUD — stores config (dynamo, edi, company) and invCounter per user
|
|
|
|
const { GetCommand, PutCommand } = require("@aws-sdk/lib-dynamodb");
|
|
const { getDocClient, TABLES, ok, notFound, badRequest, serverError, parseBody, handler } = require("@ledgerflow/shared");
|
|
|
|
const TABLE = () => TABLES.SETTINGS;
|
|
|
|
// Default config shape (mirrors frontend defaults)
|
|
const DEFAULT_CONFIG = {
|
|
dynamo: { region: "us-east-1", table: "", key: "", secret: "", fields: { poNumber: "po_number", vendor: "vendor_name", amount: "total_amount", status: "status", issueDate: "issue_date", dueDate: "due_date" }, connected: false },
|
|
edi: { region: "us-east-1", partnershipId: "", key: "", secret: "", senderId: "", receiverId: "", transformerId: "", connected: false },
|
|
company: { name: "", taxId: "", terms: "Net 30", currency: "USD", invPrefix: "INV-", taxRate: 0 },
|
|
};
|
|
|
|
async function getSettings(event, user) {
|
|
const doc = getDocClient();
|
|
const result = await doc.send(new GetCommand({ TableName: TABLE(), Key: { userId: user.userId } }));
|
|
if (!result.Item) {
|
|
return ok({ config: DEFAULT_CONFIG, invCounter: 1 });
|
|
}
|
|
return ok({ config: result.Item.config, invCounter: result.Item.invCounter });
|
|
}
|
|
|
|
async function putSettings(event, user) {
|
|
const body = parseBody(event);
|
|
if (!body.config && body.invCounter === undefined) {
|
|
return badRequest("Request body must include config and/or invCounter");
|
|
}
|
|
|
|
const doc = getDocClient();
|
|
|
|
// Merge with existing settings so partial updates work
|
|
const existing = await doc.send(new GetCommand({ TableName: TABLE(), Key: { userId: user.userId } }));
|
|
const current = existing.Item || { config: DEFAULT_CONFIG, invCounter: 1 };
|
|
|
|
const item = {
|
|
userId: user.userId,
|
|
config: body.config !== undefined ? body.config : current.config,
|
|
invCounter: body.invCounter !== undefined ? body.invCounter : current.invCounter,
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
|
|
await doc.send(new PutCommand({ TableName: TABLE(), Item: item }));
|
|
return ok({ config: item.config, invCounter: item.invCounter });
|
|
}
|
|
|
|
// ── Router ────────────────────────────────────────────────────────────────────
|
|
|
|
exports.handler = handler(async (event, context, user) => {
|
|
if (!user) return { statusCode: 401, body: "Unauthorized" };
|
|
|
|
const method = event.requestContext?.http?.method || event.httpMethod;
|
|
|
|
switch (method) {
|
|
case "GET": return getSettings(event, user);
|
|
case "PUT": return putSettings(event, user);
|
|
default: return badRequest(`Method ${method} not allowed on /settings`);
|
|
}
|
|
});
|