201 lines
5.0 KiB
Go
201 lines
5.0 KiB
Go
package repository
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
models "vibeStonk/server/models/v1"
|
|
)
|
|
|
|
var (
|
|
ErrTransactionNotFound = errors.New("transaction not found")
|
|
)
|
|
|
|
func newSqliteTransactionRepo(db *sql.DB) (TransactionRepo, error) {
|
|
repo := &sqliteTransactionRepo{db: db}
|
|
if err := repo.initialize(); err != nil {
|
|
return nil, err
|
|
}
|
|
return repo, nil
|
|
}
|
|
|
|
type sqliteTransactionRepo struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
// initialize creates the transactions table if it doesn't exist
|
|
func (s *sqliteTransactionRepo) initialize() error {
|
|
query := `
|
|
CREATE TABLE IF NOT EXISTS transactions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
purchase_id INTEGER NOT NULL,
|
|
sale_id INTEGER NOT NULL,
|
|
qty REAL NOT NULL,
|
|
FOREIGN KEY (purchase_id) REFERENCES purchases(id),
|
|
FOREIGN KEY (sale_id) REFERENCES sales(id)
|
|
);
|
|
`
|
|
_, err := s.db.Exec(query)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create transactions table: %w", err)
|
|
}
|
|
|
|
query = `
|
|
CREATE INDEX IF NOT EXISTS transactions_foreign_id
|
|
ON transactions(purchase_id, sale_id);
|
|
`
|
|
_, err = s.db.Exec(query)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create purchase_id index for transactions table: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *sqliteTransactionRepo) Create(transaction *models.Transaction) (*models.Transaction, error) {
|
|
query := `
|
|
INSERT INTO transactions (purchase_id, sale_id, qty)
|
|
VALUES (?, ?, ?)
|
|
`
|
|
result, err := s.db.Exec(query, transaction.PurchaseID, transaction.SaleID, transaction.Qty)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create transaction: %w", err)
|
|
}
|
|
|
|
id, err := result.LastInsertId()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get last insert ID: %w", err)
|
|
}
|
|
|
|
transaction.Id = id
|
|
return transaction, nil
|
|
}
|
|
|
|
func (s *sqliteTransactionRepo) Get(id int64) (*models.Transaction, error) {
|
|
query := `
|
|
SELECT id, purchase_id, sale_id, qty
|
|
FROM transactions
|
|
WHERE id = ?
|
|
`
|
|
row := s.db.QueryRow(query, id)
|
|
|
|
transaction := &models.Transaction{}
|
|
err := row.Scan(&transaction.Id, &transaction.PurchaseID, &transaction.SaleID, &transaction.Qty)
|
|
if err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, ErrTransactionNotFound
|
|
}
|
|
return nil, fmt.Errorf("failed to get transaction: %w", err)
|
|
}
|
|
|
|
return transaction, nil
|
|
}
|
|
|
|
func (s *sqliteTransactionRepo) GetByPurchaseID(purchaseID int64) ([]*models.Transaction, error) {
|
|
query := `
|
|
SELECT id, purchase_id, sale_id, qty
|
|
FROM transactions
|
|
WHERE purchase_id = ?
|
|
`
|
|
rows, err := s.db.Query(query, purchaseID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get transactions by purchase ID: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var transactions []*models.Transaction
|
|
for rows.Next() {
|
|
transaction := &models.Transaction{}
|
|
err := rows.Scan(&transaction.Id, &transaction.PurchaseID, &transaction.SaleID, &transaction.Qty)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to scan transaction row: %w", err)
|
|
}
|
|
transactions = append(transactions, transaction)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("error iterating transaction rows: %w", err)
|
|
}
|
|
|
|
return transactions, nil
|
|
}
|
|
|
|
func (s *sqliteTransactionRepo) GetBySaleID(saleID int64) ([]*models.Transaction, error) {
|
|
query := `
|
|
SELECT id, purchase_id, sale_id, qty
|
|
FROM transactions
|
|
WHERE sale_id = ?
|
|
`
|
|
rows, err := s.db.Query(query, saleID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get transactions by sale ID: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var transactions []*models.Transaction
|
|
for rows.Next() {
|
|
transaction := &models.Transaction{}
|
|
err := rows.Scan(&transaction.Id, &transaction.PurchaseID, &transaction.SaleID, &transaction.Qty)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to scan transaction row: %w", err)
|
|
}
|
|
transactions = append(transactions, transaction)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("error iterating transaction rows: %w", err)
|
|
}
|
|
|
|
return transactions, nil
|
|
}
|
|
|
|
func (s *sqliteTransactionRepo) DeleteBySaleID(saleID int64) error {
|
|
query := `
|
|
DELETE FROM transactions
|
|
WHERE sale_id = ?
|
|
`
|
|
result, err := s.db.Exec(query, saleID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete transaction: %w", err)
|
|
}
|
|
|
|
rowsAffected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get rows affected: %w", err)
|
|
}
|
|
|
|
if rowsAffected == 0 {
|
|
return ErrTransactionNotFound
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *sqliteTransactionRepo) List() ([]*models.Transaction, error) {
|
|
query := `
|
|
SELECT id, purchase_id, sale_id, qty
|
|
FROM transactions
|
|
`
|
|
rows, err := s.db.Query(query)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list transactions: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var transactions []*models.Transaction
|
|
for rows.Next() {
|
|
transaction := &models.Transaction{}
|
|
err := rows.Scan(&transaction.Id, &transaction.PurchaseID, &transaction.SaleID, &transaction.Qty)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to scan transaction row: %w", err)
|
|
}
|
|
transactions = append(transactions, transaction)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("error iterating transaction rows: %w", err)
|
|
}
|
|
|
|
return transactions, nil
|
|
}
|