Last active
July 2, 2023 18:06
-
-
Save christopherbauer/5916e68513e3978ec5697bb8e30eaaee to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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