reduce balance on cart buy

This commit is contained in:
SimonFJ20 2025-03-18 15:02:22 +01:00
parent fcaad4f876
commit 27b633cc1e
2 changed files with 61 additions and 1 deletions

View File

@ -27,6 +27,10 @@ void route_post_carts_purchase(HttpCtx* ctx)
size_t item_amount = req.items.size; size_t item_amount = req.items.size;
// accumulate product_prices and total
int64_t total_dkk_cent = 0;
ProductPriceVec prices; ProductPriceVec prices;
product_price_vec_construct(&prices); product_price_vec_construct(&prices);
@ -38,9 +42,34 @@ void route_post_carts_purchase(HttpCtx* ctx)
RESPOND_SERVER_ERROR(ctx); RESPOND_SERVER_ERROR(ctx);
goto l0_return; goto l0_return;
} }
total_dkk_cent += price.price_dkk_cent;
product_price_vec_push(&prices, price); product_price_vec_push(&prices, price);
} }
// check and update user balance
User user;
DbRes db_res = db_user_with_id(cx->db, &user, session->user_id);
if (db_res != DbRes_Ok) {
RESPOND_SERVER_ERROR(ctx);
goto l0_return;
}
if (user.balance_dkk_cent < total_dkk_cent) {
RESPOND_JSON(
ctx, 200, "{\"ok\":false,\"message\":\"insufficient funds\"}");
goto l0_return;
}
user.balance_dkk_cent -= total_dkk_cent;
db_res = db_user_update(cx->db, &user);
if (db_res != DbRes_Ok) {
RESPOND_SERVER_ERROR(ctx);
goto l0_return;
}
// assemble receipt
Receipt receipt = { Receipt receipt = {
.id = 0, .id = 0,
.user_id = session->user_id, .user_id = session->user_id,
@ -59,8 +88,10 @@ void route_post_carts_purchase(HttpCtx* ctx)
}); });
} }
// insert receipt
int64_t receipt_id; int64_t receipt_id;
DbRes db_res = db_receipt_insert(cx->db, &receipt, &receipt_id); db_res = db_receipt_insert(cx->db, &receipt, &receipt_id);
if (db_res != DbRes_Ok) { if (db_res != DbRes_Ok) {
RESPOND_SERVER_ERROR(ctx); RESPOND_SERVER_ERROR(ctx);
goto l0_return; goto l0_return;
@ -71,5 +102,6 @@ void route_post_carts_purchase(HttpCtx* ctx)
l0_return: l0_return:
receipt_destroy(&receipt); receipt_destroy(&receipt);
product_price_vec_destroy(&prices); product_price_vec_destroy(&prices);
user_destroy(&user);
carts_purchase_req_destroy(&req); carts_purchase_req_destroy(&req);
} }

View File

@ -49,6 +49,8 @@ Deno.test("test backend", async (t) => {
assertEquals(sessionUserRes.ok, true); assertEquals(sessionUserRes.ok, true);
}); });
const user1 = await sessionUser(token);
await t.step("test /api/users/balance/add", async () => { await t.step("test /api/users/balance/add", async () => {
const sessionUserRes = await post<{ ok: boolean }>( const sessionUserRes = await post<{ ok: boolean }>(
"/api/users/balance/add", "/api/users/balance/add",
@ -60,6 +62,9 @@ Deno.test("test backend", async (t) => {
assertEquals(sessionUserRes.ok, true); assertEquals(sessionUserRes.ok, true);
}); });
const user2 = await sessionUser(token);
assertNotEquals(user1.balance_dkk_cent, user2.balance_dkk_cent);
await testCartsAndReceipts(t, token!); await testCartsAndReceipts(t, token!);
await t.step("test /api/sessions/logout", async () => { await t.step("test /api/sessions/logout", async () => {
@ -76,6 +81,8 @@ Deno.test("test backend", async (t) => {
async function testCartsAndReceipts(t: Deno.TestContext, token: string) { async function testCartsAndReceipts(t: Deno.TestContext, token: string) {
let receiptId: number | undefined = undefined; let receiptId: number | undefined = undefined;
const user1 = await sessionUser(token);
await t.step("test /api/carts/purchase", async () => { await t.step("test /api/carts/purchase", async () => {
const res = await post<{ ok: boolean; receipt_id: number }>( const res = await post<{ ok: boolean; receipt_id: number }>(
"/api/carts/purchase", "/api/carts/purchase",
@ -92,6 +99,9 @@ async function testCartsAndReceipts(t: Deno.TestContext, token: string) {
receiptId = res.receipt_id; receiptId = res.receipt_id;
}); });
const user2 = await sessionUser(token);
assertNotEquals(user1.balance_dkk_cent, user2.balance_dkk_cent);
if (!receiptId) { if (!receiptId) {
return; return;
} }
@ -125,6 +135,24 @@ async function testCartsAndReceipts(t: Deno.TestContext, token: string) {
}); });
} }
type SessionUser = { id: number; email: string; balance_dkk_cent: number };
async function sessionUser(
token: string,
): Promise<SessionUser> {
const res = await get<{
ok: boolean;
user: SessionUser;
}>(
"/api/sessions/user",
{ "Session-Token": token! },
);
if (!res.ok) {
throw new Error();
}
return res.user;
}
function get<Res>( function get<Res>(
path: string, path: string,
headers: Record<string, string>, headers: Record<string, string>,