package apis import ( "net/http" "planner/core" "slices" "strconv" "github.com/gin-gonic/gin" "github.com/shopspring/decimal" ) type ExpenseDef struct { Payer string `json:"payer"` Type string `json:"type"` Amount decimal.Decimal `json:"amount"` } func createExpense(c *gin.Context) { u := extractUser(db, c) if u == nil { c.Status(http.StatusUnauthorized) return } plan_id, err := strconv.ParseInt(c.Param("id"), 10, 32) if err != nil || plan_id < 0 { c.Status(http.StatusBadRequest) return } plan, err := u.GetPlan(db, uint(plan_id)) if err != nil { c.Status(http.StatusBadRequest) return } members, err := plan.GetAllUsers(db) if err != nil { c.Status(http.StatusInternalServerError) return } var exp ExpenseDef if err := c.ShouldBind(&exp); err != nil { c.Status(http.StatusBadRequest) return } var compare func(m core.Member) bool if exp.Type == "user" { compare = func(m core.Member) bool { return m.UserID == exp.Payer } } else if exp.Type == "non-user" { compare = func(m core.Member) bool { return m.Name == exp.Payer } } else { c.String(http.StatusBadRequest, "Invalid member type") return } idx := slices.IndexFunc(members, compare) if idx != -1 { expense, err := core.CreateExpense(db, plan, members[idx], exp.Amount) if err != nil { c.Status(http.StatusInternalServerError) return } c.JSON(http.StatusOK, expense) return } c.String(http.StatusBadRequest, "Unable to found member") } func listExpenses(c *gin.Context) { u := extractUser(db, c) if u == nil { c.Status(http.StatusUnauthorized) return } plan_id, err := strconv.ParseInt(c.Param("id"), 10, 32) if err != nil || plan_id < 0 { c.Status(http.StatusBadRequest) return } plan, err := u.GetPlan(db, uint(plan_id)) if err != nil { c.Status(http.StatusBadRequest) return } expenses, err := core.ListExpenses(db, plan) if err != nil { c.Status(http.StatusInternalServerError) return } c.JSON(http.StatusOK, expenses) } func getExpense(c *gin.Context) { u := extractUser(db, c) if u == nil { c.Status(http.StatusUnauthorized) return } expense_id, err := strconv.ParseInt(c.Param("id"), 10, 32) if err != nil || expense_id < 0 { c.Status(http.StatusBadRequest) return } expense, err := core.GetExpense(db, uint(expense_id)) if err != nil { c.Status(http.StatusBadRequest) return } _, err = u.GetPlan(db, expense.PlanID) if err != nil { c.Status(http.StatusBadRequest) return } c.JSON(http.StatusOK, expense) } func deleteExpense(c *gin.Context) { u := extractUser(db, c) if u == nil { c.Status(http.StatusUnauthorized) return } expense_id, err := strconv.ParseInt(c.Param("id"), 10, 32) if err != nil || expense_id < 0 { c.Status(http.StatusBadRequest) return } expense, err := core.GetExpense(db, uint(expense_id)) if err != nil { c.Status(http.StatusBadRequest) return } _, err = u.GetPlan(db, expense.PlanID) if err != nil { c.Status(http.StatusBadRequest) return } if err = expense.Delete(db); err != nil { c.Status(http.StatusInternalServerError) return } c.Status(http.StatusOK) } func getExpenseDebts(c *gin.Context) { u := extractUser(db, c) if u == nil { c.Status(http.StatusUnauthorized) return } expense_id, err := strconv.ParseInt(c.Param("id"), 10, 32) if err != nil || expense_id < 0 { c.Status(http.StatusBadRequest) return } expense, err := core.GetExpense(db, uint(expense_id)) if err != nil { c.Status(http.StatusBadRequest) return } _, err = u.GetPlan(db, expense.PlanID) if err != nil { c.Status(http.StatusBadRequest) return } debts, err := expense.GetDebt(db) if err != nil { c.Status(http.StatusInternalServerError) return } c.JSON(http.StatusOK, debts) } func setExpenseDebts(c *gin.Context) { u := extractUser(db, c) if u == nil { c.Status(http.StatusUnauthorized) return } expense_id, err := strconv.ParseInt(c.Param("id"), 10, 32) if err != nil || expense_id < 0 { c.Status(http.StatusBadRequest) return } expense, err := core.GetExpense(db, uint(expense_id)) if err != nil { c.Status(http.StatusBadRequest) return } plan, err := u.GetPlan(db, expense.PlanID) if err != nil { c.Status(http.StatusBadRequest) return } expense.Plan = plan var debtSpec []core.DebtSpec if err := c.ShouldBind(&debtSpec); err != nil { c.Status(http.StatusBadRequest) return } //expense.SetDebt(db, debtSpec) c.JSON(http.StatusOK, debtSpec) } func bindExpensesAPIs(r *gin.Engine) { r.POST("/plans/:id/expenses", createExpense) r.GET("/plans/:id/expenses", listExpenses) r.GET("/expenses/:id", getExpense) r.DELETE("/expenses/:id", deleteExpense) r.GET("/expenses/:id/debts", getExpenseDebts) r.POST("/expenses/:id/debts", setExpenseDebts) }