feat: loans
This commit is contained in:
parent
f05c36e44f
commit
ac7296b06e
20 changed files with 3191 additions and 4 deletions
107
internal/repository/loan.go
Normal file
107
internal/repository/loan.go
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/model"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrLoanNotFound = errors.New("loan not found")
|
||||
)
|
||||
|
||||
type LoanRepository interface {
|
||||
Create(loan *model.Loan) error
|
||||
GetByID(id string) (*model.Loan, error)
|
||||
GetBySpaceID(spaceID string) ([]*model.Loan, error)
|
||||
GetBySpaceIDPaginated(spaceID string, limit, offset int) ([]*model.Loan, error)
|
||||
CountBySpaceID(spaceID string) (int, error)
|
||||
Update(loan *model.Loan) error
|
||||
Delete(id string) error
|
||||
SetPaidOff(id string, paidOff bool) error
|
||||
GetTotalPaidForLoan(loanID string) (int, error)
|
||||
GetReceiptCountForLoan(loanID string) (int, error)
|
||||
}
|
||||
|
||||
type loanRepository struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
func NewLoanRepository(db *sqlx.DB) LoanRepository {
|
||||
return &loanRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *loanRepository) Create(loan *model.Loan) error {
|
||||
query := `INSERT INTO loans (id, space_id, name, description, original_amount_cents, interest_rate_bps, start_date, end_date, is_paid_off, created_by, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);`
|
||||
_, err := r.db.Exec(query, loan.ID, loan.SpaceID, loan.Name, loan.Description, loan.OriginalAmountCents, loan.InterestRateBps, loan.StartDate, loan.EndDate, loan.IsPaidOff, loan.CreatedBy, loan.CreatedAt, loan.UpdatedAt)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *loanRepository) GetByID(id string) (*model.Loan, error) {
|
||||
loan := &model.Loan{}
|
||||
query := `SELECT * FROM loans WHERE id = $1;`
|
||||
err := r.db.Get(loan, query, id)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, ErrLoanNotFound
|
||||
}
|
||||
return loan, err
|
||||
}
|
||||
|
||||
func (r *loanRepository) GetBySpaceID(spaceID string) ([]*model.Loan, error) {
|
||||
var loans []*model.Loan
|
||||
query := `SELECT * FROM loans WHERE space_id = $1 ORDER BY is_paid_off ASC, created_at DESC;`
|
||||
err := r.db.Select(&loans, query, spaceID)
|
||||
return loans, err
|
||||
}
|
||||
|
||||
func (r *loanRepository) GetBySpaceIDPaginated(spaceID string, limit, offset int) ([]*model.Loan, error) {
|
||||
var loans []*model.Loan
|
||||
query := `SELECT * FROM loans WHERE space_id = $1 ORDER BY is_paid_off ASC, created_at DESC LIMIT $2 OFFSET $3;`
|
||||
err := r.db.Select(&loans, query, spaceID, limit, offset)
|
||||
return loans, err
|
||||
}
|
||||
|
||||
func (r *loanRepository) CountBySpaceID(spaceID string) (int, error) {
|
||||
var count int
|
||||
err := r.db.Get(&count, `SELECT COUNT(*) FROM loans WHERE space_id = $1;`, spaceID)
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (r *loanRepository) Update(loan *model.Loan) error {
|
||||
query := `UPDATE loans SET name = $1, description = $2, original_amount_cents = $3, interest_rate_bps = $4, start_date = $5, end_date = $6, updated_at = $7 WHERE id = $8;`
|
||||
result, err := r.db.Exec(query, loan.Name, loan.Description, loan.OriginalAmountCents, loan.InterestRateBps, loan.StartDate, loan.EndDate, loan.UpdatedAt, loan.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rows, err := result.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return ErrLoanNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *loanRepository) Delete(id string) error {
|
||||
_, err := r.db.Exec(`DELETE FROM loans WHERE id = $1;`, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *loanRepository) SetPaidOff(id string, paidOff bool) error {
|
||||
_, err := r.db.Exec(`UPDATE loans SET is_paid_off = $1, updated_at = $2 WHERE id = $3;`, paidOff, time.Now(), id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *loanRepository) GetTotalPaidForLoan(loanID string) (int, error) {
|
||||
var total int
|
||||
err := r.db.Get(&total, `SELECT COALESCE(SUM(total_amount_cents), 0) FROM receipts WHERE loan_id = $1;`, loanID)
|
||||
return total, err
|
||||
}
|
||||
|
||||
func (r *loanRepository) GetReceiptCountForLoan(loanID string) (int, error) {
|
||||
var count int
|
||||
err := r.db.Get(&count, `SELECT COUNT(*) FROM receipts WHERE loan_id = $1;`, loanID)
|
||||
return count, err
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue