Skip to content

Instantly share code, notes, and snippets.

@christopherbauer
Last active July 2, 2023 18:06
Show Gist options
  • Save christopherbauer/5916e68513e3978ec5697bb8e30eaaee to your computer and use it in GitHub Desktop.
Save christopherbauer/5916e68513e3978ec5697bb8e30eaaee to your computer and use it in GitHub Desktop.
import * as s from "zapatos/schema";
import * as db from "zapatos/db";
import pool from "../pool";
class OrderRepository {
addOrderItem = async (order_id: number, product_id: number, quantity: number) => {
const order_query = this.getOrder(order_id);
const product_query = db.selectExactlyOne("Product", { product_id }).run(pool);
const [order, product] = await Promise.all([order_query, product_query]);
const itemInOrder = order.items.find((item) => item.product_id === product_id);
const result = db.serializable(pool, async (txnClient) => {
if (itemInOrder) {
await this.updateOrderItem(itemInOrder.order_item_id, quantity, product), txnClient;
} else {
await this.insertOrderItem(order_id, quantity, product, txnClient);
}
return await this.refreshTotal(order_id, txnClient);
});
return result
.then((v) => this.getOrder(order_id))
.catch((ex) => {
console.error(ex);
return undefined;
});
};
createOrder = async (user_id: number) => {
return await db
.insert("Order", {
user_id: user_id,
status: "open",
order_date: new Date(),
total_amount: 0,
})
.run(pool);
};
list = async () =>
await db
.select(
"Order",
{},
{
lateral: {
items: db.select("OrderItem", {
order_id: db.parent("order_id"),
}),
},
}
)
.run(pool);
private updateOrderItem = (
order_item_id: number,
quantity: number,
product: s.Product.JSONSelectable,
txnClient?: db.TxnClientForSerializable
) => {
if (quantity > 0) {
return db.update("OrderItem", this.makeOrderItem(product, quantity), { order_item_id }).run(txnClient || pool);
} else {
return db.deletes("OrderItem", { order_item_id }).run(txnClient || pool);
}
};
private insertOrderItem = (
order_id: number,
quantity: number,
product: s.Product.JSONSelectable,
txnClient?: db.TxnClientForSerializable
) => db.insert("OrderItem", { order_id, ...this.makeOrderItem(product, quantity) }).run(txnClient || pool);
private refreshTotal = async (order_id: number, txnClient?: db.TxnClientForSerializable) => {
const total_amount = (await this.getOrder(order_id)).items.reduce(
(total, item) => total + item.quantity * item.price_per_unit,
0
);
return db.update("Order", { total_amount }, { order_id }).run(txnClient || pool);
};
private makeOrderItem = (product: s.Product.JSONSelectable, quantity: number) => ({
product_id: product.product_id,
quantity: quantity,
price_per_unit: quantity > 1 ? 0.95 * product.price : product.price,
});
getOrder = async (order_id: number) =>
await db
.selectExactlyOne(
"Order",
{ order_id },
{
lateral: {
items: db.select("OrderItem", {
order_id: db.parent("order_id"),
}),
},
}
)
.run(pool);
}
const orderRepository = new OrderRepository();
export default orderRepository;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment