mirror of
https://github.com/ForFarmTeam/ForFarm.git
synced 2025-12-18 21:44:08 +01:00
315 lines
7.2 KiB
Go
315 lines
7.2 KiB
Go
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.UserID,
|
|
&i.Name,
|
|
&i.CategoryID,
|
|
&i.Quantity,
|
|
&i.UnitID,
|
|
&i.DateAdded,
|
|
&i.StatusID,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
func (p *postgresInventoryRepository) GetByID(ctx context.Context, id, userID string) (domain.InventoryItem, error) {
|
|
query := `
|
|
SELECT
|
|
i.id, i.user_id, i.name, i.category_id, i.quantity, i.unit_id,
|
|
i.date_added, i.status_id, i.created_at, i.updated_at,
|
|
c.name as category_name,
|
|
s.name as status_name,
|
|
u.name as unit_name
|
|
FROM inventory_items i
|
|
LEFT JOIN inventory_category c ON i.category_id = c.id
|
|
LEFT JOIN inventory_status s ON i.status_id = s.id
|
|
LEFT JOIN harvest_units u ON i.unit_id = u.id
|
|
WHERE i.id = $1 AND i.user_id = $2`
|
|
|
|
rows, err := p.conn.Query(ctx, query, id, userID)
|
|
if err != nil {
|
|
return domain.InventoryItem{}, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
if !rows.Next() {
|
|
return domain.InventoryItem{}, domain.ErrNotFound
|
|
}
|
|
|
|
var item domain.InventoryItem
|
|
err = rows.Scan(
|
|
&item.ID,
|
|
&item.UserID,
|
|
&item.Name,
|
|
&item.CategoryID,
|
|
&item.Quantity,
|
|
&item.UnitID,
|
|
&item.DateAdded,
|
|
&item.StatusID,
|
|
&item.CreatedAt,
|
|
&item.UpdatedAt,
|
|
&item.Category.Name,
|
|
&item.Status.Name,
|
|
&item.Unit.Name,
|
|
)
|
|
if err != nil {
|
|
return domain.InventoryItem{}, err
|
|
}
|
|
|
|
return item, nil
|
|
}
|
|
|
|
func (p *postgresInventoryRepository) GetByUserID(
|
|
ctx context.Context,
|
|
userID string,
|
|
filter domain.InventoryFilter,
|
|
sort domain.InventorySort,
|
|
) ([]domain.InventoryItem, error) {
|
|
var query strings.Builder
|
|
args := []interface{}{userID}
|
|
argPos := 2
|
|
|
|
query.WriteString(`
|
|
SELECT
|
|
i.id, i.user_id, i.name, i.category_id, i.quantity, i.unit_id,
|
|
i.date_added, i.status_id, i.created_at, i.updated_at,
|
|
c.name as category_name,
|
|
s.name as status_name,
|
|
u.name as unit_name
|
|
FROM inventory_items i
|
|
LEFT JOIN inventory_category c ON i.category_id = c.id
|
|
LEFT JOIN inventory_status s ON i.status_id = s.id
|
|
LEFT JOIN harvest_units u ON i.unit_id = u.id
|
|
WHERE i.user_id = $1`)
|
|
|
|
if filter.CategoryID != 0 {
|
|
query.WriteString(fmt.Sprintf(" AND i.category_id = $%d", argPos))
|
|
args = append(args, filter.CategoryID)
|
|
argPos++
|
|
}
|
|
|
|
if filter.StatusID != 0 {
|
|
query.WriteString(fmt.Sprintf(" AND i.status_id = $%d", argPos))
|
|
args = append(args, filter.StatusID)
|
|
argPos++
|
|
}
|
|
|
|
if !filter.StartDate.IsZero() {
|
|
query.WriteString(fmt.Sprintf(" AND i.date_added >= $%d", argPos))
|
|
args = append(args, filter.StartDate)
|
|
argPos++
|
|
}
|
|
|
|
if !filter.EndDate.IsZero() {
|
|
query.WriteString(fmt.Sprintf(" AND i.date_added <= $%d", argPos))
|
|
args = append(args, filter.EndDate)
|
|
argPos++
|
|
}
|
|
|
|
if filter.SearchQuery != "" {
|
|
query.WriteString(fmt.Sprintf(" AND i.name ILIKE $%d", argPos))
|
|
args = append(args, "%"+filter.SearchQuery+"%")
|
|
argPos++
|
|
}
|
|
|
|
if sort.Field == "" {
|
|
sort.Field = "i.date_added"
|
|
sort.Direction = "desc"
|
|
}
|
|
|
|
validSortFields := map[string]bool{
|
|
"name": true,
|
|
"quantity": true,
|
|
"date_added": 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")
|
|
}
|
|
}
|
|
|
|
rows, err := p.conn.Query(ctx, query.String(), args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var items []domain.InventoryItem
|
|
for rows.Next() {
|
|
var item domain.InventoryItem
|
|
err := rows.Scan(
|
|
&item.ID,
|
|
&item.UserID,
|
|
&item.Name,
|
|
&item.CategoryID,
|
|
&item.Quantity,
|
|
&item.UnitID,
|
|
&item.DateAdded,
|
|
&item.StatusID,
|
|
&item.CreatedAt,
|
|
&item.UpdatedAt,
|
|
&item.Category.Name,
|
|
&item.Status.Name,
|
|
&item.Unit.Name,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, item)
|
|
}
|
|
|
|
return items, nil
|
|
}
|
|
|
|
func (p *postgresInventoryRepository) GetAll(ctx context.Context) ([]domain.InventoryItem, error) {
|
|
query := `
|
|
SELECT
|
|
i.id, i.user_id, i.name, i.category_id, i.quantity, i.unit_id,
|
|
i.date_added, i.status_id, i.created_at, i.updated_at,
|
|
c.name as category_name,
|
|
s.name as status_name,
|
|
u.name as unit_name
|
|
FROM inventory_items i
|
|
LEFT JOIN inventory_category c ON i.category_id = c.id
|
|
LEFT JOIN inventory_status s ON i.status_id = s.id
|
|
LEFT JOIN harvest_units u ON i.unit_id = u.id
|
|
ORDER BY i.created_at DESC`
|
|
return p.fetch(ctx, query)
|
|
}
|
|
|
|
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, user_id, name, category_id, quantity, unit_id, date_added, status_id, 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.UserID,
|
|
item.Name,
|
|
item.CategoryID,
|
|
item.Quantity,
|
|
item.UnitID,
|
|
item.DateAdded,
|
|
item.StatusID,
|
|
item.CreatedAt,
|
|
item.UpdatedAt,
|
|
).Scan(&item.ID)
|
|
}
|
|
|
|
query := `
|
|
UPDATE inventory_items
|
|
SET name = $1,
|
|
category_id = $2,
|
|
quantity = $3,
|
|
unit_id = $4,
|
|
date_added = $5,
|
|
status_id = $6,
|
|
updated_at = $7
|
|
WHERE id = $8 AND user_id = $9
|
|
RETURNING id`
|
|
|
|
return p.conn.QueryRow(
|
|
ctx,
|
|
query,
|
|
item.Name,
|
|
item.CategoryID,
|
|
item.Quantity,
|
|
item.UnitID,
|
|
item.DateAdded,
|
|
item.StatusID,
|
|
item.UpdatedAt,
|
|
item.ID,
|
|
item.UserID,
|
|
).Scan(&item.ID)
|
|
}
|
|
|
|
func (p *postgresInventoryRepository) Delete(ctx context.Context, id, userID string) error {
|
|
query := `DELETE FROM inventory_items WHERE id = $1 AND user_id = $2`
|
|
_, err := p.conn.Exec(ctx, query, id, userID)
|
|
return err
|
|
}
|
|
|
|
func (p *postgresInventoryRepository) GetStatuses(ctx context.Context) ([]domain.InventoryStatus, error) {
|
|
query := `SELECT id, name FROM inventory_status ORDER BY id`
|
|
rows, err := p.conn.Query(ctx, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var statuses []domain.InventoryStatus
|
|
for rows.Next() {
|
|
var s domain.InventoryStatus
|
|
if err := rows.Scan(&s.ID, &s.Name); err != nil {
|
|
return nil, err
|
|
}
|
|
statuses = append(statuses, s)
|
|
}
|
|
return statuses, nil
|
|
}
|
|
|
|
func (p *postgresInventoryRepository) GetCategories(ctx context.Context) ([]domain.InventoryCategory, error) {
|
|
query := `SELECT id, name FROM inventory_category ORDER BY id`
|
|
rows, err := p.conn.Query(ctx, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var categories []domain.InventoryCategory
|
|
for rows.Next() {
|
|
var c domain.InventoryCategory
|
|
if err := rows.Scan(&c.ID, &c.Name); err != nil {
|
|
return nil, err
|
|
}
|
|
categories = append(categories, c)
|
|
}
|
|
return categories, nil
|
|
}
|