Skip to content

Commit

Permalink
Merge pull request #214 from Receipt-Wrangler/tech/update-receipt-upd…
Browse files Browse the repository at this point in the history
…ate-to-use-command

Tech/update receipt update to use command
  • Loading branch information
Noah231515 committed Apr 11, 2024
2 parents cdba7d3 + c013521 commit 04ecc37
Show file tree
Hide file tree
Showing 20 changed files with 740 additions and 397 deletions.
21 changes: 20 additions & 1 deletion internal/commands/bulk_status_update_command.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
package commands

import "receipt-wrangler/api/internal/models"
import (
"encoding/json"
"net/http"
"receipt-wrangler/api/internal/models"
"receipt-wrangler/api/internal/utils"
)

type BulkStatusUpdateCommand struct {
Comment string
Status models.ReceiptStatus
ReceiptIds []uint
}

func (command *BulkStatusUpdateCommand) LoadDataFromRequest(w http.ResponseWriter, r *http.Request) error {
bytes, err := utils.GetBodyData(w, r)
if err != nil {
return err
}

err = json.Unmarshal(bytes, &command)
if err != nil {
return err
}

return nil
}
13 changes: 13 additions & 0 deletions internal/commands/paged_request_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ type ReceiptPagedRequestCommand struct {
Filter ReceiptPagedRequestFilter `json:"filter"`
}

func (command *ReceiptPagedRequestCommand) LoadDataFromRequest(w http.ResponseWriter, r *http.Request) error {
bytes, err := utils.GetBodyData(w, r)
if err != nil {
return err
}

err = json.Unmarshal(bytes, &command)
if err != nil {
return err
}
return nil
}

type ReceiptPagedRequestFilter struct {
Date PagedRequestField `json:"date"`
Amount PagedRequestField `json:"amount"`
Expand Down
40 changes: 40 additions & 0 deletions internal/commands/upsert_category_command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package commands

import (
"encoding/json"
"net/http"
"receipt-wrangler/api/internal/structs"
"receipt-wrangler/api/internal/utils"
)

type UpsertCategoryCommand struct {
Id *uint `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
}

func (category *UpsertCategoryCommand) LoadDataFromRequest(w http.ResponseWriter, r *http.Request) error {
bytes, err := utils.GetBodyData(w, r)
if err != nil {
return err
}

err = json.Unmarshal(bytes, &category)
if err != nil {
return err
}

return nil
}

func (category *UpsertCategoryCommand) Validate() structs.ValidatorError {
errors := make(map[string]string)
vErr := structs.ValidatorError{}

if len(category.Name) == 0 {
errors["name"] = "Name is required"
}

vErr.Errors = errors
return vErr
}
37 changes: 37 additions & 0 deletions internal/commands/upsert_comment_command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package commands

import (
"receipt-wrangler/api/internal/structs"
)

type UpsertCommentCommand struct {
Comment string `json:"comment"`
ReceiptId uint `json:"receiptId"`
UserId uint `json:"userId"`
}

func (comment *UpsertCommentCommand) Validate(userRequestId uint, isCreate bool) structs.ValidatorError {
errors := make(map[string]string)
vErr := structs.ValidatorError{}

if len(comment.Comment) == 0 {
errors["comment"] = "Comment is required"
}

if !isCreate {
if comment.ReceiptId == 0 {
errors["receiptId"] = "Receipt Id is required"
}
}

if comment.UserId == 0 {
errors["userId"] = "User Id is required"
}

if comment.UserId != userRequestId {
errors["userId"] = "Bad user id"
}

vErr.Errors = errors
return vErr
}
54 changes: 54 additions & 0 deletions internal/commands/upsert_item_command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package commands

import (
"github.com/shopspring/decimal"
"receipt-wrangler/api/internal/models"
"receipt-wrangler/api/internal/structs"
)

type UpsertItemCommand struct {
Amount decimal.Decimal `json:"amount"`
ChargedToUserId uint `json:"chargedToUserId"`
IsTaxed bool `json:"isTaxed"`
Name string `json:"name"`
ReceiptId uint `json:"receiptId"`
Status models.ItemStatus `json:"status"`
}

func (item *UpsertItemCommand) Validate(receiptAmount decimal.Decimal, isCreate bool) structs.ValidatorError {
errors := make(map[string]string)
vErr := structs.ValidatorError{}

if item.Amount.IsZero() {
errors["amount"] = "Amount is required"
}

if item.Amount.GreaterThan(receiptAmount) {
errors["amount"] = "Amount cannot be greater than receipt amount"
}

if item.Amount.LessThanOrEqual(decimal.Zero) {
errors["amount"] = "Amount must be greater than zero"
}

if len(item.Name) == 0 {
errors["name"] = "Name is required"
}

if !isCreate {
if item.ReceiptId == 0 {
errors["receiptId"] = "Receipt Id is required"
}
}

if item.ChargedToUserId == 0 {
errors["chargedToUserId"] = "Charged To User Id is required"
}

if len(item.Status) == 0 {
errors["status"] = "Status is required"
}

vErr.Errors = errors
return vErr
}
123 changes: 123 additions & 0 deletions internal/commands/upsert_receipt_command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package commands

import (
"encoding/json"
"fmt"
"github.com/shopspring/decimal"
"net/http"
"receipt-wrangler/api/internal/models"
"receipt-wrangler/api/internal/structs"
"receipt-wrangler/api/internal/utils"
"time"
)

type UpsertReceiptCommand struct {
Name string `json:"name"`
Amount decimal.Decimal `json:"amount"`
Date time.Time `json:"date"`
GroupId uint `json:"groupId"`
PaidByUserID uint `json:"paidByUserId"`
Status models.ReceiptStatus `json:"status"`
Categories []UpsertCategoryCommand `json:"categories"`
Tags []UpsertTagCommand `json:"tags"`
Items []UpsertItemCommand `json:"receiptItems"`
Comments []UpsertCommentCommand `json:"comments"`
CreatedByString string `json:"createdByString"`
}

func (receipt *UpsertReceiptCommand) LoadDataFromRequest(w http.ResponseWriter, r *http.Request) error {
bytes, err := utils.GetBodyData(w, r)
if err != nil {
return err
}

err = json.Unmarshal(bytes, &receipt)
if err != nil {
return err
}

return nil
}

func (receipt *UpsertReceiptCommand) Validate(tokenUserId uint, isCreate bool) structs.ValidatorError {
errors := make(map[string]string)
vErr := structs.ValidatorError{}

if len(receipt.Name) == 0 {
errors["name"] = "Name is required"
}

if receipt.Amount.IsZero() {
errors["amount"] = "Amount is required"
}

if receipt.Amount.LessThanOrEqual(decimal.Zero) {
errors["amount"] = "Amount must be greater than zero"
}

if receipt.Date.IsZero() {
errors["date"] = "Date is required"
}

if receipt.GroupId == 0 {
errors["groupId"] = "Group Id is required"
}

if receipt.PaidByUserID == 0 {
errors["paidByUserId"] = "Paid By User Id is required"
}

if receipt.Status == "" {
errors["status"] = "Status is required"
}

for i, category := range receipt.Categories {
basePath := "categories." + fmt.Sprintf("%d", i)
categoryErrors := category.Validate()
for key, value := range categoryErrors.Errors {
errors[basePath+"."+key] = value
}
}

for i, tag := range receipt.Tags {
basePath := "tags." + fmt.Sprintf("%d", i)
tagErrors := tag.Validate()
for key, value := range tagErrors.Errors {
errors[basePath+"."+key] = value
}
}

for i, item := range receipt.Items {
basePath := "receiptItems." + fmt.Sprintf("%d", i)
itemErrors := item.Validate(receipt.Amount, isCreate)
for key, value := range itemErrors.Errors {
errors[basePath+"."+key] = value
}
}

for i, comment := range receipt.Comments {
basePath := "comments." + fmt.Sprintf("%d", i)
commentErrors := comment.Validate(tokenUserId, isCreate)
for key, value := range commentErrors.Errors {
errors[basePath+"."+key] = value
}
}

vErr.Errors = errors
return vErr
}

func (receipt *UpsertReceiptCommand) ToReceipt() (models.Receipt, error) {
var result models.Receipt
bytes, err := json.Marshal(receipt)
if err != nil {
return result, err
}

err = json.Unmarshal(bytes, &result)
if err != nil {
return result, err
}

return result, nil
}
14 changes: 14 additions & 0 deletions internal/commands/upsert_tag_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package commands
import (
"encoding/json"
"net/http"
"receipt-wrangler/api/internal/structs"
"receipt-wrangler/api/internal/utils"
)

type UpsertTagCommand struct {
Id *uint `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
}
Expand All @@ -24,3 +26,15 @@ func (tag *UpsertTagCommand) LoadDataFromRequest(w http.ResponseWriter, r *http.

return nil
}

func (tag *UpsertTagCommand) Validate() structs.ValidatorError {
errors := make(map[string]string)
vErr := structs.ValidatorError{}

if len(tag.Name) == 0 {
errors["name"] = "Name is required"
}

vErr.Errors = errors
return vErr
}
12 changes: 6 additions & 6 deletions internal/email/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func processEmails(emailMetadata []structs.EmailMetadata, groupSettings []models
return err
}

receipt, err := services.ReadReceiptImageFromFileOnly(imageForOcrPath)
command, err := services.ReadReceiptImageFromFileOnly(imageForOcrPath)
if err != nil {
return err
}
Expand All @@ -168,12 +168,12 @@ func processEmails(emailMetadata []structs.EmailMetadata, groupSettings []models
return fmt.Errorf("could not find group settings with id %d", groupSettingsId)
}

receipt.GroupId = groupSettingsToUse.GroupId
receipt.Status = groupSettingsToUse.EmailDefaultReceiptStatus
receipt.PaidByUserID = *groupSettingsToUse.EmailDefaultReceiptPaidById
receipt.CreatedByString = "Email Integration"
command.GroupId = groupSettingsToUse.GroupId
command.Status = groupSettingsToUse.EmailDefaultReceiptStatus
command.PaidByUserID = *groupSettingsToUse.EmailDefaultReceiptPaidById
command.CreatedByString = "Email Integration"

createdReceipt, err := receiptRepository.CreateReceipt(receipt, 0)
createdReceipt, err := receiptRepository.CreateReceipt(command, 0)
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions internal/handlers/receipt_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,15 @@ func MagicFillFromImage(w http.ResponseWriter, r *http.Request) {
ResponseType: constants.APPLICATION_JSON,
HandlerFunction: func(w http.ResponseWriter, r *http.Request) (int, error) {
receiptImageId := r.URL.Query().Get("receiptImageId")
filledReceipt := models.Receipt{}
receiptCommand := commands.UpsertReceiptCommand{}

if len(receiptImageId) > 0 {
errCode, err := validateReceiptImageAccess(r, models.VIEWER, receiptImageId)
if err != nil {
return errCode, err
}

filledReceipt, err = services.ReadReceiptImage(receiptImageId)
receiptCommand, err = services.ReadReceiptImage(receiptImageId)
if err != nil {
return http.StatusInternalServerError, err
}
Expand All @@ -238,13 +238,13 @@ func MagicFillFromImage(w http.ResponseWriter, r *http.Request) {
Filename: fileHeader.Filename,
}

filledReceipt, err = services.MagicFillFromImage(magicFillCommand)
receiptCommand, err = services.MagicFillFromImage(magicFillCommand)
if err != nil {
return http.StatusInternalServerError, err
}
}

bytes, err := utils.MarshalResponseData(filledReceipt)
bytes, err := utils.MarshalResponseData(receiptCommand)
if err != nil {
return http.StatusInternalServerError, err
}
Expand Down
Loading

0 comments on commit 04ecc37

Please sign in to comment.