github.com/shoshinnikita/budget-manager@v0.7.1-0.20220131195411-8c46ff1c6778/internal/db/base/monthly_payment.go (about) 1 package base 2 3 import ( 4 "context" 5 "time" 6 7 common "github.com/ShoshinNikita/budget-manager/internal/db" 8 "github.com/ShoshinNikita/budget-manager/internal/db/base/internal/sqlx" 9 "github.com/ShoshinNikita/budget-manager/internal/db/base/types" 10 "github.com/ShoshinNikita/budget-manager/internal/pkg/errors" 11 "github.com/ShoshinNikita/budget-manager/internal/pkg/money" 12 ) 13 14 type MonthlyPayment struct { 15 ID uint `db:"id"` 16 MonthID uint `db:"month_id"` 17 Title string `db:"title"` 18 TypeID types.Uint `db:"type_id"` 19 Notes types.String `db:"notes"` 20 Cost money.Money `db:"cost"` 21 22 Type *SpendType `db:"type"` 23 } 24 25 // ToCommon converts MonthlyPayment to common MonthlyPayment structure from 26 // "github.com/ShoshinNikita/budget-manager/internal/db" package 27 func (mp MonthlyPayment) ToCommon(year int, month time.Month) common.MonthlyPayment { 28 return common.MonthlyPayment{ 29 ID: mp.ID, 30 Year: year, 31 Month: month, 32 Title: mp.Title, 33 Type: mp.Type.ToCommon(), 34 Notes: string(mp.Notes), 35 Cost: mp.Cost, 36 } 37 } 38 39 // AddMonthlyPayment adds new Monthly Payment 40 func (db DB) AddMonthlyPayment(ctx context.Context, args common.AddMonthlyPaymentArgs) (id uint, err error) { 41 err = db.db.RunInTransaction(ctx, func(tx *sqlx.Tx) error { 42 if !checkMonth(tx, args.MonthID) { 43 return common.ErrMonthNotExist 44 } 45 if args.TypeID != 0 && !checkSpendType(tx, args.TypeID) { 46 return common.ErrSpendTypeNotExist 47 } 48 49 err = tx.Get( 50 &id, 51 `INSERT INTO monthly_payments(month_id, title, notes, type_id, cost) VALUES(?, ?, ?, ?, ?) RETURNING id`, 52 args.MonthID, args.Title, args.Notes, types.Uint(args.TypeID), args.Cost, 53 ) 54 if err != nil { 55 return err 56 } 57 return db.recomputeAndUpdateMonth(tx, args.MonthID) 58 }) 59 if err != nil { 60 return 0, err 61 } 62 63 return id, nil 64 } 65 66 // EditMonthlyPayment modifies existing Monthly Payment 67 func (db DB) EditMonthlyPayment(ctx context.Context, args common.EditMonthlyPaymentArgs) error { 68 return db.db.RunInTransaction(ctx, func(tx *sqlx.Tx) error { 69 if !checkMonthlyPayment(tx, args.ID) { 70 return common.ErrMonthlyPaymentNotExist 71 } 72 if args.TypeID != nil && *args.TypeID != 0 && !checkSpendType(tx, *args.TypeID) { 73 return common.ErrSpendTypeNotExist 74 } 75 76 monthID, err := db.selectMonthlyPaymentMonthID(tx, args.ID) 77 if err != nil { 78 return err 79 } 80 81 query := newUpdateQueryBuilder("monthly_payments", args.ID) 82 if args.Title != nil { 83 query.Set("title", *args.Title) 84 } 85 if args.TypeID != nil { 86 if *args.TypeID == 0 { 87 query.Set("type_id", nil) 88 } else { 89 query.Set("type_id", *args.TypeID) 90 } 91 } 92 if args.Notes != nil { 93 query.Set("notes", *args.Notes) 94 } 95 if args.Cost != nil { 96 query.Set("cost", *args.Cost) 97 } 98 if _, err := tx.ExecQuery(query); err != nil { 99 return err 100 } 101 102 if args.Cost != nil { 103 // Recompute month only when cost has been changed 104 return db.recomputeAndUpdateMonth(tx, monthID) 105 } 106 return nil 107 }) 108 } 109 110 // RemoveMonthlyPayment removes Monthly Payment with passed id 111 func (db DB) RemoveMonthlyPayment(ctx context.Context, id uint) error { 112 return db.db.RunInTransaction(ctx, func(tx *sqlx.Tx) error { 113 if !checkMonthlyPayment(tx, id) { 114 return common.ErrMonthlyPaymentNotExist 115 } 116 117 monthID, err := db.selectMonthlyPaymentMonthID(tx, id) 118 if err != nil { 119 return err 120 } 121 122 _, err = tx.Exec(`DELETE FROM monthly_payments WHERE id = ?`, id) 123 if err != nil { 124 return err 125 } 126 127 return db.recomputeAndUpdateMonth(tx, monthID) 128 }) 129 } 130 131 func (DB) selectMonthlyPaymentMonthID(tx *sqlx.Tx, id uint) (monthID uint, err error) { 132 err = tx.Get(&monthID, `SELECT month_id FROM monthly_payments WHERE id = ?`, id) 133 if err != nil { 134 return 0, errors.Wrap(err, "couldn't select month id of Monthly Payment") 135 } 136 return monthID, nil 137 }