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 getBudget(req: *httpz.Request, res: *httpz.Response) !void { const db = handler.getDb(); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); const id_str = req.param("id"); if (id_str == null) { res.status = 400; res.body = "Bad Request: No Id"; return; } const id = std.fmt.parseInt(u32, id_str.?, 0) catch { res.status = 401; res.body = "Bad Request: Bad Id"; return; }; const budget = try db.selectOneById(models.Budget, allocator, id); if (budget == null) { res.status = 404; res.body = "Budget not found"; return; } try res.json(budget.?, .{}); } const BudgetPostReq = struct { id: ?u32, name: []const u8, created_at: ?u64, updated_at: ?u64, hide: u8, }; pub fn putBudget(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.Budget) 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.?; // Add Budget const now = @intCast(u64, std.time.milliTimestamp()); // Update existing Budget body.updated_at = now; try db.updateById(models.Budget, body); const query = models.createSelectOnIdQuery(models.Transaction); const updated_budget = try db.selectOne(models.Budget, allocator, query, .{ .id = body.id }); if (updated_budget) |budget| { try handler.returnData(budget, res); } else { handler.returnError("Internal Server Error", 500, res); } return; } pub fn postBudget(req: *httpz.Request, res: *httpz.Response) !void { comptime { const putReqLen = @typeInfo(BudgetPostReq).Struct.fields.len; const budgetLen = @typeInfo(models.Budget).Struct.fields.len; if (putReqLen != budgetLen) { @compileError(std.fmt.comptimePrint("BudgetPutReq does not equal Budget model struct, fields inconsistent", .{})); } } var db = handler.getDb(); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); const body_data = req.json(BudgetPostReq) 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); } // Add Budget const now = @intCast(u64, std.time.milliTimestamp()); // Create Budget body.created_at = now; body.updated_at = now; try db.insert(models.Budget, utils.removeStructFields(body, &[_]u8{0})); // Get Budget const query = try models.createSelectOnFieldQuery(models.Budget, null, "created_at", "="); const updated_budget = try db.selectOne(models.Budget, allocator, query, .{ .created_at = body.created_at }); if (updated_budget) |budget| { try handler.returnData(budget, res); } else { handler.returnError("Internal Server Error", 500, res); } return; } const BudgetCatPostReq = struct { id: ?u32, budget_id: u32, amount: f64, name: []const u8, color: []const u8, created_at: ?u64, updated_at: ?u64, hide: u8, }; pub fn postBudgetCategory(req: *httpz.Request, res: *httpz.Response) !void { comptime { const putReqLen = @typeInfo(BudgetCatPostReq).Struct.fields.len; const budgetLen = @typeInfo(models.BudgetCategory).Struct.fields.len; if (putReqLen != budgetLen) { @compileError(std.fmt.comptimePrint("BudgetCatPutReq does not equal Budget model struct, fields inconsistent", .{})); } } var db = handler.getDb(); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); const body_data = req.json(BudgetCatPostReq) 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; } // Add Budget const now = @intCast(u64, std.time.milliTimestamp()); // Create Budget body.created_at = now; body.updated_at = now; try db.insert(models.BudgetCategory, utils.removeStructFields(body, &[_]u8{0})); // Get Budget const query = try models.createSelectOnFieldQuery(models.BudgetCategory, null, "created_at", "="); const updated_budget = try db.selectOne(models.BudgetCategory, allocator, query, .{ .created_at = body.created_at }); if (updated_budget) |budget| { try handler.returnData(budget, res); } else { std.debug.print("Could not find inserted budget", .{}); handler.returnError("Internal Server Error", 500, res); } return; } pub fn putBudgetCategory(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.BudgetCategory) 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 budget_category = body_data.?; const now = @intCast(u64, std.time.milliTimestamp()); // Update existing Budget budget_category.updated_at = now; try db.updateById(models.BudgetCategory, budget_category); const query = models.createSelectOnIdQuery(models.BudgetCategory); const updated_budget = try db.selectOne(models.BudgetCategory, allocator, query, .{ .id = budget_category.id }); if (updated_budget) |budget| { try handler.returnData(budget, res); } else { std.debug.print("Could not find inserted budget", .{}); handler.returnError("Internal Server Error", 500, res); } return; }