2025-04-09 18:37:02 +02:00
|
|
|
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 {
|
2025-04-16 23:24:23 +02:00
|
|
|
return *m.UserId == exp.Payer
|
2025-04-09 18:37:02 +02:00
|
|
|
}
|
|
|
|
|
} 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 {
|
2025-04-16 23:24:23 +02:00
|
|
|
expense, err := core.ExpenseCreate(db, *plan, members[idx], exp.Amount)
|
2025-04-09 18:37:02 +02:00
|
|
|
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
|
|
|
|
|
}
|
2025-04-16 23:24:23 +02:00
|
|
|
expenses, err := core.ExpensesList(db, *plan)
|
2025-04-09 18:37:02 +02:00
|
|
|
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
|
|
|
|
|
}
|
2025-04-16 23:24:23 +02:00
|
|
|
expense, err := core.ExpensesGet(db, uint(expense_id))
|
2025-04-09 18:37:02 +02:00
|
|
|
if err != nil {
|
|
|
|
|
c.Status(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-04-16 23:24:23 +02:00
|
|
|
_, err = u.GetPlan(db, expense.PlanId)
|
2025-04-09 18:37:02 +02:00
|
|
|
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
|
|
|
|
|
}
|
2025-04-16 23:24:23 +02:00
|
|
|
expense, err := core.ExpensesGet(db, uint(expense_id))
|
2025-04-09 18:37:02 +02:00
|
|
|
if err != nil {
|
|
|
|
|
c.Status(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-04-16 23:24:23 +02:00
|
|
|
_, err = u.GetPlan(db, expense.PlanId)
|
2025-04-09 18:37:02 +02:00
|
|
|
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
|
|
|
|
|
}
|
2025-04-16 23:24:23 +02:00
|
|
|
expense, err := core.ExpensesGet(db, uint(expense_id))
|
2025-04-09 18:37:02 +02:00
|
|
|
if err != nil {
|
|
|
|
|
c.Status(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-04-16 23:24:23 +02:00
|
|
|
_, err = u.GetPlan(db, expense.PlanId)
|
2025-04-09 18:37:02 +02:00
|
|
|
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
|
|
|
|
|
}
|
2025-04-16 23:24:23 +02:00
|
|
|
expense, err := core.ExpensesGet(db, uint(expense_id))
|
2025-04-09 18:37:02 +02:00
|
|
|
if err != nil {
|
|
|
|
|
c.Status(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-04-16 23:24:23 +02:00
|
|
|
_, err = u.GetPlan(db, expense.PlanId)
|
2025-04-09 18:37:02 +02:00
|
|
|
if err != nil {
|
|
|
|
|
c.Status(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
}
|