mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-28 08:44:06 +02:00
receipts one combined
This commit is contained in:
parent
a54d94d45e
commit
4f84dc4842
@ -72,37 +72,49 @@ void route_get_receipts_one(HttpCtx* ctx)
|
|||||||
free(receipt_id_str);
|
free(receipt_id_str);
|
||||||
|
|
||||||
Receipt receipt;
|
Receipt receipt;
|
||||||
DbRes db_rizz = db_receipt_with_id(cx->db, &receipt, receipt_id);
|
DbRes db_res = db_receipt_with_id(cx->db, &receipt, receipt_id);
|
||||||
if (db_rizz != DbRes_Ok) {
|
if (db_res != DbRes_Ok) {
|
||||||
RESPOND_BAD_REQUEST(ctx, "receipt not found");
|
RESPOND_BAD_REQUEST(ctx, "receipt not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProductPriceVec product_prices = { 0 };
|
ProductPriceVec product_prices = { 0 };
|
||||||
product_price_vec_construct(&product_prices);
|
product_price_vec_construct(&product_prices);
|
||||||
db_receipt_prices(cx->db, &product_prices, receipt_id);
|
db_res = db_receipt_prices(cx->db, &product_prices, receipt_id);
|
||||||
|
if (db_res != DbRes_Ok) {
|
||||||
String res;
|
RESPOND_SERVER_ERROR(ctx);
|
||||||
string_construct(&res);
|
return;
|
||||||
|
|
||||||
char* receipt_str = receipt_to_json_string(&receipt);
|
|
||||||
|
|
||||||
string_pushf(
|
|
||||||
&res, "{\"ok\":true,\"receipt\":%s,\"product_prices\":[", receipt_str);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < product_prices.size; ++i) {
|
|
||||||
if (i != 0) {
|
|
||||||
string_pushf(&res, ",");
|
|
||||||
}
|
|
||||||
char* product_price_str
|
|
||||||
= product_price_to_json_string(&product_prices.data[i]);
|
|
||||||
string_pushf(&res, "%s", product_price_str);
|
|
||||||
free(product_price_str);
|
|
||||||
}
|
}
|
||||||
string_pushf(&res, "]}");
|
|
||||||
|
|
||||||
RESPOND_JSON(ctx, 200, "%s", res.data);
|
ProductVec products = { 0 };
|
||||||
string_destroy(&res);
|
product_vec_construct(&products);
|
||||||
|
db_res = db_receipt_products(cx->db, &products, receipt_id);
|
||||||
|
if (db_res != DbRes_Ok) {
|
||||||
|
RESPOND_SERVER_ERROR(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReceiptsOneRes res = {
|
||||||
|
.receipt_id = receipt.id,
|
||||||
|
.timestamp = receipt.timestamp,
|
||||||
|
.products = (ReceiptsOneResProductVec) { 0 },
|
||||||
|
};
|
||||||
|
receipts_one_res_product_vec_construct(&res.products);
|
||||||
|
for (size_t i = 0; i < receipt.products.size; ++i) {
|
||||||
|
receipts_one_res_product_vec_push(&res.products,
|
||||||
|
(ReceiptsOneResProduct) {
|
||||||
|
.product_id = products.data[i].id,
|
||||||
|
.name = products.data[i].name,
|
||||||
|
.price_dkk_cent = product_prices.data[i].price_dkk_cent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
char* res_json = receipts_one_res_to_json_string(&res);
|
||||||
|
|
||||||
|
RESPOND_JSON(ctx, 200, "{\"ok\":true,\"receipt\":%s}", res_json);
|
||||||
|
free(res_json);
|
||||||
|
receipts_one_res_destroy(&res);
|
||||||
|
product_vec_destroy(&products);
|
||||||
product_price_vec_destroy(&product_prices);
|
product_price_vec_destroy(&product_prices);
|
||||||
receipt_destroy(&receipt);
|
receipt_destroy(&receipt);
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,9 @@ DbRes db_user_with_email_exists(Db* db, bool* exists, const char* email);
|
|||||||
/// `user` is an out parameter.
|
/// `user` is an out parameter.
|
||||||
DbRes db_user_with_email(Db* db, User* user, const char* email);
|
DbRes db_user_with_email(Db* db, User* user, const char* email);
|
||||||
|
|
||||||
|
/// `product` is an out parameter.
|
||||||
|
DbRes db_product_with_id(Db* db, Product* product, int64_t id);
|
||||||
|
|
||||||
/// Expects `vec` to be constructed.
|
/// Expects `vec` to be constructed.
|
||||||
DbRes db_product_all(Db* db, ProductVec* vec);
|
DbRes db_product_all(Db* db, ProductVec* vec);
|
||||||
|
|
||||||
@ -49,3 +52,7 @@ DbRes db_receipt_with_id(Db* db, Receipt* receipt, int64_t id);
|
|||||||
/// Expects `product_prices` to be constructed.
|
/// Expects `product_prices` to be constructed.
|
||||||
DbRes db_receipt_prices(
|
DbRes db_receipt_prices(
|
||||||
Db* db, ProductPriceVec* product_prices, int64_t receipt_id);
|
Db* db, ProductPriceVec* product_prices, int64_t receipt_id);
|
||||||
|
|
||||||
|
/// `products` field is an out parameter.
|
||||||
|
/// Expects `products` to be constructed.
|
||||||
|
DbRes db_receipt_products(Db* db, ProductVec* products, int64_t receipt_id);
|
||||||
|
@ -225,7 +225,7 @@ DbRes db_user_with_email_exists(Db* db, bool* exists, const char* email)
|
|||||||
*exists = true;
|
*exists = true;
|
||||||
}
|
}
|
||||||
if (sqlite_res != SQLITE_DONE) {
|
if (sqlite_res != SQLITE_DONE) {
|
||||||
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
REPORT_SQLITE3_ERROR();
|
||||||
res = DbRes_Error;
|
res = DbRes_Error;
|
||||||
goto l0_return;
|
goto l0_return;
|
||||||
}
|
}
|
||||||
@ -285,6 +285,55 @@ l0_return:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `product` is an out parameter.
|
||||||
|
DbRes db_product_with_id(Db* db, Product* product, int64_t id)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(Product) == 48, "model has changed");
|
||||||
|
|
||||||
|
sqlite3* connection;
|
||||||
|
CONNECT;
|
||||||
|
DbRes res;
|
||||||
|
|
||||||
|
sqlite3_stmt* stmt;
|
||||||
|
int prepare_res = sqlite3_prepare_v2(connection,
|
||||||
|
"SELECT id, name, price_dkk_cent, description, coord, barcode FROM "
|
||||||
|
"products WHERE id = ?",
|
||||||
|
-1,
|
||||||
|
&stmt,
|
||||||
|
NULL);
|
||||||
|
if (prepare_res != SQLITE_OK) {
|
||||||
|
REPORT_SQLITE3_ERROR();
|
||||||
|
res = DbRes_Error;
|
||||||
|
goto l0_return;
|
||||||
|
}
|
||||||
|
sqlite3_bind_int64(stmt, 1, id);
|
||||||
|
|
||||||
|
int step_res = sqlite3_step(stmt);
|
||||||
|
if (step_res == SQLITE_DONE) {
|
||||||
|
res = DbRes_NotFound;
|
||||||
|
goto l0_return;
|
||||||
|
} else if (step_res != SQLITE_ROW) {
|
||||||
|
REPORT_SQLITE3_ERROR();
|
||||||
|
res = DbRes_Error;
|
||||||
|
goto l0_return;
|
||||||
|
}
|
||||||
|
*product = (Product){
|
||||||
|
.id = GET_INT(0),
|
||||||
|
.name = GET_STR(1),
|
||||||
|
.price_dkk_cent = GET_INT(2),
|
||||||
|
.description = GET_STR(3),
|
||||||
|
.coord_id = GET_INT(4),
|
||||||
|
.barcode = GET_STR(5),
|
||||||
|
},
|
||||||
|
|
||||||
|
res = DbRes_Ok;
|
||||||
|
l0_return:
|
||||||
|
if (stmt)
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
DISCONNECT;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
DbRes db_product_all(Db* db, ProductVec* vec)
|
DbRes db_product_all(Db* db, ProductVec* vec)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(Product) == 48, "model has changed");
|
static_assert(sizeof(Product) == 48, "model has changed");
|
||||||
@ -668,3 +717,63 @@ l0_return:
|
|||||||
DISCONNECT;
|
DISCONNECT;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DbRes db_receipt_products(Db* db, ProductVec* products, int64_t receipt_id)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(Product) == 48, "model has changed");
|
||||||
|
|
||||||
|
sqlite3* connection;
|
||||||
|
CONNECT;
|
||||||
|
DbRes res;
|
||||||
|
sqlite3_stmt* stmt = NULL;
|
||||||
|
|
||||||
|
int prepare_res = sqlite3_prepare_v2(connection,
|
||||||
|
"SELECT"
|
||||||
|
" products.id,"
|
||||||
|
" products.name,"
|
||||||
|
" products.price_dkk_cent,"
|
||||||
|
" products.description,"
|
||||||
|
" products.coord,"
|
||||||
|
" products.barcode"
|
||||||
|
" FROM receipt_products"
|
||||||
|
" JOIN product_prices"
|
||||||
|
" ON receipt_products.product_price = product_prices.id"
|
||||||
|
" JOIN products"
|
||||||
|
" ON product_prices.product = products.id"
|
||||||
|
" WHERE receipt_products.receipt = ?",
|
||||||
|
-1,
|
||||||
|
&stmt,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (prepare_res != SQLITE_OK) {
|
||||||
|
REPORT_SQLITE3_ERROR();
|
||||||
|
res = DbRes_Error;
|
||||||
|
goto l0_return;
|
||||||
|
}
|
||||||
|
sqlite3_bind_int64(stmt, 1, receipt_id);
|
||||||
|
|
||||||
|
int sqlite_res;
|
||||||
|
while ((sqlite_res = sqlite3_step(stmt)) == SQLITE_ROW) {
|
||||||
|
Product product = {
|
||||||
|
.id = GET_INT(0),
|
||||||
|
.name = GET_STR(1),
|
||||||
|
.price_dkk_cent = GET_INT(2),
|
||||||
|
.description = GET_STR(3),
|
||||||
|
.coord_id = GET_INT(4),
|
||||||
|
.barcode = GET_STR(5),
|
||||||
|
};
|
||||||
|
product_vec_push(products, product);
|
||||||
|
}
|
||||||
|
if (sqlite_res != SQLITE_DONE) {
|
||||||
|
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
||||||
|
res = DbRes_Error;
|
||||||
|
goto l0_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = DbRes_Ok;
|
||||||
|
l0_return:
|
||||||
|
if (stmt)
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
DISCONNECT;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
@ -77,6 +77,21 @@ void carts_purchase_req_destroy(CartsPurchaseReq* model)
|
|||||||
carts_item_vec_destroy(&model->items);
|
carts_item_vec_destroy(&model->items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void receipts_one_res_product_destroy(ReceiptsOneResProduct* m)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(ReceiptsOneResProduct) == 32, "model has changed");
|
||||||
|
|
||||||
|
free(m->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void receipts_one_res_destroy(ReceiptsOneRes* m)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(ReceiptsOneRes) == 40, "model has changed");
|
||||||
|
|
||||||
|
free(m->timestamp);
|
||||||
|
receipts_one_res_product_vec_destroy(&m->products);
|
||||||
|
}
|
||||||
|
|
||||||
char* user_to_json_string(const User* m)
|
char* user_to_json_string(const User* m)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(User) == 40, "model has changed");
|
static_assert(sizeof(User) == 40, "model has changed");
|
||||||
@ -208,7 +223,7 @@ char* receipt_to_json_string(const Receipt* m)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* users_register_req_to_json(const UsersRegisterReq* m)
|
char* users_register_req_to_json_string(const UsersRegisterReq* m)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(UsersRegisterReq) == 24, "model has changed");
|
static_assert(sizeof(UsersRegisterReq) == 24, "model has changed");
|
||||||
|
|
||||||
@ -229,7 +244,7 @@ char* users_register_req_to_json(const UsersRegisterReq* m)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* sessions_login_req_to_json(const SessionsLoginReq* m)
|
char* sessions_login_req_to_json_string(const SessionsLoginReq* m)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(SessionsLoginReq) == 16, "model has changed");
|
static_assert(sizeof(SessionsLoginReq) == 16, "model has changed");
|
||||||
|
|
||||||
@ -248,13 +263,66 @@ char* sessions_login_req_to_json(const SessionsLoginReq* m)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* carts_purchase_req_to_json(const CartsPurchaseReq* m)
|
char* carts_purchase_req_to_json_string(const CartsPurchaseReq* m)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(CartsPurchaseReq) == 24, "model has changed");
|
static_assert(sizeof(CartsPurchaseReq) == 24, "model has changed");
|
||||||
|
|
||||||
PANIC("not implemented");
|
PANIC("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* receipts_one_res_product_to_json_string(const ReceiptsOneResProduct* m)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(ReceiptsOneResProduct) == 32, "model has changed");
|
||||||
|
|
||||||
|
String string;
|
||||||
|
string_construct(&string);
|
||||||
|
string_pushf(&string,
|
||||||
|
"{"
|
||||||
|
"\"product_id\":\"%ld\","
|
||||||
|
"\"name\":\"%s\","
|
||||||
|
"\"price_dkk_cent\":\"%ld\","
|
||||||
|
"\"price_dkk_cent\":\"%ld\""
|
||||||
|
"}",
|
||||||
|
m->product_id,
|
||||||
|
m->name,
|
||||||
|
m->price_dkk_cent,
|
||||||
|
m->amount);
|
||||||
|
|
||||||
|
char* result = string_copy(&string);
|
||||||
|
string_destroy(&string);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* receipts_one_res_to_json_string(const ReceiptsOneRes* m)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(ReceiptsOneRes) == 40, "model has changed");
|
||||||
|
|
||||||
|
String string;
|
||||||
|
string_construct(&string);
|
||||||
|
string_pushf(&string,
|
||||||
|
"{"
|
||||||
|
"\"receipt_id\":\"%ld\","
|
||||||
|
"\"timestamp\":\"%s\","
|
||||||
|
"\"products:\":[",
|
||||||
|
m->receipt_id,
|
||||||
|
m->timestamp);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m->products.size; ++i) {
|
||||||
|
if (i != 0) {
|
||||||
|
string_pushf(&string, ",");
|
||||||
|
}
|
||||||
|
char* product
|
||||||
|
= receipts_one_res_product_to_json_string(&m->products.data[i]);
|
||||||
|
string_push_str(&string, product);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_pushf(&string, "]}");
|
||||||
|
|
||||||
|
char* result = string_copy(&string);
|
||||||
|
string_destroy(&string);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* key;
|
const char* key;
|
||||||
JsonType type;
|
JsonType type;
|
||||||
@ -454,6 +522,24 @@ int carts_purchase_req_from_json(CartsPurchaseReq* m, const JsonValue* json)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int receipts_one_res_product_from_json(
|
||||||
|
ReceiptsOneResProduct* m, const JsonValue* json)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(ReceiptsOneResProduct) == 32, "model has changed");
|
||||||
|
|
||||||
|
PANIC("not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
int receipts_one_res_from_json(ReceiptsOneRes* m, const JsonValue* json)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(ReceiptsOneRes) == 40, "model has changed");
|
||||||
|
|
||||||
|
PANIC("not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_VEC_IMPL(ProductPrice, ProductPriceVec, product_price_vec, )
|
DEFINE_VEC_IMPL(ProductPrice, ProductPriceVec, product_price_vec, )
|
||||||
DEFINE_VEC_IMPL(ReceiptProduct, ReceiptProductVec, receipt_product_vec, )
|
DEFINE_VEC_IMPL(ReceiptProduct, ReceiptProductVec, receipt_product_vec, )
|
||||||
DEFINE_VEC_IMPL(CartsItem, CartsItemVec, carts_item_vec, )
|
DEFINE_VEC_IMPL(CartsItem, CartsItemVec, carts_item_vec, )
|
||||||
|
DEFINE_VEC_IMPL(ReceiptsOneResProduct,
|
||||||
|
ReceiptsOneResProductVec,
|
||||||
|
receipts_one_res_product_vec, )
|
||||||
|
@ -86,3 +86,24 @@ typedef struct {
|
|||||||
} CartsPurchaseReq;
|
} CartsPurchaseReq;
|
||||||
|
|
||||||
void carts_purchase_req_destroy(CartsPurchaseReq* model);
|
void carts_purchase_req_destroy(CartsPurchaseReq* model);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int64_t product_id;
|
||||||
|
char* name;
|
||||||
|
int64_t price_dkk_cent;
|
||||||
|
int64_t amount;
|
||||||
|
} ReceiptsOneResProduct;
|
||||||
|
|
||||||
|
void receipts_one_res_product_destroy(ReceiptsOneResProduct* model);
|
||||||
|
|
||||||
|
DECLARE_VEC_TYPE(ReceiptsOneResProduct,
|
||||||
|
ReceiptsOneResProductVec,
|
||||||
|
receipts_one_res_product_vec, )
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int64_t receipt_id;
|
||||||
|
char* timestamp;
|
||||||
|
ReceiptsOneResProductVec products;
|
||||||
|
} ReceiptsOneRes;
|
||||||
|
|
||||||
|
void receipts_one_res_destroy(ReceiptsOneRes* model);
|
||||||
|
@ -14,3 +14,5 @@ DEFINE_MODEL_JSON(Receipt, receipt)
|
|||||||
DEFINE_MODEL_JSON(UsersRegisterReq, users_register_req)
|
DEFINE_MODEL_JSON(UsersRegisterReq, users_register_req)
|
||||||
DEFINE_MODEL_JSON(SessionsLoginReq, sessions_login_req)
|
DEFINE_MODEL_JSON(SessionsLoginReq, sessions_login_req)
|
||||||
DEFINE_MODEL_JSON(CartsPurchaseReq, carts_purchase_req)
|
DEFINE_MODEL_JSON(CartsPurchaseReq, carts_purchase_req)
|
||||||
|
DEFINE_MODEL_JSON(ReceiptsOneResProduct, receipts_one_res_product)
|
||||||
|
DEFINE_MODEL_JSON(ReceiptsOneRes, receipts_one_res)
|
||||||
|
@ -45,8 +45,8 @@ Deno.test("test backend", async (t) => {
|
|||||||
{ "Session-Token": token! },
|
{ "Session-Token": token! },
|
||||||
);
|
);
|
||||||
|
|
||||||
assertEquals(sessionUserRes.ok, true);
|
|
||||||
// console.log(sessionUserRes.user);
|
// console.log(sessionUserRes.user);
|
||||||
|
assertEquals(sessionUserRes.ok, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
await t.step("test /api/users/balance/add", async () => {
|
await t.step("test /api/users/balance/add", async () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user