const std = @import("std"); const httpz = @import("../.deps/http.zig/src/httpz.zig"); const models = @import("../db/models.zig"); const ztime = @import("../.deps/time.zig"); const utils = @import("../utils.zig"); const handler = @import("../http_handler.zig"); pub fn fetchTransFromDb(allocator: std.mem.Allocator, budget_id: u32) !?[]models.Transaction { var db = handler.getDb(); const now = ztime.DateTime.now(); const beginningOfMonth = ztime.DateTime.init(now.years, now.months, 0, 0, 0, 0); comptime { if (!std.mem.eql(u8, @typeInfo(models.Transaction).Struct.fields[7].name, "date")) { return error{TransactionModelError}; } } const transactions = try db.selectAllWhere( models.Transaction, allocator, "WHERE budget_id = ? AND date > ? AND hide = ?", .{ .budget_id = budget_id, .date = beginningOfMonth.toUnixMilli(), .hide = 0 }, null, ); return transactions; } pub fn getTransactions(req: *httpz.Request, res: *httpz.Response) !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); const budget_id_str = req.param("budget_id"); if (budget_id_str == null) { handler.returnError("Bad request", 400, res); return; } const budget_id = std.fmt.parseInt(u32, budget_id_str.?, 0) catch { handler.returnError("Bad request", 400, res); return; }; const transactions = try fetchTransFromDb(allocator, budget_id); if (transactions == null) { res.status = 200; res.body = ""; return; } // std.debug.print("Transactions got:\n", .{}); // for (transactions.?) |transaction| { // std.debug.print("\t{any}\n", .{transaction}); // } try handler.returnData(.{ .transactions = transactions.? }, res); } pub fn putTransaction(req: *httpz.Request, res: *httpz.Response) !void { var db = handler.getDb(); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); const body_data = req.json(models.Transaction) catch |err| { std.debug.print("Malformed body: {any}\n", .{err}); handler.returnError("Bad request: Malformed Body", 400, res); return; }; if (body_data == null) { handler.returnError("Bad request: No Data", 400, res); return; } var transaction = body_data.?; // Add Transaction const now = @intCast(u64, std.time.milliTimestamp()); // Update existing Transaction transaction.updated_at = now; try db.updateById(models.Transaction, transaction); const query = models.createSelectOnIdQuery(models.Transaction); const updated_trans = try db.selectOne(models.Transaction, allocator, query, .{ .id = transaction.id }); if (updated_trans) |trans| { try handler.returnData(trans, res); } else { handler.returnError("Internal Server Error", 500, res); } return; } const TransPostReq = struct { id: ?u32, amount: f64, type: []const u8, memo: ?[]const u8, budget_id: u32, added_by_user_id: u32, budget_category_id: ?u32, date: u64, created_at: ?u64, updated_at: ?u64, hide: u8, }; pub fn postTransaction(req: *httpz.Request, res: *httpz.Response) !void { comptime { const putReqLen = @typeInfo(TransPostReq).Struct.fields.len; const transLen = @typeInfo(models.Transaction).Struct.fields.len; if (putReqLen != transLen) { @compileError(std.fmt.comptimePrint("TransactionPutReq does not equal Transaction model struct, fields inconsistent", .{})); } } var db = handler.getDb(); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); const body_data = req.json(TransPostReq) catch |err| { std.debug.print("Malformed body: {any}\n", .{err}); handler.returnError("Bad request: Malformed Body", 400, res); return; }; if (body_data == null) { handler.returnError("Bad request: No Data", 400, res); return; } var body = body_data.?; if (body.id != null) { handler.returnError("Bad request: ID", 400, res); return; } const now = @intCast(u64, std.time.milliTimestamp()); body.created_at = now; body.updated_at = now; try db.insert(models.Transaction, utils.removeStructFields(body, &[_]u8{0})); // Get new Transaction const query = try models.createSelectOnFieldQuery(models.Transaction, null, "created_at", "="); const updated_tran = try db.selectOne(models.Transaction, allocator, query, .{ .created_at = body.created_at }); if (updated_tran) |tran| { try handler.returnData(tran, res); } else { handler.returnError("Internal Server Error", 500, res); } return; }