mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
209 lines
6.8 KiB
Go
209 lines
6.8 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/glebarez/sqlite"
|
|
"gitlab.com/mbugroup/lti-api.git/internal/utils/fifo"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func TestSapronakIncomingPurchaseQueryPartsUsesAttributedPurchasesWhenProjectFlockKandangIDsProvided(t *testing.T) {
|
|
sql, args := sapronakIncomingPurchaseQueryParts(SapronakQueryParams{
|
|
WarehouseIDs: []uint{46},
|
|
ProjectFlockKandangIDs: []uint{101},
|
|
})
|
|
|
|
if sql != sapronakIncomingPurchasesScopedSQL() {
|
|
t.Fatalf("expected scoped purchase SQL, got %q", sql)
|
|
}
|
|
if len(args) != 8 {
|
|
t.Fatalf("expected 8 argument groups, got %d", len(args))
|
|
}
|
|
}
|
|
|
|
func TestFetchSapronakIncomingIncludesAttributedFarmPurchasesAndHistoricalWarehouseFallback(t *testing.T) {
|
|
db := setupClosingRepositoryTestDB(t)
|
|
repo := NewClosingRepository(db)
|
|
ctx := context.Background()
|
|
|
|
receivedAt := time.Date(2026, 4, 1, 4, 0, 0, 0, time.UTC)
|
|
statements := []string{
|
|
`INSERT INTO warehouses (id, kandang_id) VALUES (1, NULL), (2, 59), (3, 88)`,
|
|
`INSERT INTO product_categories (id, code) VALUES (1, 'OBT'), (2, 'RAW')`,
|
|
`INSERT INTO products (id, name, product_category_id, product_price) VALUES
|
|
(10, 'MEFISTO @1 LITER', 1, 261700),
|
|
(20, 'PAKAN GROWING CRUMBLE MALINDO', 2, 15000)`,
|
|
`INSERT INTO flags (id, flagable_id, flagable_type, name) VALUES
|
|
(1, 10, 'products', 'OVK'),
|
|
(2, 10, 'products', 'OBAT')`,
|
|
`INSERT INTO purchases (id, po_number, deleted_at) VALUES (1, 'PO-LTI-0005', NULL)`,
|
|
`INSERT INTO recordings (id, project_flock_kandangs_id, deleted_at) VALUES (11, 101, NULL), (12, 999, NULL)`,
|
|
`INSERT INTO recording_stocks (id, recording_id, product_warehouse_id, usage_qty) VALUES (21, 11, 501, 150), (22, 12, 502, 10)`,
|
|
`INSERT INTO purchase_items (id, purchase_id, product_id, warehouse_id, project_flock_kandang_id, total_qty, price, received_date) VALUES
|
|
(1, 1, 10, 1, NULL, 100, 261700, '` + receivedAt.Format(time.RFC3339) + `'),
|
|
(2, 1, 20, 1, NULL, 50, 15000, '` + receivedAt.Format(time.RFC3339) + `'),
|
|
(3, 1, 20, 2, NULL, 25, 12000, '` + receivedAt.Format(time.RFC3339) + `'),
|
|
(4, 1, 10, 3, 999, 10, 261700, '` + receivedAt.Format(time.RFC3339) + `'),
|
|
(5, 1, 20, 1, NULL, 40, 15000, '` + receivedAt.Format(time.RFC3339) + `')`,
|
|
fmt.Sprintf(`INSERT INTO stock_allocations (id, product_warehouse_id, stockable_type, stockable_id, usable_type, usable_id, qty, allocation_purpose, status) VALUES
|
|
(1, 701, '%s', 1, '%s', 21, 100, 'CONSUME', 'ACTIVE'),
|
|
(2, 702, '%s', 2, '%s', 21, 50, 'CONSUME', 'ACTIVE'),
|
|
(3, 703, '%s', 5, '%s', 22, 40, 'CONSUME', 'ACTIVE')`,
|
|
fifo.StockableKeyPurchaseItems.String(),
|
|
fifo.UsableKeyRecordingStock.String(),
|
|
fifo.StockableKeyPurchaseItems.String(),
|
|
fifo.UsableKeyRecordingStock.String(),
|
|
fifo.StockableKeyPurchaseItems.String(),
|
|
fifo.UsableKeyRecordingStock.String(),
|
|
),
|
|
}
|
|
for _, stmt := range statements {
|
|
if err := db.Exec(stmt).Error; err != nil {
|
|
t.Fatalf("failed seeding schema: %v", err)
|
|
}
|
|
}
|
|
|
|
rows, err := repo.FetchSapronakIncoming(ctx, 101, 59, nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(rows) != 2 {
|
|
t.Fatalf("expected 2 sapronak rows, got %d", len(rows))
|
|
}
|
|
|
|
byProduct := make(map[uint]SapronakIncomingRow, len(rows))
|
|
for _, row := range rows {
|
|
byProduct[row.ProductID] = row
|
|
}
|
|
|
|
if got := byProduct[10]; got.ProductID == 0 || got.Flag != "OVK" || got.Qty != 100 {
|
|
t.Fatalf("expected OVK farm purchase qty 100 for product 10, got %+v", got)
|
|
}
|
|
|
|
if got := byProduct[20]; got.ProductID == 0 || got.Flag != "PAKAN" || got.Qty != 75 {
|
|
t.Fatalf("expected PAKAN total qty 75 including farm allocated qty 50 and kandang receipt qty 25, got %+v", got)
|
|
}
|
|
}
|
|
|
|
func setupClosingRepositoryTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
|
|
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=private"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("failed opening sqlite db: %v", err)
|
|
}
|
|
|
|
statements := []string{
|
|
`CREATE TABLE warehouses (
|
|
id INTEGER PRIMARY KEY,
|
|
kandang_id INTEGER NULL
|
|
)`,
|
|
`CREATE TABLE product_categories (
|
|
id INTEGER PRIMARY KEY,
|
|
code TEXT NOT NULL
|
|
)`,
|
|
`CREATE TABLE uoms (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL
|
|
)`,
|
|
`CREATE TABLE products (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
product_category_id INTEGER NULL,
|
|
uom_id INTEGER NULL,
|
|
product_price NUMERIC(15,3) NOT NULL DEFAULT 0
|
|
)`,
|
|
`CREATE TABLE flags (
|
|
id INTEGER PRIMARY KEY,
|
|
flagable_id INTEGER NOT NULL,
|
|
flagable_type TEXT NOT NULL,
|
|
name TEXT NOT NULL
|
|
)`,
|
|
`CREATE TABLE purchases (
|
|
id INTEGER PRIMARY KEY,
|
|
po_number TEXT NULL,
|
|
notes TEXT NULL,
|
|
deleted_at TIMESTAMP NULL
|
|
)`,
|
|
`CREATE TABLE purchase_items (
|
|
id INTEGER PRIMARY KEY,
|
|
purchase_id INTEGER NOT NULL,
|
|
product_id INTEGER NOT NULL,
|
|
warehouse_id INTEGER NOT NULL,
|
|
project_flock_kandang_id INTEGER NULL,
|
|
total_qty NUMERIC(15,3) NOT NULL DEFAULT 0,
|
|
price NUMERIC(15,3) NOT NULL DEFAULT 0,
|
|
received_date TIMESTAMP NULL
|
|
)`,
|
|
`CREATE TABLE recordings (
|
|
id INTEGER PRIMARY KEY,
|
|
project_flock_kandangs_id INTEGER NOT NULL,
|
|
deleted_at TIMESTAMP NULL
|
|
)`,
|
|
`CREATE TABLE recording_stocks (
|
|
id INTEGER PRIMARY KEY,
|
|
recording_id INTEGER NOT NULL,
|
|
product_warehouse_id INTEGER NOT NULL,
|
|
usage_qty NUMERIC(15,3) NOT NULL DEFAULT 0
|
|
)`,
|
|
`CREATE TABLE project_chickins (
|
|
id INTEGER PRIMARY KEY,
|
|
project_flock_kandang_id INTEGER NOT NULL
|
|
)`,
|
|
`CREATE TABLE stock_allocations (
|
|
id INTEGER PRIMARY KEY,
|
|
product_warehouse_id INTEGER NOT NULL,
|
|
stockable_type TEXT NOT NULL,
|
|
stockable_id INTEGER NOT NULL,
|
|
usable_type TEXT NOT NULL,
|
|
usable_id INTEGER NOT NULL,
|
|
qty NUMERIC(15,3) NOT NULL DEFAULT 0,
|
|
allocation_purpose TEXT NOT NULL,
|
|
status TEXT NOT NULL
|
|
)`,
|
|
`CREATE TABLE product_warehouses (
|
|
id INTEGER PRIMARY KEY,
|
|
product_id INTEGER NOT NULL,
|
|
warehouse_id INTEGER NOT NULL,
|
|
project_flock_kandang_id INTEGER NULL
|
|
)`,
|
|
`CREATE TABLE stock_transfers (
|
|
id INTEGER PRIMARY KEY,
|
|
from_warehouse_id INTEGER NULL,
|
|
to_warehouse_id INTEGER NULL,
|
|
transfer_date TIMESTAMP NULL,
|
|
movement_number TEXT NULL,
|
|
reason TEXT NULL
|
|
)`,
|
|
`CREATE TABLE stock_transfer_details (
|
|
id INTEGER PRIMARY KEY,
|
|
stock_transfer_id INTEGER NOT NULL,
|
|
product_id INTEGER NOT NULL,
|
|
dest_product_warehouse_id INTEGER NULL,
|
|
source_product_warehouse_id INTEGER NULL,
|
|
total_qty NUMERIC(15,3) NOT NULL DEFAULT 0,
|
|
usage_qty NUMERIC(15,3) NOT NULL DEFAULT 0
|
|
)`,
|
|
`CREATE TABLE adjustment_stocks (
|
|
id INTEGER PRIMARY KEY,
|
|
product_warehouse_id INTEGER NOT NULL,
|
|
total_qty NUMERIC(15,3) NOT NULL DEFAULT 0,
|
|
usage_qty NUMERIC(15,3) NOT NULL DEFAULT 0,
|
|
adj_number TEXT NULL,
|
|
created_at TIMESTAMP NULL
|
|
)`,
|
|
}
|
|
|
|
for _, stmt := range statements {
|
|
if err := db.Exec(stmt).Error; err != nil {
|
|
t.Fatalf("failed preparing schema: %v", err)
|
|
}
|
|
}
|
|
|
|
return db
|
|
}
|