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  }