feat: implement inventory repository with status and category relations

This commit is contained in:
Natthapol SERMSARAN 2025-04-01 15:16:51 +07:00
parent 6dac03a489
commit b79f3f69f3

View File

@ -31,12 +31,11 @@ func (p *postgresInventoryRepository) fetch(ctx context.Context, query string, a
&i.ID,
&i.UserID,
&i.Name,
&i.Category,
&i.Type,
&i.CategoryID,
&i.Quantity,
&i.Unit,
&i.UnitID,
&i.DateAdded,
&i.Status,
&i.StatusID,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
@ -49,18 +48,49 @@ func (p *postgresInventoryRepository) fetch(ctx context.Context, query string, a
func (p *postgresInventoryRepository) GetByID(ctx context.Context, id, userID string) (domain.InventoryItem, error) {
query := `
SELECT id, user_id, name, category, type, quantity, unit, date_added, status, created_at, updated_at
FROM inventory_items
WHERE id = $1 AND user_id = $2`
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`
items, err := p.fetch(ctx, query, id, userID)
rows, err := p.conn.Query(ctx, query, id, userID)
if err != nil {
return domain.InventoryItem{}, err
}
if len(items) == 0 {
defer rows.Close()
if !rows.Next() {
return domain.InventoryItem{}, domain.ErrNotFound
}
return items[0], nil
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(
@ -74,58 +104,57 @@ func (p *postgresInventoryRepository) GetByUserID(
argPos := 2
query.WriteString(`
SELECT id, user_id, name, category, type, quantity, unit, date_added, status, created_at, updated_at
FROM inventory_items
WHERE user_id = $1`)
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.Category != "" {
query.WriteString(fmt.Sprintf(" AND category = $%d", argPos))
args = append(args, filter.Category)
if filter.CategoryID != 0 {
query.WriteString(fmt.Sprintf(" AND i.category_id = $%d", argPos))
args = append(args, filter.CategoryID)
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)
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 date_added >= $%d", argPos))
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 date_added <= $%d", argPos))
query.WriteString(fmt.Sprintf(" AND i.date_added <= $%d", argPos))
args = append(args, filter.EndDate)
argPos++
}
if filter.SearchQuery != "" {
query.WriteString(fmt.Sprintf(" AND name ILIKE $%d", argPos))
query.WriteString(fmt.Sprintf(" AND i.name ILIKE $%d", argPos))
args = append(args, "%"+filter.SearchQuery+"%")
argPos++
}
if sort.Field == "" {
sort.Field = "date_added"
sort.Field = "i.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,
}
@ -138,14 +167,52 @@ func (p *postgresInventoryRepository) GetByUserID(
}
}
return p.fetch(ctx, query.String(), args...)
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 id, user_id, name, category, type, quantity, unit, date_added, status, created_at, updated_at
FROM inventory_items
ORDER BY created_at DESC`
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)
}
@ -157,20 +224,19 @@ func (p *postgresInventoryRepository) CreateOrUpdate(ctx context.Context, item *
item.CreatedAt = now
query := `
INSERT INTO inventory_items
(id, user_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, $10)
(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.Category,
item.Type,
item.CategoryID,
item.Quantity,
item.Unit,
item.UnitID,
item.DateAdded,
item.Status,
item.StatusID,
item.CreatedAt,
item.UpdatedAt,
).Scan(&item.ID)
@ -179,26 +245,24 @@ func (p *postgresInventoryRepository) CreateOrUpdate(ctx context.Context, item *
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 AND user_id = $10
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.Category,
item.Type,
item.CategoryID,
item.Quantity,
item.Unit,
item.UnitID,
item.DateAdded,
item.Status,
item.StatusID,
item.UpdatedAt,
item.ID,
item.UserID,
@ -210,3 +274,41 @@ func (p *postgresInventoryRepository) Delete(ctx context.Context, id, userID str
_, 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
}