feat: add inventory repository for query logic

This commit is contained in:
Natthapol SERMSARAN 2025-03-29 19:12:46 +07:00
parent 044a2856cf
commit 4ed46f9ba5

View File

@ -0,0 +1,196 @@
package repository
import (
"context"
"fmt"
"strings"
"time"
"github.com/forfarm/backend/internal/domain"
)
type postgresInventoryRepository struct {
conn Connection
}
func NewPostgresInventory(conn Connection) domain.InventoryRepository {
return &postgresInventoryRepository{conn: conn}
}
func (p *postgresInventoryRepository) fetch(ctx context.Context, query string, args ...interface{}) ([]domain.InventoryItem, error) {
rows, err := p.conn.Query(ctx, query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var items []domain.InventoryItem
for rows.Next() {
var i domain.InventoryItem
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Category,
&i.Type,
&i.Quantity,
&i.Unit,
&i.DateAdded,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
return items, nil
}
func (p *postgresInventoryRepository) GetByID(ctx context.Context, id string) (domain.InventoryItem, error) {
query := `
SELECT id, name, category, type, quantity, unit, date_added, status, created_at, updated_at
FROM inventory_items
WHERE id = $1`
items, err := p.fetch(ctx, query, id)
if err != nil {
return domain.InventoryItem{}, err
}
if len(items) == 0 {
return domain.InventoryItem{}, domain.ErrNotFound
}
return items[0], nil
}
func (p *postgresInventoryRepository) GetWithFilter(ctx context.Context, filter domain.InventoryFilter, sort domain.InventorySort) ([]domain.InventoryItem, error) {
var query strings.Builder
args := []interface{}{}
argPos := 1
query.WriteString(`
SELECT id, name, category, type, quantity, unit, date_added, status, created_at, updated_at
FROM inventory_items
WHERE 1=1`)
if filter.Category != "" {
query.WriteString(fmt.Sprintf(" AND category = $%d", argPos))
args = append(args, filter.Category)
argPos++
}
if filter.Type != "" {
query.WriteString(fmt.Sprintf(" AND type = $%d", argPos))
args = append(args, filter.Type)
argPos++
}
if filter.Status != "" {
query.WriteString(fmt.Sprintf(" AND status = $%d", argPos))
args = append(args, filter.Status)
argPos++
}
if !filter.StartDate.IsZero() {
query.WriteString(fmt.Sprintf(" AND date_added >= $%d", argPos))
args = append(args, filter.StartDate)
argPos++
}
if !filter.EndDate.IsZero() {
query.WriteString(fmt.Sprintf(" AND date_added <= $%d", argPos))
args = append(args, filter.EndDate)
argPos++
}
if filter.SearchQuery != "" {
query.WriteString(fmt.Sprintf(" AND name ILIKE $%d", argPos))
args = append(args, "%"+filter.SearchQuery+"%")
argPos++
}
if sort.Field == "" {
sort.Field = "date_added"
sort.Direction = "desc"
}
validSortFields := map[string]bool{
"name": true,
"category": true,
"type": true,
"quantity": true,
"date_added": true,
"status": true,
"created_at": true,
}
if validSortFields[sort.Field] {
query.WriteString(fmt.Sprintf(" ORDER BY %s", sort.Field))
if strings.ToLower(sort.Direction) == "desc" {
query.WriteString(" DESC")
} else {
query.WriteString(" ASC")
}
}
return p.fetch(ctx, query.String(), args...)
}
func (p *postgresInventoryRepository) CreateOrUpdate(ctx context.Context, item *domain.InventoryItem) error {
now := time.Now()
item.UpdatedAt = now
if item.ID == "" {
item.CreatedAt = now
query := `
INSERT INTO inventory_items
(id, name, category, type, quantity, unit, date_added, status, created_at, updated_at)
VALUES (gen_random_uuid(), $1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING id`
return p.conn.QueryRow(
ctx,
query,
item.Name,
item.Category,
item.Type,
item.Quantity,
item.Unit,
item.DateAdded,
item.Status,
item.CreatedAt,
item.UpdatedAt,
).Scan(&item.ID)
}
query := `
UPDATE inventory_items
SET name = $1,
category = $2,
type = $3,
quantity = $4,
unit = $5,
date_added = $6,
status = $7,
updated_at = $8
WHERE id = $9
RETURNING id`
return p.conn.QueryRow(
ctx,
query,
item.Name,
item.Category,
item.Type,
item.Quantity,
item.Unit,
item.DateAdded,
item.Status,
item.UpdatedAt,
item.ID,
).Scan(&item.ID)
}
func (p *postgresInventoryRepository) Delete(ctx context.Context, id string) error {
query := `DELETE FROM inventory_items WHERE id = $1`
_, err := p.conn.Exec(ctx, query, id)
return err
}