Skip to content
This repository has been archived by the owner on Oct 31, 2021. It is now read-only.

Commit

Permalink
Adding expense endpoints.
Browse files Browse the repository at this point in the history
  • Loading branch information
elliotcourant committed Mar 13, 2021
1 parent a76ef81 commit 60381ed
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 24 deletions.
107 changes: 85 additions & 22 deletions pkg/controller/expenses.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,18 @@
package controller

import (
"github.com/harderthanitneedstobe/rest-api/v0/pkg/models"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/context"
"net/http"
"strings"
"time"
)

// @tag.name Expenses
func (c *Controller) handleExpenses(p iris.Party) {
p.Get("/{bankAccountId:uint64}/expenses", func(ctx *context.Context) {
bankAccountId := ctx.Params().GetUint64Default("bankAccountId", 0)
if bankAccountId == 0 {
c.returnError(ctx, http.StatusBadRequest, "must specify valid bank account Id")
return
}

repo := c.mustGetAuthenticatedRepository(ctx)
expenses, err := repo.GetExpenses(bankAccountId)
if err != nil {
c.wrapPgError(ctx, err, "could not retrieve expenses")
return
}

ctx.JSON(map[string]interface{}{
"expenses": expenses,
})
})

p.Post("/{bankAccountId:uint64}/expenses", func(ctx *context.Context) {

})
p.Get("/{bankAccountId:uint64}/expenses", c.getExpenses)
p.Post("/{bankAccountId:uint64}/expenses", c.postExpenses)

p.Put("/{bankAccountId:uint64}/expenses/{expenseId:uint64}", func(ctx *context.Context) {

Expand All @@ -38,3 +22,82 @@ func (c *Controller) handleExpenses(p iris.Party) {

})
}

// List Expenses
// @id list-expenses
// @tags Expenses
// @description List all of the expenses for the specified bank account.
// @Security ApiKeyAuth
// @Param bankAccountId path int true "Bank Account ID"
// @Router /bank_accounts/{bankAccountId}/expenses [get]
// @Success 200 {array} models.Expense
// @Failure 400 {object} InvalidBankAccountIdError Invalid Bank Account ID.
// @Failure 500 {object} ApiError Something went wrong on our end.
func (c *Controller) getExpenses(ctx *context.Context) {
bankAccountId := ctx.Params().GetUint64Default("bankAccountId", 0)
if bankAccountId == 0 {
c.returnError(ctx, http.StatusBadRequest, "must specify valid bank account Id")
return
}

repo := c.mustGetAuthenticatedRepository(ctx)

expenses, err := repo.GetExpenses(bankAccountId)
if err != nil {
c.wrapPgError(ctx, err, "could not retrieve expenses")
return
}

ctx.JSON(expenses)
}

// Create Expense
// @id create-expense
// @tags Expense
// @summary Create an expense for the specified bank account.
// @security ApiKeyAuth
// @accept json
// @product json
// @Param bankAccountId path int true "Bank Account ID"
// @Param expense body models.Expense true "New Expense"
// @Router /bank_accounts/{bankAccountId}/expenses [post]
// @Success 200 {object} models.Expense
// @Failure 400 {object} InvalidBankAccountIdError "Invalid Bank Account ID."
// @Failure 400 {object} ApiError "Malformed JSON or invalid RRule."
// @Failure 500 {object} ApiError "Failed to persist data."
func (c *Controller) postExpenses(ctx *context.Context) {
bankAccountId := ctx.Params().GetUint64Default("bankAccountId", 0)
if bankAccountId == 0 {
c.returnError(ctx, http.StatusBadRequest, "must specify valid bank account Id")
return
}

var expense models.Expense
if err := ctx.ReadJSON(&expense); err != nil {
c.wrapAndReturnError(ctx, err, http.StatusBadRequest, "malformed JSON")
return
}

expense.ExpenseId = 0 // Make sure we create a new expense.
expense.BankAccountId = bankAccountId
expense.Name = strings.TrimSpace(expense.Name)
expense.Description = strings.TrimSpace(expense.Description)

if expense.Name == "" {
c.returnError(ctx, http.StatusBadRequest, "expense must have a name")
return
}

expense.LastRecurrence = nil
expense.NextRecurrence = expense.RecurrenceRule.After(time.Now(), false)

// TODO Add next contribution calculation here.

repo := c.mustGetAuthenticatedRepository(ctx)
if err := repo.CreateExpense(&expense); err != nil {
c.wrapPgError(ctx, err, "failed to create expense")
return
}

ctx.JSON(expense)
}
3 changes: 1 addition & 2 deletions pkg/controller/funding_schedules.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ func (c *Controller) handleFundingSchedules(p iris.Party) {
p.Delete("/{bankAccountId:uint64}/funding_schedules/{fundingScheduleId:uint64}", c.deleteFundingSchedules)
}


// List Funding Schedules
// @id list-funding-schedules
// @tags Funding Schedules
Expand Down Expand Up @@ -80,7 +79,7 @@ func (c *Controller) postFundingSchedules(ctx *context.Context) {
fundingSchedule.Description = strings.TrimSpace(fundingSchedule.Description)

if fundingSchedule.Name == "" {
c.returnError(ctx, http.StatusBadRequest, "bank account must have a name")
c.returnError(ctx, http.StatusBadRequest, "funding schedule must have a name")
return
}

Expand Down
1 change: 1 addition & 0 deletions pkg/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Repository interface {
UserId() uint64

CreateBankAccounts(bankAccounts ...models.BankAccount) error
CreateExpense(expense *models.Expense) error
CreateFundingSchedule(fundingSchedule *models.FundingSchedule) error
CreateLink(link *models.Link) error
CreatePlaidLink(link *models.PlaidLink) error
Expand Down

0 comments on commit 60381ed

Please sign in to comment.