Files
billit/internal/database/invoice.go
2025-12-06 15:31:18 +05:30

100 lines
3.1 KiB
Go

package database
import (
"billit/internal/models"
"database/sql"
"encoding/json"
"fmt"
"time"
)
// GetNextInvoiceNumber generates the next invoice ID in format PREFIX/MMM-YYYY/XXX and increments the counter
func (s *service) GetNextInvoiceNumber(userID string) (string, error) {
var prefix string
var counter int
// Get current prefix and counter
err := s.db.QueryRow(`SELECT COALESCE(invoice_prefix, 'INV'), COALESCE(invoice_counter, 0) FROM users WHERE id = ?`, userID).
Scan(&prefix, &counter)
if err != nil {
return "", err
}
// Increment counter
counter++
// Update counter in database
_, err = s.db.Exec(`UPDATE users SET invoice_counter = ? WHERE id = ?`, counter, userID)
if err != nil {
return "", err
}
// Generate formatted invoice ID: PREFIX/MMM-YYYY/XXX
now := time.Now()
humanReadableID := fmt.Sprintf("%s/%s-%d/%03d", prefix, now.Month().String()[:3], now.Year(), counter)
return humanReadableID, nil
}
// CreateInvoice stores an invoice with UUID and human-readable ID for a user
func (s *service) CreateInvoice(id string, humanReadableID string, data interface{}, userID string) error {
jsonData, err := json.Marshal(data)
if err != nil {
return err
}
_, err = s.db.Exec(`INSERT INTO invoices (id, human_readable_id, data, user_id) VALUES (?, ?, ?, ?)`, id, humanReadableID, string(jsonData), userID)
return err
}
// GetInvoice retrieves an invoice by ID for a user
func (s *service) GetInvoice(id string, userID string) (*models.Invoice, error) {
var inv models.Invoice
err := s.db.QueryRow(`SELECT id, COALESCE(human_readable_id, ''), data, user_id, created_at FROM invoices WHERE id=? AND user_id=?`, id, userID).
Scan(&inv.ID, &inv.HumanReadableID, &inv.Data, &inv.UserID, &inv.CreatedAt)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
return &inv, nil
}
// GetAllInvoices retrieves all invoices for a user
func (s *service) GetAllInvoices(userID string) ([]models.Invoice, error) {
rows, err := s.db.Query(`SELECT id, COALESCE(human_readable_id, ''), data, user_id, created_at FROM invoices WHERE user_id=? ORDER BY created_at DESC`, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var invoices []models.Invoice
for rows.Next() {
var inv models.Invoice
if err := rows.Scan(&inv.ID, &inv.HumanReadableID, &inv.Data, &inv.UserID, &inv.CreatedAt); err != nil {
return nil, err
}
invoices = append(invoices, inv)
}
return invoices, nil
}
// GetRecentInvoices returns the most recently generated invoices for a user
func (s *service) GetRecentInvoices(userID string, limit int) ([]models.Invoice, error) {
rows, err := s.db.Query(`SELECT id, COALESCE(human_readable_id, ''), data, user_id, created_at FROM invoices WHERE user_id=? ORDER BY created_at DESC LIMIT ?`, userID, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var invoices []models.Invoice
for rows.Next() {
var inv models.Invoice
if err := rows.Scan(&inv.ID, &inv.HumanReadableID, &inv.Data, &inv.UserID, &inv.CreatedAt); err != nil {
return nil, err
}
invoices = append(invoices, inv)
}
return invoices, nil
}