refactor: restructure in entirety
This commit is contained in:
99
internal/database/invoice.go
Normal file
99
internal/database/invoice.go
Normal file
@@ -0,0 +1,99 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user