github.com/shoshinnikita/budget-manager@v0.7.1-0.20220131195411-8c46ff1c6778/internal/web/api/income.go (about) 1 package api 2 3 import ( 4 "context" 5 "errors" 6 "net/http" 7 8 "github.com/ShoshinNikita/budget-manager/internal/db" 9 "github.com/ShoshinNikita/budget-manager/internal/logger" 10 "github.com/ShoshinNikita/budget-manager/internal/pkg/money" 11 "github.com/ShoshinNikita/budget-manager/internal/pkg/reqid" 12 "github.com/ShoshinNikita/budget-manager/internal/web/api/models" 13 "github.com/ShoshinNikita/budget-manager/internal/web/utils" 14 ) 15 16 type IncomesHandlers struct { 17 db IncomesDB 18 log logger.Logger 19 } 20 21 type IncomesDB interface { 22 AddIncome(ctx context.Context, args db.AddIncomeArgs) (id uint, err error) 23 EditIncome(ctx context.Context, args db.EditIncomeArgs) error 24 RemoveIncome(ctx context.Context, id uint) error 25 } 26 27 // @Summary Create Income 28 // @Tags Incomes 29 // @Router /api/incomes [post] 30 // @Accept json 31 // @Param body body models.AddIncomeReq true "New Income" 32 // @Produce json 33 // @Success 201 {object} models.AddIncomeResp 34 // @Failure 400 {object} models.Response "Invalid request" 35 // @Failure 404 {object} models.Response "Month doesn't exist" 36 // @Failure 500 {object} models.Response "Internal error" 37 // 38 func (h IncomesHandlers) AddIncome(w http.ResponseWriter, r *http.Request) { 39 ctx := r.Context() 40 log := reqid.FromContextToLogger(ctx, h.log) 41 42 // Decode 43 req := &models.AddIncomeReq{} 44 if ok := utils.DecodeRequest(w, r, log, req); !ok { 45 return 46 } 47 log = log.WithRequest(req) 48 49 // Process 50 args := db.AddIncomeArgs{ 51 MonthID: req.MonthID, 52 Title: req.Title, 53 Notes: req.Notes, 54 Income: money.FromFloat(req.Income), 55 } 56 id, err := h.db.AddIncome(ctx, args) 57 if err != nil { 58 switch { 59 case errors.Is(err, db.ErrMonthNotExist): 60 utils.EncodeError(ctx, w, log, err, http.StatusNotFound) 61 default: 62 utils.EncodeInternalError(ctx, w, log, "couldn't add Income", err) 63 } 64 return 65 } 66 log = log.WithField("id", id) 67 log.Debug("Income was successfully added") 68 69 resp := &models.AddIncomeResp{ 70 ID: id, 71 } 72 utils.Encode(ctx, w, log, utils.EncodeResponse(resp), utils.EncodeStatusCode(http.StatusCreated)) 73 } 74 75 // @Summary Edit Income 76 // @Tags Incomes 77 // @Router /api/incomes [put] 78 // @Accept json 79 // @Param body body models.EditIncomeReq true "Updated Income" 80 // @Produce json 81 // @Success 200 {object} models.Response 82 // @Failure 400 {object} models.Response "Invalid request" 83 // @Failure 404 {object} models.Response "Income doesn't exist" 84 // @Failure 500 {object} models.Response "Internal error" 85 // 86 func (h IncomesHandlers) EditIncome(w http.ResponseWriter, r *http.Request) { 87 ctx := r.Context() 88 log := reqid.FromContextToLogger(ctx, h.log) 89 90 // Decode 91 req := &models.EditIncomeReq{} 92 if ok := utils.DecodeRequest(w, r, log, req); !ok { 93 return 94 } 95 log = log.WithRequest(req) 96 97 // Process 98 args := db.EditIncomeArgs{ 99 ID: req.ID, 100 Title: req.Title, 101 Notes: req.Notes, 102 } 103 if req.Income != nil { 104 income := money.FromFloat(*req.Income) 105 args.Income = &income 106 } 107 err := h.db.EditIncome(ctx, args) 108 if err != nil { 109 switch { 110 case errors.Is(err, db.ErrIncomeNotExist): 111 utils.EncodeError(ctx, w, log, err, http.StatusNotFound) 112 default: 113 utils.EncodeInternalError(ctx, w, log, "couldn't edit Income", err) 114 } 115 return 116 } 117 log.Debug("Income was successfully edited") 118 119 utils.Encode(ctx, w, log) 120 } 121 122 // @Summary Remove Income 123 // @Tags Incomes 124 // @Router /api/incomes [delete] 125 // @Accept json 126 // @Param body body models.RemoveIncomeReq true "Income id" 127 // @Produce json 128 // @Success 200 {object} models.Response 129 // @Failure 400 {object} models.Response "Invalid request" 130 // @Failure 404 {object} models.Response "Income doesn't exist" 131 // @Failure 500 {object} models.Response "Internal error" 132 // 133 func (h IncomesHandlers) RemoveIncome(w http.ResponseWriter, r *http.Request) { 134 ctx := r.Context() 135 log := reqid.FromContextToLogger(ctx, h.log) 136 137 // Decode 138 req := &models.RemoveIncomeReq{} 139 if ok := utils.DecodeRequest(w, r, log, req); !ok { 140 return 141 } 142 log = log.WithRequest(req) 143 144 // Process 145 err := h.db.RemoveIncome(ctx, req.ID) 146 if err != nil { 147 switch { 148 case errors.Is(err, db.ErrIncomeNotExist): 149 utils.EncodeError(ctx, w, log, err, http.StatusNotFound) 150 default: 151 utils.EncodeInternalError(ctx, w, log, "couldn't remove Income", err) 152 } 153 return 154 } 155 log.Debug("Income was successfully removed") 156 157 utils.Encode(ctx, w, log) 158 }