init
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import type { Address, AuthUser } from "@orderops/shared";
|
||||
import type { FastifyPluginAsync, FastifyRequest } from "fastify";
|
||||
import { requireEmployeeUser } from "../auth/current-user";
|
||||
import type { DatabaseContext } from "../db/database";
|
||||
import { cancelOrder } from "./cancel-order";
|
||||
import { getOrder } from "./get-order";
|
||||
import { listAuditEvents } from "./list-audit-events";
|
||||
import { listOrders } from "./list-orders";
|
||||
import { changeOrderItemQuantity } from "./update-order-item";
|
||||
import { changeShippingAddress } from "./update-shipping-address";
|
||||
|
||||
interface OrderRouteOptions {
|
||||
db: DatabaseContext;
|
||||
}
|
||||
|
||||
interface SearchQuery {
|
||||
query?: string;
|
||||
}
|
||||
|
||||
interface IdParams {
|
||||
orderId: string;
|
||||
}
|
||||
|
||||
interface OrderItemParams extends IdParams {
|
||||
itemId: string;
|
||||
}
|
||||
|
||||
interface QuantityBody {
|
||||
quantity: number;
|
||||
}
|
||||
|
||||
interface CancelBody {
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
type AuthenticatedRequest = FastifyRequest & { currentUser: AuthUser };
|
||||
|
||||
export const registerOrderRoutes: FastifyPluginAsync<OrderRouteOptions> = async (app, options) => {
|
||||
app.addHook("preHandler", async (request, reply) => {
|
||||
const user = await requireEmployeeUser(options.db, request, reply);
|
||||
|
||||
if (!user) {
|
||||
return reply;
|
||||
}
|
||||
|
||||
(request as AuthenticatedRequest).currentUser = user;
|
||||
});
|
||||
|
||||
app.get<{ Querystring: SearchQuery }>("/orders", {
|
||||
schema: {
|
||||
querystring: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: { type: "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (request) => listOrders(options.db, request.query.query));
|
||||
|
||||
app.get<{ Params: IdParams }>("/orders/:orderId", async (request, reply) => {
|
||||
const order = await getOrder(options.db, request.params.orderId);
|
||||
|
||||
if (!order) {
|
||||
return reply.code(404).send({ message: "Order not found." });
|
||||
}
|
||||
|
||||
return order;
|
||||
});
|
||||
|
||||
app.get<{ Params: IdParams }>("/orders/:orderId/audit-events", async (request) => listAuditEvents(options.db, request.params.orderId));
|
||||
|
||||
app.post<{ Params: OrderItemParams; Body: QuantityBody }>("/orders/:orderId/items/:itemId/quantity", {
|
||||
schema: {
|
||||
body: {
|
||||
type: "object",
|
||||
required: ["quantity"],
|
||||
properties: {
|
||||
quantity: { type: "number" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const currentUser = (request as AuthenticatedRequest).currentUser;
|
||||
const result = await changeOrderItemQuantity(options.db, {
|
||||
orderId: request.params.orderId,
|
||||
itemId: request.params.itemId,
|
||||
quantity: request.body.quantity,
|
||||
actor: currentUser.username
|
||||
});
|
||||
|
||||
if (result.statusCode !== 200) {
|
||||
return reply.code(result.statusCode).send({ message: result.message });
|
||||
}
|
||||
|
||||
return result.order;
|
||||
});
|
||||
|
||||
app.post<{ Params: IdParams; Body: Address }>("/orders/:orderId/shipping-address", {
|
||||
schema: {
|
||||
body: {
|
||||
type: "object",
|
||||
required: ["fullName", "line1", "city", "state", "postalCode", "country"],
|
||||
properties: {
|
||||
fullName: { type: "string", minLength: 1 },
|
||||
line1: { type: "string", minLength: 1 },
|
||||
line2: { type: ["string", "null"] },
|
||||
city: { type: "string", minLength: 1 },
|
||||
state: { type: "string", minLength: 1 },
|
||||
postalCode: { type: "string", minLength: 1 },
|
||||
country: { type: "string", minLength: 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const currentUser = (request as AuthenticatedRequest).currentUser;
|
||||
const result = await changeShippingAddress(options.db, {
|
||||
orderId: request.params.orderId,
|
||||
address: {
|
||||
fullName: request.body.fullName,
|
||||
line1: request.body.line1,
|
||||
line2: request.body.line2 ?? null,
|
||||
city: request.body.city,
|
||||
state: request.body.state,
|
||||
postalCode: request.body.postalCode,
|
||||
country: request.body.country
|
||||
},
|
||||
actor: currentUser.username
|
||||
});
|
||||
|
||||
if (result.statusCode !== 200) {
|
||||
return reply.code(result.statusCode).send({ message: result.message });
|
||||
}
|
||||
|
||||
return result.order;
|
||||
});
|
||||
|
||||
app.post<{ Params: IdParams; Body: CancelBody }>("/orders/:orderId/cancel", {
|
||||
schema: {
|
||||
body: {
|
||||
type: "object",
|
||||
properties: {
|
||||
reason: { type: "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const currentUser = (request as AuthenticatedRequest).currentUser;
|
||||
const result = await cancelOrder(options.db, {
|
||||
orderId: request.params.orderId,
|
||||
reason: request.body.reason,
|
||||
actor: currentUser.username
|
||||
});
|
||||
|
||||
if (result.statusCode !== 200) {
|
||||
return reply.code(result.statusCode).send({ message: result.message });
|
||||
}
|
||||
|
||||
return result.order;
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user