Merge branch 'dev/ragil' of https://gitlab.com/mbugroup/lti-api into dev/teguh

This commit is contained in:
aguhh18
2025-11-28 15:25:52 +07:00
63 changed files with 859 additions and 881 deletions
@@ -2,42 +2,42 @@
CREATE TABLE users ( CREATE TABLE users (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
id_user BIGINT NOT NULL, id_user BIGINT NOT NULL,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
email VARCHAR NOT NULL, email VARCHAR(50) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ deleted_at TIMESTAMPTZ
); );
CREATE UNIQUE INDEX users_id_user_unique ON users (id_user) WHERE deleted_at IS NULL; CREATE UNIQUE INDEX users_id_user_unique ON users (id_user)
WHERE
deleted_at IS NULL;
CREATE UNIQUE INDEX users_email_unique ON users (email) WHERE deleted_at IS NULL; CREATE UNIQUE INDEX users_email_unique ON users (email)
WHERE
deleted_at IS NULL;
-- FLAGS -- FLAGS
CREATE TABLE flags ( CREATE TABLE flags (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
flagable_id BIGINT NOT NULL, flagable_id BIGINT NOT NULL,
flagable_type VARCHAR(50) NOT NULL, flagable_type VARCHAR(50) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW() updated_at TIMESTAMPTZ DEFAULT NOW ()
); );
CREATE UNIQUE INDEX flags_unique_flagable ON flags ( CREATE UNIQUE INDEX flags_unique_flagable ON flags (name, flagable_id, flagable_type);
name,
flagable_id,
flagable_type
);
CREATE INDEX flags_flagable_lookup ON flags (flagable_type, flagable_id); CREATE INDEX flags_flagable_lookup ON flags (flagable_type, flagable_id);
-- PRODUCT CATEGORIES -- PRODUCT CATEGORIES
CREATE TABLE product_categories ( CREATE TABLE product_categories (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
code VARCHAR(10) NOT NULL, code VARCHAR(10) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -53,9 +53,9 @@ WHERE
-- UOM -- UOM
CREATE TABLE uoms ( CREATE TABLE uoms (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -67,12 +67,12 @@ WHERE
-- BANKS -- BANKS
CREATE TABLE banks ( CREATE TABLE banks (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
alias VARCHAR(5) NOT NULL, alias VARCHAR(5) NOT NULL,
owner VARCHAR, owner VARCHAR(50),
account_number VARCHAR(50) NOT NULL, account_number VARCHAR(50) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -84,9 +84,9 @@ WHERE
-- AREAS -- AREAS
CREATE TABLE areas ( CREATE TABLE areas (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -98,11 +98,11 @@ WHERE
-- LOCATIONS -- LOCATIONS
CREATE TABLE locations ( CREATE TABLE locations (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
address TEXT NOT NULL, address TEXT NOT NULL,
area_id BIGINT NOT NULL REFERENCES areas (id) ON DELETE RESTRICT ON UPDATE CASCADE, area_id BIGINT NOT NULL REFERENCES areas (id) ON DELETE RESTRICT ON UPDATE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -114,11 +114,11 @@ WHERE
-- KANDANG -- KANDANG
CREATE TABLE kandangs ( CREATE TABLE kandangs (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
location_id BIGINT NOT NULL REFERENCES locations (id) ON DELETE RESTRICT ON UPDATE CASCADE, location_id BIGINT NOT NULL REFERENCES locations (id) ON DELETE RESTRICT ON UPDATE CASCADE,
pic_id BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE, pic_id BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -130,13 +130,13 @@ WHERE
-- WAREHOUSES -- WAREHOUSES
CREATE TABLE warehouses ( CREATE TABLE warehouses (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
type VARCHAR(50) NOT NULL, type VARCHAR(50) NOT NULL,
area_id BIGINT NOT NULL REFERENCES areas (id) ON DELETE RESTRICT ON UPDATE CASCADE, area_id BIGINT NOT NULL REFERENCES areas (id) ON DELETE RESTRICT ON UPDATE CASCADE,
location_id BIGINT REFERENCES locations (id) ON DELETE SET NULL ON UPDATE CASCADE, location_id BIGINT REFERENCES locations (id) ON DELETE SET NULL ON UPDATE CASCADE,
kandang_id BIGINT REFERENCES kandangs (id) ON DELETE SET NULL ON UPDATE CASCADE, kandang_id BIGINT REFERENCES kandangs (id) ON DELETE SET NULL ON UPDATE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -148,16 +148,16 @@ WHERE
-- CUSTOMERS -- CUSTOMERS
CREATE TABLE customers ( CREATE TABLE customers (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
pic_id BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE, pic_id BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE,
type VARCHAR(50) NOT NULL, type VARCHAR(50) NOT NULL,
address TEXT NOT NULL, address TEXT NOT NULL,
phone VARCHAR(20) NOT NULL, phone VARCHAR(20) NOT NULL,
email VARCHAR NOT NULL, email VARCHAR(50) NOT NULL,
account_number VARCHAR(50) NOT NULL, account_number VARCHAR(50) NOT NULL,
balance NUMERIC(15, 3) DEFAULT 0, balance NUMERIC(15, 3) DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -169,10 +169,10 @@ WHERE
-- NONSTOCK -- NONSTOCK
CREATE TABLE nonstocks ( CREATE TABLE nonstocks (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
uom_id BIGINT NOT NULL REFERENCES uoms (id) ON DELETE RESTRICT ON UPDATE CASCADE, uom_id BIGINT NOT NULL REFERENCES uoms (id) ON DELETE RESTRICT ON UPDATE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -184,9 +184,9 @@ WHERE
-- FCR -- FCR
CREATE TABLE fcrs ( CREATE TABLE fcrs (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -201,29 +201,29 @@ CREATE TABLE fcr_standards (
weight NUMERIC(15, 3) NOT NULL, weight NUMERIC(15, 3) NOT NULL,
fcr_number NUMERIC(15, 3) NOT NULL, fcr_number NUMERIC(15, 3) NOT NULL,
mortality NUMERIC(15, 3) NOT NULL, mortality NUMERIC(15, 3) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ deleted_at TIMESTAMPTZ
); );
-- SUPPLIERS -- SUPPLIERS
CREATE TABLE suppliers ( CREATE TABLE suppliers (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
alias VARCHAR(5) NOT NULL, alias VARCHAR(5) NOT NULL,
pic VARCHAR NOT NULL, pic VARCHAR(50) NOT NULL,
type VARCHAR(50) NOT NULL, type VARCHAR(50) NOT NULL,
category VARCHAR(20) NOT NULL, category VARCHAR(20) NOT NULL,
hatchery VARCHAR, hatchery VARCHAR(50),
phone VARCHAR(20) NOT NULL, phone VARCHAR(20) NOT NULL,
email VARCHAR NOT NULL, email VARCHAR(50) NOT NULL,
address TEXT NOT NULL, address TEXT NOT NULL,
npwp VARCHAR(50), npwp VARCHAR(50),
account_number VARCHAR(50), account_number VARCHAR(50),
balance NUMERIC(15, 3) DEFAULT 0, balance NUMERIC(15, 3) DEFAULT 0,
due_date INT NOT NULL, due_date INT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -235,15 +235,15 @@ WHERE
CREATE TABLE nonstock_suppliers ( CREATE TABLE nonstock_suppliers (
nonstock_id BIGINT NOT NULL REFERENCES nonstocks (id) ON DELETE CASCADE ON UPDATE CASCADE, nonstock_id BIGINT NOT NULL REFERENCES nonstocks (id) ON DELETE CASCADE ON UPDATE CASCADE,
supplier_id BIGINT NOT NULL REFERENCES suppliers (id) ON DELETE CASCADE ON UPDATE CASCADE, supplier_id BIGINT NOT NULL REFERENCES suppliers (id) ON DELETE CASCADE ON UPDATE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
PRIMARY KEY (nonstock_id, supplier_id) PRIMARY KEY (nonstock_id, supplier_id)
); );
-- PRODUCTS -- PRODUCTS
CREATE TABLE products ( CREATE TABLE products (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR(50) NOT NULL,
brand VARCHAR NOT NULL, brand VARCHAR(50) NOT NULL,
sku VARCHAR(100), sku VARCHAR(100),
uom_id BIGINT NOT NULL REFERENCES uoms (id) ON DELETE RESTRICT ON UPDATE CASCADE, uom_id BIGINT NOT NULL REFERENCES uoms (id) ON DELETE RESTRICT ON UPDATE CASCADE,
product_category_id BIGINT NOT NULL REFERENCES product_categories (id) ON DELETE RESTRICT ON UPDATE CASCADE, product_category_id BIGINT NOT NULL REFERENCES product_categories (id) ON DELETE RESTRICT ON UPDATE CASCADE,
@@ -251,8 +251,8 @@ CREATE TABLE products (
selling_price NUMERIC(15, 3), selling_price NUMERIC(15, 3),
tax NUMERIC(15, 3), tax NUMERIC(15, 3),
expiry_period INT, expiry_period INT,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -268,15 +268,15 @@ WHERE
CREATE TABLE product_suppliers ( CREATE TABLE product_suppliers (
product_id BIGINT NOT NULL REFERENCES products (id) ON DELETE CASCADE ON UPDATE CASCADE, product_id BIGINT NOT NULL REFERENCES products (id) ON DELETE CASCADE ON UPDATE CASCADE,
supplier_id BIGINT NOT NULL REFERENCES suppliers (id) ON DELETE CASCADE ON UPDATE CASCADE, supplier_id BIGINT NOT NULL REFERENCES suppliers (id) ON DELETE CASCADE ON UPDATE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
PRIMARY KEY (product_id, supplier_id) PRIMARY KEY (product_id, supplier_id)
); );
-- PROJECTS -- PROJECTS
CREATE TABLE projects ( CREATE TABLE projects (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
); );
@@ -288,8 +288,8 @@ CREATE TABLE product_warehouses (
warehouse_id BIGINT NOT NULL REFERENCES warehouses (id), warehouse_id BIGINT NOT NULL REFERENCES warehouses (id),
quantity INTEGER NOT NULL DEFAULT 0, quantity INTEGER NOT NULL DEFAULT 0,
created_by BIGINT NOT NULL REFERENCES users (id), created_by BIGINT NOT NULL REFERENCES users (id),
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ deleted_at TIMESTAMPTZ
); );
@@ -316,8 +316,8 @@ CREATE TABLE stock_logs (
note TEXT, note TEXT,
product_warehouse_id BIGINT NOT NULL REFERENCES product_warehouses (id) ON DELETE CASCADE ON UPDATE CASCADE, product_warehouse_id BIGINT NOT NULL REFERENCES product_warehouses (id) ON DELETE CASCADE ON UPDATE CASCADE,
created_by BIGINT NOT NULL REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE, created_by BIGINT NOT NULL REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW (),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW (),
deleted_at TIMESTAMPTZ deleted_at TIMESTAMPTZ
); );
@@ -330,4 +330,4 @@ CREATE INDEX stock_logs_created_by_idx ON stock_logs (created_by);
CREATE INDEX stock_logs_created_at_idx ON stock_logs (created_at); CREATE INDEX stock_logs_created_at_idx ON stock_logs (created_at);
CREATE INDEX stock_logs_deleted_at_idx ON stock_logs (deleted_at); CREATE INDEX stock_logs_deleted_at_idx ON stock_logs (deleted_at);
+1 -1
View File
@@ -8,7 +8,7 @@ import (
type Area struct { type Area struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:areas_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:areas_name_unique,where:deleted_at IS NULL"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"` UpdatedAt time.Time `gorm:"autoUpdateTime"`
+2 -2
View File
@@ -8,9 +8,9 @@ import (
type Bank struct { type Bank struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:banks_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:banks_name_unique,where:deleted_at IS NULL"`
Alias string `gorm:"not null;size:5"` Alias string `gorm:"not null;size:5"`
Owner *string `gorm:""` Owner *string `gorm:"type:varchar(50)"`
AccountNumber string `gorm:"not null;size:50"` AccountNumber string `gorm:"not null;size:50"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
+2 -2
View File
@@ -8,12 +8,12 @@ import (
type Customer struct { type Customer struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:customers_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:customers_name_unique,where:deleted_at IS NULL"`
PicId uint `gorm:"not null"` PicId uint `gorm:"not null"`
Type string `gorm:"not null;size:50"` Type string `gorm:"not null;size:50"`
Address string `gorm:"not null"` Address string `gorm:"not null"`
Phone string `gorm:"not null;size:20"` Phone string `gorm:"not null;size:20"`
Email string `gorm:"not null"` Email string `gorm:"type:varchar(50);not null"`
AccountNumber string `gorm:"not null;size:50"` AccountNumber string `gorm:"not null;size:50"`
Balance float64 `gorm:"default:0"` Balance float64 `gorm:"default:0"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
+1 -1
View File
@@ -8,7 +8,7 @@ import (
type Fcr struct { type Fcr struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:idx_suppliers_name,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:idx_suppliers_name,where:deleted_at IS NULL"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"` UpdatedAt time.Time `gorm:"autoUpdateTime"`
+1 -1
View File
@@ -9,7 +9,7 @@ const (
type Flag struct { type Flag struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:flags_unique_flagable"` Name string `gorm:"type:varchar(50);size:50;not null;uniqueIndex:flags_unique_flagable"`
FlagableID uint `gorm:"not null;uniqueIndex:flags_unique_flagable;index:flags_flagable_lookup,priority:2"` FlagableID uint `gorm:"not null;uniqueIndex:flags_unique_flagable;index:flags_flagable_lookup,priority:2"`
FlagableType string `gorm:"size:50;not null;uniqueIndex:flags_unique_flagable;index:flags_flagable_lookup,priority:1"` FlagableType string `gorm:"size:50;not null;uniqueIndex:flags_unique_flagable;index:flags_flagable_lookup,priority:1"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
+1 -1
View File
@@ -8,7 +8,7 @@ import (
type Kandang struct { type Kandang struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:kandangs_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:kandangs_name_unique,where:deleted_at IS NULL"`
Status string `gorm:"type:varchar(50);not null"` Status string `gorm:"type:varchar(50);not null"`
LocationId uint `gorm:"not null"` LocationId uint `gorm:"not null"`
Capacity float64 `gorm:"not null"` Capacity float64 `gorm:"not null"`
+1 -1
View File
@@ -8,7 +8,7 @@ import (
type Location struct { type Location struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:locations_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:locations_name_unique,where:deleted_at IS NULL"`
Address string `gorm:"not null"` Address string `gorm:"not null"`
AreaId uint `gorm:"not null"` AreaId uint `gorm:"not null"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
+1 -1
View File
@@ -8,7 +8,7 @@ import (
type Nonstock struct { type Nonstock struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:nonstocks_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:nonstocks_name_unique,where:deleted_at IS NULL"`
UomId uint `gorm:"not null"` UomId uint `gorm:"not null"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
+1 -1
View File
@@ -8,7 +8,7 @@ import (
type ProductCategory struct { type ProductCategory struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:product_categories_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:product_categories_name_unique,where:deleted_at IS NULL"`
Code string `gorm:"not null;size:10;uniqueIndex:product_categories_code_unique,where:deleted_at IS NULL"` Code string `gorm:"not null;size:10;uniqueIndex:product_categories_code_unique,where:deleted_at IS NULL"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
+2 -2
View File
@@ -8,8 +8,8 @@ import (
type Product struct { type Product struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:products_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:products_name_unique,where:deleted_at IS NULL"`
Brand string `gorm:"not null"` Brand string `gorm:"type:varchar(50);not null"`
Sku *string `gorm:"size:100;uniqueIndex:products_sku_unique,where:deleted_at IS NULL"` Sku *string `gorm:"size:100;uniqueIndex:products_sku_unique,where:deleted_at IS NULL"`
UomId uint `gorm:"not null"` UomId uint `gorm:"not null"`
ProductCategoryId uint `gorm:"not null"` ProductCategoryId uint `gorm:"not null"`
+3 -3
View File
@@ -5,11 +5,11 @@ import (
) )
type Purchase struct { type Purchase struct {
Id uint64 `gorm:"primaryKey;autoIncrement"` Id uint `gorm:"primaryKey;autoIncrement"`
PrNumber string `gorm:"not null"` PrNumber string `gorm:"not null"`
PoNumber *string PoNumber *string
PoDate *time.Time PoDate *time.Time
SupplierId uint64 `gorm:"not null"` SupplierId uint `gorm:"not null"`
CreditTerm *int CreditTerm *int
DueDate *time.Time DueDate *time.Time
GrandTotal float64 `gorm:"type:numeric(15,3);default:0"` GrandTotal float64 `gorm:"type:numeric(15,3);default:0"`
@@ -17,7 +17,7 @@ type Purchase struct {
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"` UpdatedAt time.Time `gorm:"autoUpdateTime"`
DeletedAt *time.Time `gorm:"index"` DeletedAt *time.Time `gorm:"index"`
CreatedBy uint64 `gorm:"not null"` CreatedBy uint `gorm:"not null"`
// Relations // Relations
Supplier Supplier `gorm:"foreignKey:SupplierId;references:Id"` Supplier Supplier `gorm:"foreignKey:SupplierId;references:Id"`
+5 -5
View File
@@ -5,11 +5,11 @@ import (
) )
type PurchaseItem struct { type PurchaseItem struct {
Id uint64 `gorm:"primaryKey;autoIncrement"` Id uint `gorm:"primaryKey;autoIncrement"`
PurchaseId uint64 `gorm:"not null"` PurchaseId uint `gorm:"not null"`
ProductId uint64 `gorm:"not null"` ProductId uint `gorm:"not null"`
WarehouseId uint64 `gorm:"not null"` WarehouseId uint `gorm:"not null"`
ProductWarehouseId *uint64 ProductWarehouseId *uint
ReceivedDate *time.Time ReceivedDate *time.Time
TravelNumber *string TravelNumber *string
TravelNumberDocs *string TravelNumberDocs *string
+4 -4
View File
@@ -8,14 +8,14 @@ import (
type Supplier struct { type Supplier struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:suppliers_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:suppliers_name_unique,where:deleted_at IS NULL"`
Alias string `gorm:"not null;size:5"` Alias string `gorm:"not null;size:5"`
Pic string `gorm:"not null"` Pic string `gorm:"type:varchar(50);not null"`
Type string `gorm:"not null;size:50"` Type string `gorm:"not null;size:50"`
Category string `gorm:"not null;size:20"` Category string `gorm:"not null;size:20"`
Hatchery *string `gorm:"size:255"` Hatchery *string `gorm:"type:varchar(50)"`
Phone string `gorm:"not null;size:20"` Phone string `gorm:"not null;size:20"`
Email string `gorm:"not null"` Email string `gorm:"type:varchar(50);not null"`
Address string `gorm:"not null"` Address string `gorm:"not null"`
Npwp *string `gorm:"size:50"` Npwp *string `gorm:"size:50"`
AccountNumber *string `gorm:"size:50"` AccountNumber *string `gorm:"size:50"`
+1 -1
View File
@@ -8,7 +8,7 @@ import (
type Uom struct { type Uom struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null;uniqueIndex:uoms_name_unique,where:deleted_at IS NULL"` Name string `gorm:"type:varchar(50);not null;uniqueIndex:uoms_name_unique,where:deleted_at IS NULL"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"` UpdatedAt time.Time `gorm:"autoUpdateTime"`
+2 -2
View File
@@ -9,8 +9,8 @@ import (
type User struct { type User struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
IdUser int64 `gorm:"uniqueIndex"` IdUser int64 `gorm:"uniqueIndex"`
Email string `gorm:"uniqueIndex"` Email string `gorm:"type:varchar(50);uniqueIndex"`
Name string `gorm:"not null"` Name string `gorm:"type:varchar(50);not null"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"` UpdatedAt time.Time `gorm:"autoUpdateTime"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
+1 -1
View File
@@ -8,7 +8,7 @@ import (
type Warehouse struct { type Warehouse struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null"` Name string `gorm:"type:varchar(50);not null"`
Type string `gorm:"not null"` Type string `gorm:"not null"`
AreaId uint `gorm:"not null"` AreaId uint `gorm:"not null"`
LocationId *uint LocationId *uint
+8
View File
@@ -105,6 +105,14 @@ func AuthenticatedUser(c *fiber.Ctx) (*entity.User, bool) {
return nil, false return nil, false
} }
func ActorIDFromContext(c *fiber.Ctx) (uint, error) {
user, ok := AuthenticatedUser(c)
if !ok || user == nil || user.Id == 0 {
return 0, fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
}
return user.Id, nil
}
// AuthDetails returns the full authentication context (token, claims, user). // AuthDetails returns the full authentication context (token, claims, user).
func AuthDetails(c *fiber.Ctx) (*AuthContext, bool) { func AuthDetails(c *fiber.Ctx) (*AuthContext, bool) {
value := c.Locals(authContextLocalsKey) value := c.Locals(authContextLocalsKey)
+2 -2
View File
@@ -3,7 +3,7 @@ package approvals
import ( import (
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware" // m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
common "gitlab.com/mbugroup/lti-api.git/internal/common/service" common "gitlab.com/mbugroup/lti-api.git/internal/common/service"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/controllers"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -12,8 +12,8 @@ import (
func ApprovalRoutes(v1 fiber.Router, u user.UserService, s common.ApprovalService) { func ApprovalRoutes(v1 fiber.Router, u user.UserService, s common.ApprovalService) {
_ = u _ = u
ctrl := controller.NewApprovalController(s) ctrl := controller.NewApprovalController(s)
route := v1.Group("/approvals") route := v1.Group("/approvals")
route.Use(m.Auth(u))
route.Get("/", ctrl.GetAll) route.Get("/", ctrl.GetAll)
} }
+2 -2
View File
@@ -1,7 +1,7 @@
package expenses package expenses
import ( import (
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware" m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/controllers"
expense "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/services" expense "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,7 +13,7 @@ func ExpenseRoutes(v1 fiber.Router, u user.UserService, s expense.ExpenseService
ctrl := controller.NewExpenseController(s) ctrl := controller.NewExpenseController(s)
route := v1.Group("/expenses") route := v1.Group("/expenses")
route.Use(m.Auth(u))
// route.Get("/", m.Auth(u), ctrl.GetAll) // route.Get("/", m.Auth(u), ctrl.GetAll)
// route.Post("/", m.Auth(u), ctrl.CreateOne) // route.Post("/", m.Auth(u), ctrl.CreateOne)
// route.Get("/:id", m.Auth(u), ctrl.GetOne) // route.Get("/:id", m.Auth(u), ctrl.GetOne)
@@ -5,8 +5,8 @@ import (
"strings" "strings"
common "gitlab.com/mbugroup/lti-api.git/internal/common/service" common "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/validations" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/validations"
ProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories" ProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
productRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/repositories" productRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/repositories"
@@ -78,7 +78,10 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
return nil, err return nil, err
} }
ctx := c.Context() ctx := c.Context()
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
if err := common.EnsureRelations(c.Context(), if err := common.EnsureRelations(c.Context(),
common.RelationCheck{Name: "Product", ID: &req.ProductID, Exists: s.ProductRepo.IdExists}, common.RelationCheck{Name: "Product", ID: &req.ProductID, Exists: s.ProductRepo.IdExists},
common.RelationCheck{Name: "Warehouse", ID: &req.WarehouseID, Exists: s.WarehouseRepo.IdExists}, common.RelationCheck{Name: "Warehouse", ID: &req.WarehouseID, Exists: s.WarehouseRepo.IdExists},
@@ -107,7 +110,7 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
ProductId: uint(req.ProductID), ProductId: uint(req.ProductID),
WarehouseId: uint(req.WarehouseID), WarehouseId: uint(req.WarehouseID),
Quantity: 0, Quantity: 0,
CreatedBy: 1, // TODO: should Get from auth middleware CreatedBy: actorID,
} }
if err := s.ProductWarehouseRepo.CreateOne(ctx, newPW, nil); err != nil { if err := s.ProductWarehouseRepo.CreateOne(ctx, newPW, nil); err != nil {
@@ -143,7 +146,7 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
LogId: 0, LogId: 0,
Note: req.Note, Note: req.Note,
ProductWarehouseId: productWarehouse.Id, ProductWarehouseId: productWarehouse.Id,
CreatedBy: 1, // TODO: should Get from auth middleware CreatedBy: actorID,
} }
if err := s.StockLogsRepository.WithTx(tx).CreateOne(ctx, newLog, nil); err != nil { if err := s.StockLogsRepository.WithTx(tx).CreateOne(ctx, newLog, nil); err != nil {
@@ -27,7 +27,7 @@ type ProductWarehouseRepository interface {
GetDetailByID(ctx context.Context, id uint) (*entity.ProductWarehouse, error) GetDetailByID(ctx context.Context, id uint) (*entity.ProductWarehouse, error)
IdExists(ctx context.Context, id uint) (bool, error) IdExists(ctx context.Context, id uint) (bool, error)
CleanupEmpty(ctx context.Context, affected map[uint]struct{}) error CleanupEmpty(ctx context.Context, affected map[uint]struct{}) error
EnsureProductWarehouse(ctx context.Context, productID, warehouseID uint, createdBy uint64) (uint, error) EnsureProductWarehouse(ctx context.Context, productID, warehouseID uint, createdBy uint) (uint, error)
} }
type ProductWarehouseRepositoryImpl struct { type ProductWarehouseRepositoryImpl struct {
@@ -199,7 +199,7 @@ func (r *ProductWarehouseRepositoryImpl) EnsureProductWarehouse(
ctx context.Context, ctx context.Context,
productID uint, productID uint,
warehouseID uint, warehouseID uint,
createdBy uint64, createdBy uint,
) (uint, error) { ) (uint, error) {
record, err := r.GetProductWarehouseByProductAndWarehouseID(ctx, productID, warehouseID) record, err := r.GetProductWarehouseByProductAndWarehouseID(ctx, productID, warehouseID)
if err == nil { if err == nil {
@@ -3,15 +3,15 @@ package service
import ( import (
"errors" "errors"
"fmt" "fmt"
"strings"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories" rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
rStockTransfer "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/transfers/repositories" rStockTransfer "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/transfers/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/transfers/validations" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/transfers/validations"
rSupplier "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/repositories" rSupplier "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/repositories"
rStockLogs "gitlab.com/mbugroup/lti-api.git/internal/modules/shared/repositories" rStockLogs "gitlab.com/mbugroup/lti-api.git/internal/modules/shared/repositories"
"gitlab.com/mbugroup/lti-api.git/internal/utils" "gitlab.com/mbugroup/lti-api.git/internal/utils"
"strings"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
@@ -127,6 +127,10 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Stok produk %d di gudang asal tidak cukup", product.ProductID)) return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Stok produk %d di gudang asal tidak cukup", product.ProductID))
} }
} }
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
// validasi total qty harus lebih besar dari atau sama dengan total qty di delivery compare berdasarkan productid // validasi total qty harus lebih besar dari atau sama dengan total qty di delivery compare berdasarkan productid
deliveryQtyMap := make(map[uint]float64) deliveryQtyMap := make(map[uint]float64)
@@ -174,7 +178,7 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
Reason: req.TransferReason, Reason: req.TransferReason,
TransferDate: transferDate, TransferDate: transferDate,
MovementNumber: movementNumber, MovementNumber: movementNumber,
CreatedBy: 1, //todo: get from token CreatedBy: uint64(actorID),
} }
// Save the transfer entity to the database // Save the transfer entity to the database
@@ -277,7 +281,7 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
LogId: uint(entityTransfer.Id), LogId: uint(entityTransfer.Id),
Note: "", Note: "",
ProductWarehouseId: sourcePW.Id, ProductWarehouseId: sourcePW.Id,
CreatedBy: 1, CreatedBy: actorID,
} }
if err := s.StockLogsRepository.WithTx(tx).CreateOne(c.Context(), decreaseLog, nil); err != nil { if err := s.StockLogsRepository.WithTx(tx).CreateOne(c.Context(), decreaseLog, nil); err != nil {
s.Log.Errorf("Failed to create stock log decrease: %+v", err) s.Log.Errorf("Failed to create stock log decrease: %+v", err)
@@ -298,7 +302,7 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
ProductId: uint(product.ProductID), ProductId: uint(product.ProductID),
WarehouseId: uint(req.DestinationWarehouseID), WarehouseId: uint(req.DestinationWarehouseID),
Quantity: 0, Quantity: 0,
CreatedBy: 1, // TODO: should Get from auth middleware CreatedBy: actorID,
} }
if err := s.ProductWarehouseRepo.WithTx(tx).CreateOne(c.Context(), destPW, nil); err != nil { if err := s.ProductWarehouseRepo.WithTx(tx).CreateOne(c.Context(), destPW, nil); err != nil {
s.Log.Errorf("Failed to create destination product warehouse: %+v", err) s.Log.Errorf("Failed to create destination product warehouse: %+v", err)
@@ -325,7 +329,7 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
LogId: uint(entityTransfer.Id), LogId: uint(entityTransfer.Id),
Note: "", Note: "",
ProductWarehouseId: destPW.Id, ProductWarehouseId: destPW.Id,
CreatedBy: 1, CreatedBy: actorID,
} }
if err := s.StockLogsRepository.WithTx(tx).CreateOne(c.Context(), increaseLog, nil); err != nil { if err := s.StockLogsRepository.WithTx(tx).CreateOne(c.Context(), increaseLog, nil); err != nil {
s.Log.Errorf("Failed to create stock log increase: %+v", err) s.Log.Errorf("Failed to create stock log increase: %+v", err)
@@ -8,6 +8,7 @@ import (
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
marketingDeliveryProductRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/marketing-delivery-products/repositories" marketingDeliveryProductRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/marketing-delivery-products/repositories"
productWarehouseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories" productWarehouseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
@@ -175,6 +176,11 @@ func (s *deliveryOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create)
return nil, err return nil, err
} }
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(s.MarketingRepo.DB())) approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(s.MarketingRepo.DB()))
latestApproval, err := approvalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowMarketing, req.MarketingId, nil) latestApproval, err := approvalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowMarketing, req.MarketingId, nil)
@@ -253,7 +259,7 @@ func (s *deliveryOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create)
} }
actorID := uint(1) // TODO: ambil dari auth context
approvalAction := entity.ApprovalActionApproved approvalAction := entity.ApprovalActionApproved
if _, err := approvalSvcTx.CreateApproval( if _, err := approvalSvcTx.CreateApproval(
c.Context(), c.Context(),
@@ -9,6 +9,7 @@ import (
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
rInvMarketingDeliveryProduct "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/marketing-delivery-products/repositories" rInvMarketingDeliveryProduct "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/marketing-delivery-products/repositories"
productWarehouseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories" productWarehouseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
@@ -90,6 +91,11 @@ func (s *salesOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create) (*e
return nil, err return nil, err
} }
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
if err := commonSvc.EnsureRelations(c.Context(), if err := commonSvc.EnsureRelations(c.Context(),
commonSvc.RelationCheck{Name: "Customer", ID: &req.CustomerId, Exists: s.CustomerRepo.IdExists}, commonSvc.RelationCheck{Name: "Customer", ID: &req.CustomerId, Exists: s.CustomerRepo.IdExists},
); err != nil { ); err != nil {
@@ -128,7 +134,7 @@ func (s *salesOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create) (*e
SoDate: soDate, SoDate: soDate,
SalesPersonId: req.SalesPersonId, SalesPersonId: req.SalesPersonId,
Notes: req.Notes, Notes: req.Notes,
CreatedBy: 1, CreatedBy: actorID,
} }
if err := marketingRepoTx.CreateOne(c.Context(), marketing, nil); err != nil { if err := marketingRepoTx.CreateOne(c.Context(), marketing, nil); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create salesOrders") return fiber.NewError(fiber.StatusInternalServerError, "Failed to create salesOrders")
@@ -142,7 +148,6 @@ func (s *salesOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create) (*e
} }
} }
actorID := uint(1) // TODO: ambil dari auth context
approvalAction := entity.ApprovalActionCreated approvalAction := entity.ApprovalActionCreated
if _, err := approvalSvcTx.CreateApproval( if _, err := approvalSvcTx.CreateApproval(
c.Context(), c.Context(),
@@ -179,6 +184,11 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
return nil, err return nil, err
} }
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
if err := commonSvc.EnsureRelations(c.Context(), if err := commonSvc.EnsureRelations(c.Context(),
commonSvc.RelationCheck{Name: "Marketing", ID: &id, Exists: s.MarketingRepo.IdExists}, commonSvc.RelationCheck{Name: "Marketing", ID: &id, Exists: s.MarketingRepo.IdExists},
commonSvc.RelationCheck{Name: "Customer", ID: &req.CustomerId, Exists: s.CustomerRepo.IdExists}, commonSvc.RelationCheck{Name: "Customer", ID: &req.CustomerId, Exists: s.CustomerRepo.IdExists},
@@ -320,21 +330,18 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
} }
} }
if latestApproval != nil { if latestApproval != nil {
if *latestApproval.Action != entity.ApprovalActionUpdated { action := entity.ApprovalActionUpdated
actorID := uint(1) // todo: ambil dari auth context _, err := approvalSvcTx.CreateApproval(
action := entity.ApprovalActionUpdated c.Context(),
_, err := approvalSvcTx.CreateApproval( utils.ApprovalWorkflowMarketing,
c.Context(), id,
utils.ApprovalWorkflowMarketing, approvalutils.ApprovalStep(latestApproval.StepNumber),
id, &action,
utils.MarketingStepPengajuan, actorID,
&action, nil)
actorID, if err != nil {
nil) if !errors.Is(err, gorm.ErrDuplicatedKey) {
if err != nil { return fiber.NewError(fiber.StatusInternalServerError, "Failed to create update approval")
if !errors.Is(err, gorm.ErrDuplicatedKey) {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create update approval")
}
} }
} }
@@ -407,6 +414,11 @@ func (s salesOrdersService) Approval(c *fiber.Ctx, req *validation.Approve) ([]e
return nil, err return nil, err
} }
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(s.MarketingRepo.DB())) approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(s.MarketingRepo.DB()))
var action entity.ApprovalAction var action entity.ApprovalAction
@@ -450,7 +462,7 @@ func (s salesOrdersService) Approval(c *fiber.Ctx, req *validation.Approve) ([]e
} }
} }
err := s.MarketingRepo.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error { err = s.MarketingRepo.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction)) approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
@@ -481,7 +493,6 @@ func (s salesOrdersService) Approval(c *fiber.Ctx, req *validation.Approve) ([]e
nextStep = approvalutils.ApprovalStep(currentStep) nextStep = approvalutils.ApprovalStep(currentStep)
} }
actorID := uint(1) // todo ambil dari auth context
if _, err := approvalSvc.CreateApproval( if _, err := approvalSvc.CreateApproval(
c.Context(), c.Context(),
utils.ApprovalWorkflowMarketing, utils.ApprovalWorkflowMarketing,
@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/repositories" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/validations" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils" "gitlab.com/mbugroup/lti-api.git/internal/utils"
@@ -87,10 +88,14 @@ func (s *areaService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entity.A
return nil, fiber.NewError(fiber.StatusConflict, fmt.Sprintf("Area with name %s already exists", req.Name)) return nil, fiber.NewError(fiber.StatusConflict, fmt.Sprintf("Area with name %s already exists", req.Name))
} }
//TODO: created by dummy actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
createBody := &entity.Area{ createBody := &entity.Area{
Name: req.Name, Name: req.Name,
CreatedBy: 1, CreatedBy: actorID,
} }
if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil { if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil {
@@ -1,11 +1,11 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty"` Name *string `json:"name,omitempty" validate:"omitempty,max=50"`
} }
type Query struct { type Query struct {
@@ -1,16 +1,16 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
Alias string `json:"alias" validate:"required_strict"` Alias string `json:"alias" validate:"required_strict,max=5"`
Owner *string `json:"owner,omitempty" validate:"omitempty"` Owner *string `json:"owner,omitempty" validate:"omitempty,max=50"`
AccountNumber string `json:"account_number" validate:"required_strict,max=50"` AccountNumber string `json:"account_number" validate:"required_strict,max=50"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty"` Name *string `json:"name,omitempty" validate:"omitempty,max=50"`
Alias *string `json:"alias,omitempty" validate:"omitempty"` Alias *string `json:"alias,omitempty" validate:"omitempty,max=5"`
Owner *string `json:"owner,omitempty" validate:"omitempty"` Owner *string `json:"owner,omitempty" validate:"omitempty,max=50"`
AccountNumber *string `json:"account_number,omitempty" validate:"omitempty,max=50"` AccountNumber *string `json:"account_number,omitempty" validate:"omitempty,max=50"`
} }
@@ -3,13 +3,13 @@ package service
import ( import (
"errors" "errors"
"fmt" "fmt"
"strings"
common "gitlab.com/mbugroup/lti-api.git/internal/common/service" common "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/customers/repositories" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/customers/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/customers/validations" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/customers/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils" "gitlab.com/mbugroup/lti-api.git/internal/utils"
"strings"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
@@ -81,6 +81,10 @@ func (s *customerService) CreateOne(c *fiber.Ctx, req *validation.Create) (*enti
if err := s.Validate.Struct(req); err != nil { if err := s.Validate.Struct(req); err != nil {
return nil, err return nil, err
} }
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
if exists, err := s.Repository.NameExists(c.Context(), req.Name, nil); err != nil { if exists, err := s.Repository.NameExists(c.Context(), req.Name, nil); err != nil {
s.Log.Errorf("Failed to check customer name: %+v", err) s.Log.Errorf("Failed to check customer name: %+v", err)
@@ -100,7 +104,6 @@ func (s *customerService) CreateOne(c *fiber.Ctx, req *validation.Create) (*enti
return nil, err return nil, err
} }
//TODO: created by dummy
createBody := &entity.Customer{ createBody := &entity.Customer{
Name: req.Name, Name: req.Name,
PicId: req.PicId, PicId: req.PicId,
@@ -109,7 +112,7 @@ func (s *customerService) CreateOne(c *fiber.Ctx, req *validation.Create) (*enti
Phone: req.Phone, Phone: req.Phone,
Email: req.Email, Email: req.Email,
AccountNumber: req.AccountNumber, AccountNumber: req.AccountNumber,
CreatedBy: 1, CreatedBy: actorID,
} }
if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil { if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil {
@@ -1,23 +1,23 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
PicId uint `json:"pic_id" validate:"required_strict,number,gt=0"` PicId uint `json:"pic_id" validate:"required_strict,number,gt=0"`
Type string `json:"type" validate:"required_strict"` Type string `json:"type" validate:"required_strict,max=50"`
Address string `json:"address" validate:"required_strict"` Address string `json:"address" validate:"required_strict"`
Phone string `json:"phone" validate:"required_strict,max=20"` Phone string `json:"phone" validate:"required_strict,max=20"`
Email string `json:"email" validate:"required_strict,email"` Email string `json:"email" validate:"required_strict,email,max=50"`
AccountNumber string `json:"account_number" validate:"required_strict"` AccountNumber string `json:"account_number" validate:"required_strict,max=50"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty"` Name *string `json:"name,omitempty" validate:"omitempty,max=50"`
PicId *uint `json:"pic_id,omitempty" validate:"omitempty,number,gt=0"` PicId *uint `json:"pic_id,omitempty" validate:"omitempty,number,gt=0"`
Type *string `json:"type,omitempty" validate:"omitempty"` Type *string `json:"type,omitempty" validate:"omitempty,max=50"`
Address *string `json:"address,omitempty" validate:"omitempty"` Address *string `json:"address,omitempty" validate:"omitempty"`
Phone *string `json:"phone,omitempty" validate:"omitempty"` Phone *string `json:"phone,omitempty" validate:"omitempty,max=20"`
Email *string `json:"email,omitempty" validate:"omitempty"` Email *string `json:"email,omitempty" validate:"omitempty,max=50"`
AccountNumber *string `json:"account_number,omitempty" validate:"omitempty"` AccountNumber *string `json:"account_number,omitempty" validate:"omitempty,max=50"`
} }
type Query struct { type Query struct {
+2 -2
View File
@@ -1,7 +1,7 @@
package kandangs package kandangs
import ( import (
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware" m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/controllers"
kandang "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/services" kandang "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,7 +13,7 @@ func KandangRoutes(v1 fiber.Router, u user.UserService, s kandang.KandangService
ctrl := controller.NewKandangController(s) ctrl := controller.NewKandangController(s)
route := v1.Group("/kandangs") route := v1.Group("/kandangs")
// route.Use(m.Auth(u)) route.Use(m.Auth(u))
route.Get("/", ctrl.GetAll) route.Get("/", ctrl.GetAll)
route.Post("/", ctrl.CreateOne) route.Post("/", ctrl.CreateOne)
@@ -3,13 +3,13 @@ package service
import ( import (
"errors" "errors"
"fmt" "fmt"
"strings"
common "gitlab.com/mbugroup/lti-api.git/internal/common/service" common "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/validations" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils" "gitlab.com/mbugroup/lti-api.git/internal/utils"
"strings"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
@@ -130,14 +130,18 @@ func (s *kandangService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit
} }
//TODO: created by dummy actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
createBody := &entity.Kandang{ createBody := &entity.Kandang{
Name: req.Name, Name: req.Name,
LocationId: req.LocationId, LocationId: req.LocationId,
Capacity: req.Capacity, Capacity: req.Capacity,
Status: status, Status: status,
PicId: req.PicId, PicId: req.PicId,
CreatedBy: 1, CreatedBy: actorID,
} }
if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil { if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil {
@@ -1,8 +1,8 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
Status string `json:"status,omitempty" validate:"omitempty,min=3"` Status string `json:"status,omitempty" validate:"omitempty,min=3,max=50"`
Capacity float64 `json:"capacity" validate:"required_strict,gt=0"` Capacity float64 `json:"capacity" validate:"required_strict,gt=0"`
LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"` LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"`
PicId uint `json:"pic_id" validate:"required_strict,number,gt=0"` PicId uint `json:"pic_id" validate:"required_strict,number,gt=0"`
@@ -10,8 +10,8 @@ type Create struct {
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty"` Name *string `json:"name,omitempty" validate:"omitempty,max=50"`
Status *string `json:"status,omitempty" validate:"omitempty,min=3"` Status *string `json:"status,omitempty" validate:"omitempty,min=3,max=50"`
Capacity *float64 `json:"capacity" validate:"omitempty,gt=0"` Capacity *float64 `json:"capacity" validate:"omitempty,gt=0"`
LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"` LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"`
PicId *uint `json:"pic_id,omitempty" validate:"omitempty,number,gt=0"` PicId *uint `json:"pic_id,omitempty" validate:"omitempty,number,gt=0"`
@@ -4,15 +4,15 @@ import (
"errors" "errors"
"fmt" "fmt"
common "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
common "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -97,12 +97,16 @@ func (s *locationService) CreateOne(c *fiber.Ctx, req *validation.Create) (*enti
return nil, err return nil, err
} }
//TODO: created by dummy actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
createBody := &entity.Location{ createBody := &entity.Location{
Name: req.Name, Name: req.Name,
Address: req.Address, Address: req.Address,
AreaId: req.AreaId, AreaId: req.AreaId,
CreatedBy: 1, CreatedBy: actorID,
} }
if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil { if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil {
@@ -1,13 +1,13 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
Address string `json:"address" validate:"required_strict"` Address string `json:"address" validate:"required_strict"`
AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"` AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty"` Name *string `json:"name,omitempty" validate:"omitempty,max=50"`
Address *string `json:"address,omitempty" validate:"omitempty"` Address *string `json:"address,omitempty" validate:"omitempty"`
AreaId *uint `json:"area_id,omitempty" validate:"omitempty,number,gt=0"` AreaId *uint `json:"area_id,omitempty" validate:"omitempty,number,gt=0"`
} }
@@ -1,14 +1,14 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
UomID uint `json:"uom_id" validate:"required,gt=0"` UomID uint `json:"uom_id" validate:"required,gt=0"`
SupplierIDs []uint `json:"supplier_ids,omitempty" validate:"omitempty,dive,gt=0"` SupplierIDs []uint `json:"supplier_ids,omitempty" validate:"omitempty,dive,gt=0"`
Flags []string `json:"flags,omitempty" validate:"omitempty,dive,max=50"` Flags []string `json:"flags,omitempty" validate:"omitempty,dive,max=50"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=3"` Name *string `json:"name,omitempty" validate:"omitempty,min=3,max=50"`
UomID *uint `json:"uom_id,omitempty" validate:"omitempty,gt=0"` UomID *uint `json:"uom_id,omitempty" validate:"omitempty,gt=0"`
SupplierIDs *[]uint `json:"supplier_ids,omitempty" validate:"omitempty,dive,gt=0"` SupplierIDs *[]uint `json:"supplier_ids,omitempty" validate:"omitempty,dive,gt=0"`
Flags *[]string `json:"flags,omitempty" validate:"omitempty,dive,max=50"` Flags *[]string `json:"flags,omitempty" validate:"omitempty,dive,max=50"`
@@ -1,12 +1,12 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
Code string `json:"code" validate:"required_strict,max=10"` Code string `json:"code" validate:"required_strict,max=10"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty"` Name *string `json:"name,omitempty" validate:"omitempty,max=50"`
Code *string `json:"code,omitempty" validate:"omitempty,max=10"` Code *string `json:"code,omitempty" validate:"omitempty,max=10"`
} }
@@ -12,12 +12,13 @@ import (
// === DTO Structs === // === DTO Structs ===
type ProductRelationDTO struct { type ProductRelationDTO struct {
Id uint `json:"id"` Id uint `json:"id"`
Name string `json:"name"` Name string `json:"name"`
ProductPrice float64 `gorm:"type:numeric(15,3);not null"` ProductPrice float64 `gorm:"type:numeric(15,3);not null"`
SellingPrice *float64 `gorm:"type:numeric(15,3)"` SellingPrice *float64 `gorm:"type:numeric(15,3)"`
Uom *uomDTO.UomRelationDTO `json:"uom,omitempty"` Uom *uomDTO.UomRelationDTO `json:"uom,omitempty"`
Flags *[]string `json:"flags,omitempty"` Flags *[]string `json:"flags,omitempty"`
ProductCategory *productCategoryDTO.ProductCategoryRelationDTO `json:"product_category,omitempty"`
} }
type ProductListDTO struct { type ProductListDTO struct {
@@ -55,13 +56,20 @@ func ToProductRelationDTO(e entity.Product) ProductRelationDTO {
uomRef = &mapped uomRef = &mapped
} }
var categoryRef *productCategoryDTO.ProductCategoryRelationDTO
if e.ProductCategory.Id != 0 {
mapped := productCategoryDTO.ToProductCategoryRelationDTO(e.ProductCategory)
categoryRef = &mapped
}
return ProductRelationDTO{ return ProductRelationDTO{
Id: e.Id, Id: e.Id,
Name: e.Name, Name: e.Name,
ProductPrice: e.ProductPrice, ProductPrice: e.ProductPrice,
SellingPrice: e.SellingPrice, SellingPrice: e.SellingPrice,
Flags: &flags, Flags: &flags,
Uom: uomRef, Uom: uomRef,
ProductCategory: categoryRef,
} }
} }
@@ -1,9 +1,9 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
Brand string `json:"brand" validate:"required_strict,min=2"` Brand string `json:"brand" validate:"required_strict,min=2,max=50"`
Sku *string `json:"sku,omitempty" validate:"omitempty"` Sku *string `json:"sku,omitempty" validate:"omitempty,max=100"`
UomID uint `json:"uom_id" validate:"required,gt=0"` UomID uint `json:"uom_id" validate:"required,gt=0"`
ProductCategoryID uint `json:"product_category_id" validate:"required,gt=0"` ProductCategoryID uint `json:"product_category_id" validate:"required,gt=0"`
ProductPrice float64 `json:"product_price" validate:"required"` ProductPrice float64 `json:"product_price" validate:"required"`
+2 -2
View File
@@ -1,7 +1,7 @@
package suppliers package suppliers
import ( import (
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware" m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/controllers"
supplier "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/services" supplier "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,7 +13,7 @@ func SupplierRoutes(v1 fiber.Router, u user.UserService, s supplier.SupplierServ
ctrl := controller.NewSupplierController(s) ctrl := controller.NewSupplierController(s)
route := v1.Group("/suppliers") route := v1.Group("/suppliers")
// route.Use(m.Auth(u)) route.Use(m.Auth(u))
route.Get("/", ctrl.GetAll) route.Get("/", ctrl.GetAll)
route.Post("/", ctrl.CreateOne) route.Post("/", ctrl.CreateOne)
@@ -5,14 +5,14 @@ import (
"fmt" "fmt"
"strings" "strings"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -124,8 +124,10 @@ func (s *supplierService) CreateOne(c *fiber.Ctx, req *validation.Create) (*enti
} }
alias := strings.TrimSpace(strings.ToUpper(req.Alias)) alias := strings.TrimSpace(strings.ToUpper(req.Alias))
actorID, err := m.ActorIDFromContext(c)
//TODO: created by dummy if err != nil {
return nil, err
}
createBody := &entity.Supplier{ createBody := &entity.Supplier{
Name: req.Name, Name: req.Name,
Alias: alias, Alias: alias,
@@ -139,7 +141,7 @@ func (s *supplierService) CreateOne(c *fiber.Ctx, req *validation.Create) (*enti
Npwp: req.Npwp, Npwp: req.Npwp,
AccountNumber: req.AccountNumber, AccountNumber: req.AccountNumber,
DueDate: req.DueDate, DueDate: req.DueDate,
CreatedBy: 1, CreatedBy: actorID,
} }
if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil { if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil {
@@ -1,14 +1,14 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
Alias string `json:"alias" validate:"required_strict,max=5"` Alias string `json:"alias" validate:"required_strict,max=5"`
Pic string `json:"pic" validate:"required_strict"` Pic string `json:"pic" validate:"required_strict,max=50"`
Type string `json:"type" validate:"required_strict"` Type string `json:"type" validate:"required_strict,max=50"`
Category string `json:"category" validate:"required_strict"` Category string `json:"category" validate:"required_strict,max=20"`
Hatchery *string `json:"hatchery,omitempty" validate:"omitempty"` Hatchery *string `json:"hatchery,omitempty" validate:"omitempty,max=50"`
Phone string `json:"phone" validate:"required_strict,max=20"` Phone string `json:"phone" validate:"required_strict,max=20"`
Email string `json:"email" validate:"required_strict,email"` Email string `json:"email" validate:"required_strict,email,max=50"`
Address string `json:"address" validate:"required_strict"` Address string `json:"address" validate:"required_strict"`
Npwp *string `json:"npwp,omitempty" validate:"omitempty,max=50"` Npwp *string `json:"npwp,omitempty" validate:"omitempty,max=50"`
AccountNumber *string `json:"account_number,omitempty" validate:"omitempty,max=50"` AccountNumber *string `json:"account_number,omitempty" validate:"omitempty,max=50"`
@@ -16,14 +16,14 @@ type Create struct {
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=3"` Name *string `json:"name,omitempty" validate:"omitempty,min=3,max=50"`
Alias *string `json:"alias,omitempty" validate:"omitempty,max=5"` Alias *string `json:"alias,omitempty" validate:"omitempty,max=5"`
Pic *string `json:"pic,omitempty" validate:"omitempty"` Pic *string `json:"pic,omitempty" validate:"omitempty,max=50"`
Type *string `json:"type,omitempty" validate:"omitempty"` Type *string `json:"type,omitempty" validate:"omitempty,max=50"`
Category *string `json:"category,omitempty" validate:"omitempty"` Category *string `json:"category,omitempty" validate:"omitempty,max=20"`
Hatchery *string `json:"hatchery,omitempty" validate:"omitempty"` Hatchery *string `json:"hatchery,omitempty" validate:"omitempty,max=50"`
Phone *string `json:"phone,omitempty" validate:"omitempty,max=20"` Phone *string `json:"phone,omitempty" validate:"omitempty,max=20"`
Email *string `json:"email,omitempty" validate:"omitempty,email"` Email *string `json:"email,omitempty" validate:"omitempty,email,max=50"`
Address *string `json:"address,omitempty" validate:"omitempty"` Address *string `json:"address,omitempty" validate:"omitempty"`
Npwp *string `json:"npwp,omitempty" validate:"omitempty,max=50"` Npwp *string `json:"npwp,omitempty" validate:"omitempty,max=50"`
AccountNumber *string `json:"account_number,omitempty" validate:"omitempty,max=50"` AccountNumber *string `json:"account_number,omitempty" validate:"omitempty,max=50"`
@@ -4,14 +4,14 @@ import (
"errors" "errors"
"fmt" "fmt"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -87,10 +87,13 @@ func (s *uomService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entity.Uo
return nil, fiber.NewError(fiber.StatusConflict, fmt.Sprintf("Uom with name %s already exists", req.Name)) return nil, fiber.NewError(fiber.StatusConflict, fmt.Sprintf("Uom with name %s already exists", req.Name))
} }
//TODO: created by dummy actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
createBody := &entity.Uom{ createBody := &entity.Uom{
Name: req.Name, Name: req.Name,
CreatedBy: 1, CreatedBy: actorID,
} }
if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil { if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil {
@@ -1,11 +1,11 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty"` Name *string `json:"name,omitempty" validate:"omitempty,max=50"`
} }
type Query struct { type Query struct {
@@ -17,7 +17,6 @@ type WarehouseRepository interface {
IdExists(ctx context.Context, id uint) (bool, error) IdExists(ctx context.Context, id uint) (bool, error)
GetByKandangID(ctx context.Context, kandangId uint) (*entity.Warehouse, error) GetByKandangID(ctx context.Context, kandangId uint) (*entity.Warehouse, error)
GetLatestByKandangID(ctx context.Context, kandangId uint) (*entity.Warehouse, error) GetLatestByKandangID(ctx context.Context, kandangId uint) (*entity.Warehouse, error)
GetDetailByID(ctx context.Context, id uint) (*entity.Warehouse, error)
} }
type WarehouseRepositoryImpl struct { type WarehouseRepositoryImpl struct {
@@ -63,18 +62,6 @@ func (r *WarehouseRepositoryImpl) GetByKandangID(ctx context.Context, kandangId
return &warehouse, nil return &warehouse, nil
} }
func (r *WarehouseRepositoryImpl) GetDetailByID(ctx context.Context, id uint) (*entity.Warehouse, error) {
var warehouse entity.Warehouse
err := r.db.WithContext(ctx).
Preload("Area").
Preload("Location").
First(&warehouse, id).Error
if err != nil {
return nil, err
}
return &warehouse, nil
}
func (r *WarehouseRepositoryImpl) GetLatestByKandangID(ctx context.Context, kandangId uint) (*entity.Warehouse, error) { func (r *WarehouseRepositoryImpl) GetLatestByKandangID(ctx context.Context, kandangId uint) (*entity.Warehouse, error) {
var warehouse entity.Warehouse var warehouse entity.Warehouse
err := r.db.WithContext(ctx). err := r.db.WithContext(ctx).
@@ -3,13 +3,13 @@ package service
import ( import (
"errors" "errors"
"fmt" "fmt"
"strings"
common "gitlab.com/mbugroup/lti-api.git/internal/common/service" common "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/validations" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils" "gitlab.com/mbugroup/lti-api.git/internal/utils"
"strings"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
@@ -105,13 +105,15 @@ func (s *warehouseService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
); err != nil { ); err != nil {
return nil, err return nil, err
} }
actorID, err := m.ActorIDFromContext(c)
//TODO: created by dummy if err != nil {
return nil, err
}
createBody := &entity.Warehouse{ createBody := &entity.Warehouse{
Name: req.Name, Name: req.Name,
Type: typ, Type: typ,
AreaId: req.AreaId, AreaId: req.AreaId,
CreatedBy: 1, CreatedBy: actorID,
} }
if req.LocationId != nil { if req.LocationId != nil {
createBody.LocationId = req.LocationId createBody.LocationId = req.LocationId
@@ -1,16 +1,16 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
Type string `json:"type" validate:"required_strict"` Type string `json:"type" validate:"required_strict,max=50"`
AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"` AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"`
LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"` LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"`
KandangId *uint `json:"kandang_id,omitempty" validate:"omitempty,number,gt=0"` KandangId *uint `json:"kandang_id,omitempty" validate:"omitempty,number,gt=0"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty"` Name *string `json:"name,omitempty" validate:"omitempty,max=50"`
Type *string `json:"type,omitempty" validate:"omitempty"` Type *string `json:"type,omitempty" validate:"omitempty,max=50"`
AreaId *uint `json:"area_id,omitempty" validate:"omitempty,number,gt=0"` AreaId *uint `json:"area_id,omitempty" validate:"omitempty,number,gt=0"`
LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"` LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"`
KandangId *uint `json:"kandang_id,omitempty" validate:"omitempty,number,gt=0"` KandangId *uint `json:"kandang_id,omitempty" validate:"omitempty,number,gt=0"`
@@ -8,6 +8,7 @@ import (
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories" rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
KandangRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories" KandangRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories"
rWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories" rWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
@@ -125,7 +126,10 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti
category := strings.ToUpper(strings.TrimSpace(projectFlockKandang.ProjectFlock.Category)) category := strings.ToUpper(strings.TrimSpace(projectFlockKandang.ProjectFlock.Category))
actorID := uint(1) // todo nanti ambil dari auth context actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
newChikins := make([]*entity.ProjectChickin, 0) newChikins := make([]*entity.ProjectChickin, 0)
for _, chickinReq := range req.ChickinRequests { for _, chickinReq := range req.ChickinRequests {
@@ -356,6 +360,11 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
return nil, err return nil, err
} }
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(s.Repository.DB())) approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(s.Repository.DB()))
var action entity.ApprovalAction var action entity.ApprovalAction
@@ -397,14 +406,13 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
step = utils.ProjectFlockKandangStepDisetujui step = utils.ProjectFlockKandangStepDisetujui
} }
err := s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error { err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction)) approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
chickinRepoTx := repository.NewChickinRepository(dbTransaction) chickinRepoTx := repository.NewChickinRepository(dbTransaction)
productWarehouseTx := s.ProductWarehouseRepo.WithTx(dbTransaction) productWarehouseTx := s.ProductWarehouseRepo.WithTx(dbTransaction)
for _, approvableID := range approvableIDs { for _, approvableID := range approvableIDs {
actorID := uint(1) // todo nanti ambil dari auth context
if _, err := approvalSvc.CreateApproval( if _, err := approvalSvc.CreateApproval(
c.Context(), c.Context(),
utils.ApprovalWorkflowProjectFlockKandang, utils.ApprovalWorkflowProjectFlockKandang,
@@ -1,7 +1,7 @@
package project_flock_kandangs package project_flock_kandangs
import ( import (
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware" m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/controllers"
projectFlockKandang "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/services" projectFlockKandang "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,7 +13,7 @@ func ProjectFlockKandangRoutes(v1 fiber.Router, u user.UserService, s projectFlo
ctrl := controller.NewProjectFlockKandangController(s) ctrl := controller.NewProjectFlockKandangController(s)
route := v1.Group("/project-flock-kandangs") route := v1.Group("/project-flock-kandangs")
route.Use(m.Auth(u))
// route.Get("/", m.Auth(u), ctrl.GetAll) // route.Get("/", m.Auth(u), ctrl.GetAll)
// route.Post("/", m.Auth(u), ctrl.CreateOne) // route.Post("/", m.Auth(u), ctrl.CreateOne)
// route.Get("/:id", m.Auth(u), ctrl.GetOne) // route.Get("/:id", m.Auth(u), ctrl.GetOne)
@@ -11,7 +11,6 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
type ProjectflockRepository interface { type ProjectflockRepository interface {
repository.BaseRepository[entity.ProjectFlock] repository.BaseRepository[entity.ProjectFlock]
GetAllWithFilters(ctx context.Context, offset, limit int, params *validation.Query) ([]entity.ProjectFlock, int64, error) GetAllWithFilters(ctx context.Context, offset, limit int, params *validation.Query) ([]entity.ProjectFlock, int64, error)
@@ -42,24 +41,23 @@ func NewProjectflockRepository(db *gorm.DB) ProjectflockRepository {
func (r *ProjectflockRepositoryImpl) GetAllWithFilters(ctx context.Context, offset, limit int, params *validation.Query) ([]entity.ProjectFlock, int64, error) { func (r *ProjectflockRepositoryImpl) GetAllWithFilters(ctx context.Context, offset, limit int, params *validation.Query) ([]entity.ProjectFlock, int64, error) {
return r.GetAll(ctx, offset, limit, func(db *gorm.DB) *gorm.DB { return r.GetAll(ctx, offset, limit, func(db *gorm.DB) *gorm.DB {
return r.applyQueryFilters(db, params) return r.applyQueryFilters(r.WithDefaultRelations()(db), params)
}) })
} }
func (r *ProjectflockRepositoryImpl) WithDefaultRelations() func(*gorm.DB) *gorm.DB { func (r *ProjectflockRepositoryImpl) WithDefaultRelations() func(*gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB {
return db. return db.
Preload("CreatedUser"). Preload("CreatedUser").
Preload("Area"). Preload("Area").
Preload("Fcr"). Preload("Fcr").
Preload("Location"). Preload("Location").
Preload("Kandangs"). Preload("Kandangs").
Preload("KandangHistory"). Preload("KandangHistory").
Preload("KandangHistory.Kandang") Preload("KandangHistory.Kandang")
} }
} }
func (r *ProjectflockRepositoryImpl) applyQueryFilters(db *gorm.DB, params *validation.Query) *gorm.DB { func (r *ProjectflockRepositoryImpl) applyQueryFilters(db *gorm.DB, params *validation.Query) *gorm.DB {
if params == nil { if params == nil {
return db return db
@@ -1,7 +1,7 @@
package project_flocks package project_flocks
import ( import (
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware" m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/controllers"
projectflock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/services" projectflock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,7 +13,7 @@ func ProjectflockRoutes(v1 fiber.Router, u user.UserService, s projectflock.Proj
ctrl := controller.NewProjectflockController(s) ctrl := controller.NewProjectflockController(s)
route := v1.Group("/project-flocks") route := v1.Group("/project-flocks")
// route.Use(m.Auth(u)) route.Use(m.Auth(u))
route.Get("/", ctrl.GetAll) route.Get("/", ctrl.GetAll)
route.Post("/", ctrl.CreateOne) route.Post("/", ctrl.CreateOne)
@@ -10,8 +10,7 @@ import (
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
// authmiddleware "gitlab.com/mbugroup/lti-api.git/internal/middleware"
productWarehouseRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories" productWarehouseRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
flockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/dto" flockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/dto"
flockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/repositories" flockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/repositories"
@@ -85,18 +84,17 @@ func NewProjectflockService(
} }
} }
func (s projectflockService) approvalQueryModifier() func(*gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
return db.Preload("ActionUser")
}
}
func (s projectflockService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlock, int64, map[uint]*flockDTO.FlockRelationDTO, error) { func (s projectflockService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlock, int64, map[uint]*flockDTO.FlockRelationDTO, error) {
if err := s.Validate.Struct(params); err != nil { if err := s.Validate.Struct(params); err != nil {
return nil, 0, nil, err return nil, 0, nil, err
} }
if params.Page <= 0 {
params.Page = 1
}
if params.Limit <= 0 {
params.Limit = 10
}
offset := (params.Page - 1) * params.Limit offset := (params.Page - 1) * params.Limit
projectflocks, total, err := s.Repository.GetAllWithFilters(c.Context(), offset, params.Limit, params) projectflocks, total, err := s.Repository.GetAllWithFilters(c.Context(), offset, params.Limit, params)
@@ -112,7 +110,7 @@ func (s projectflockService) GetAll(c *fiber.Ctx, params *validation.Query) ([]e
ids[i] = item.Id ids[i] = item.Id
} }
latestMap, err := s.ApprovalSvc.LatestByTargets(c.Context(), s.approvalWorkflow, ids, s.Repository.WithDefaultRelations()) latestMap, err := s.ApprovalSvc.LatestByTargets(c.Context(), s.approvalWorkflow, ids, s.approvalQueryModifier())
if err != nil { if err != nil {
s.Log.Warnf("Unable to load latest approvals for projectflocks: %+v", err) s.Log.Warnf("Unable to load latest approvals for projectflocks: %+v", err)
} else if len(latestMap) > 0 { } else if len(latestMap) > 0 {
@@ -156,7 +154,7 @@ func (s projectflockService) getOneEntityOnly(c *fiber.Ctx, id uint) (*entity.Pr
} }
if s.ApprovalSvc != nil { if s.ApprovalSvc != nil {
approvals, err := s.ApprovalSvc.ListByTarget(c.Context(), s.approvalWorkflow, id, s.Repository.WithDefaultRelations()) approvals, err := s.ApprovalSvc.ListByTarget(c.Context(), s.approvalWorkflow, id, s.approvalQueryModifier())
if err != nil { if err != nil {
s.Log.Warnf("Unable to load approvals for projectflock %d: %+v", id, err) s.Log.Warnf("Unable to load approvals for projectflock %d: %+v", id, err)
} else if len(approvals) > 0 { } else if len(approvals) > 0 {
@@ -183,7 +181,7 @@ func (s projectflockService) GetOne(c *fiber.Ctx, id uint) (*entity.ProjectFlock
} }
if s.ApprovalSvc != nil { if s.ApprovalSvc != nil {
approvals, err := s.ApprovalSvc.ListByTarget(c.Context(), s.approvalWorkflow, id, s.Repository.WithDefaultRelations()) approvals, err := s.ApprovalSvc.ListByTarget(c.Context(), s.approvalWorkflow, id, s.approvalQueryModifier())
if err != nil { if err != nil {
s.Log.Warnf("Unable to load approvals for projectflock %d: %+v", id, err) s.Log.Warnf("Unable to load approvals for projectflock %d: %+v", id, err)
} else if len(approvals) > 0 { } else if len(approvals) > 0 {
@@ -221,7 +219,7 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
return nil, err return nil, err
} }
actorID, err := actorIDFromContext(c) actorID, err := m.ActorIDFromContext(c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -344,7 +342,7 @@ func (s projectflockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id
return nil, err return nil, err
} }
actorID, err := actorIDFromContext(c) actorID, err := m.ActorIDFromContext(c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -602,7 +600,7 @@ func (s projectflockService) Approval(c *fiber.Ctx, req *validation.Approve) ([]
return nil, err return nil, err
} }
actorID, err := actorIDFromContext(c) actorID, err := m.ActorIDFromContext(c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -847,7 +845,7 @@ func (s projectflockService) GetPeriodSummary(c *fiber.Ctx, locationID uint) ([]
summaries := make([]KandangPeriodSummary, 0, len(rows)) summaries := make([]KandangPeriodSummary, 0, len(rows))
for _, row := range rows { for _, row := range rows {
nextPeriod := 0 nextPeriod := 1
if row.LatestPeriod > 0 { if row.LatestPeriod > 0 {
nextPeriod = row.LatestPeriod + 1 nextPeriod = row.LatestPeriod + 1
} }
@@ -1046,12 +1044,3 @@ func (s projectflockService) kandangRepoWithTx(tx *gorm.DB) kandangRepository.Ka
} }
return kandangRepository.NewKandangRepository(s.Repository.DB()) return kandangRepository.NewKandangRepository(s.Repository.DB())
} }
func actorIDFromContext(_ *fiber.Ctx) (uint, error) {
// user, ok := authmiddleware.AuthenticatedUser(c)
// if !ok || user == nil || user.Id == 0 {
// return 0, fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
// }
// return user.Id, nil
return 1, nil
}
@@ -4,13 +4,10 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math"
"strings"
"time"
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories" rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories" rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories"
@@ -18,6 +15,9 @@ import (
"gitlab.com/mbugroup/lti-api.git/internal/utils" "gitlab.com/mbugroup/lti-api.git/internal/utils"
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals" approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
recordingutil "gitlab.com/mbugroup/lti-api.git/internal/utils/recording" recordingutil "gitlab.com/mbugroup/lti-api.git/internal/utils/recording"
"math"
"strings"
"time"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
@@ -169,7 +169,10 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
if err := s.ensureProductWarehousesExist(c, req.Stocks, req.Depletions, req.Eggs); err != nil { if err := s.ensureProductWarehousesExist(c, req.Stocks, req.Depletions, req.Eggs); err != nil {
return nil, err return nil, err
} }
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
var createdRecording entity.Recording var createdRecording entity.Recording
transactionErr := s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error { transactionErr := s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
nextDay, err := s.Repository.GenerateNextDay(tx, req.ProjectFlockKandangId) nextDay, err := s.Repository.GenerateNextDay(tx, req.ProjectFlockKandangId)
@@ -193,7 +196,7 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
ProjectFlockKandangId: req.ProjectFlockKandangId, ProjectFlockKandangId: req.ProjectFlockKandangId,
RecordDatetime: recordTime, RecordDatetime: recordTime,
Day: &day, Day: &day,
CreatedBy: 1, // TODO: replace with authenticated user CreatedBy: actorID,
} }
if err := s.Repository.CreateOne(ctx, &createdRecording, func(*gorm.DB) *gorm.DB { return tx }); err != nil { if err := s.Repository.CreateOne(ctx, &createdRecording, func(*gorm.DB) *gorm.DB { return tx }); err != nil {
@@ -422,7 +425,7 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
action := entity.ApprovalActionUpdated action := entity.ApprovalActionUpdated
actorID := recordingEntity.CreatedBy actorID := recordingEntity.CreatedBy
if actorID == 0 { if actorID == 0 {
actorID = 1 return fiber.NewError(fiber.StatusBadRequest, "Actor Id tidak valid untuk approval")
} }
var step approvalutils.ApprovalStep var step approvalutils.ApprovalStep
@@ -613,7 +616,10 @@ func (s recordingService) Approval(c *fiber.Ctx, req *validation.Approve) ([]ent
} }
ctx := c.Context() ctx := c.Context()
actorID := uint(1) // TODO: replace with authenticated user once auth is integrated actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
transactionErr := s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error { transactionErr := s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
repoTx := s.Repository.WithTx(tx) repoTx := s.Repository.WithTx(tx)
@@ -951,7 +957,7 @@ func (s *recordingService) createRecordingApproval(
return fiber.NewError(fiber.StatusBadRequest, "Recording tidak valid untuk approval") return fiber.NewError(fiber.StatusBadRequest, "Recording tidak valid untuk approval")
} }
if actorID == 0 { if actorID == 0 {
actorID = 1 return fiber.NewError(fiber.StatusBadRequest, "Actor Id tidak valid untuk approval")
} }
var svc commonSvc.ApprovalService var svc commonSvc.ApprovalService
@@ -1,7 +1,7 @@
package transfer_layings package transfer_layings
import ( import (
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware" m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/production/transfer_layings/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/production/transfer_layings/controllers"
transferLaying "gitlab.com/mbugroup/lti-api.git/internal/modules/production/transfer_layings/services" transferLaying "gitlab.com/mbugroup/lti-api.git/internal/modules/production/transfer_layings/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,7 +13,7 @@ func TransferLayingRoutes(v1 fiber.Router, u user.UserService, s transferLaying.
ctrl := controller.NewTransferLayingController(s) ctrl := controller.NewTransferLayingController(s)
route := v1.Group("/transfer_layings") route := v1.Group("/transfer_layings")
route.Use(m.Auth(u))
// route.Get("/", m.Auth(u), ctrl.GetAll) // route.Get("/", m.Auth(u), ctrl.GetAll)
// route.Post("/", m.Auth(u), ctrl.CreateOne) // route.Post("/", m.Auth(u), ctrl.CreateOne)
// route.Get("/:id", m.Auth(u), ctrl.GetOne) // route.Get("/:id", m.Auth(u), ctrl.GetOne)
@@ -10,6 +10,7 @@ import (
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
rInventory "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories" rInventory "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
rWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories" rWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
ProjectFlockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories" ProjectFlockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
@@ -154,6 +155,11 @@ func (s *transferLayingService) CreateOne(c *fiber.Ctx, req *validation.Create)
return nil, err return nil, err
} }
actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
if _, err := s.ProjectFlockRepo.GetByID(c.Context(), req.SourceProjectFlockId, nil); err != nil { if _, err := s.ProjectFlockRepo.GetByID(c.Context(), req.SourceProjectFlockId, nil); err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "Source Project Flock not found") return nil, fiber.NewError(fiber.StatusNotFound, "Source Project Flock not found")
@@ -259,7 +265,7 @@ func (s *transferLayingService) CreateOne(c *fiber.Ctx, req *validation.Create)
ToProjectFlockId: req.TargetProjectFlockId, ToProjectFlockId: req.TargetProjectFlockId,
TransferDate: transferDate, TransferDate: transferDate,
PendingUsageQty: &totalSourceQty, PendingUsageQty: &totalSourceQty,
CreatedBy: 1, //todo : harus diambil dari auth CreatedBy: actorID,
} }
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error { err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
@@ -592,7 +598,11 @@ func (s transferLayingService) Approval(c *fiber.Ctx, req *validation.Approve) (
return nil, err return nil, err
} }
actorID := uint(1) // TODO: change from auth context actorID, err := m.ActorIDFromContext(c)
if err != nil {
return nil, err
}
var action entity.ApprovalAction var action entity.ApprovalAction
switch strings.ToUpper(strings.TrimSpace(req.Action)) { switch strings.ToUpper(strings.TrimSpace(req.Action)) {
case string(entity.ApprovalActionRejected): case string(entity.ApprovalActionRejected):
@@ -613,7 +623,7 @@ func (s transferLayingService) Approval(c *fiber.Ctx, req *validation.Approve) (
step = utils.TransferToLayingStepDisetujui step = utils.TransferToLayingStepDisetujui
} }
err := s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error { err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction)) approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
sourceRepoTx := repository.NewLayingTransferSourceRepository(dbTransaction) sourceRepoTx := repository.NewLayingTransferSourceRepository(dbTransaction)
@@ -23,21 +23,19 @@ func NewPurchaseController(s service.PurchaseService) *PurchaseController {
} }
func (ctrl *PurchaseController) GetAll(c *fiber.Ctx) error { func (ctrl *PurchaseController) GetAll(c *fiber.Ctx) error {
query := &validation.PurchaseQuery{ query := &validation.Query{
Page: c.QueryInt("page", 1), Page: c.QueryInt("page", 1),
Limit: c.QueryInt("limit", 10), Limit: c.QueryInt("limit", 10),
Search: strings.TrimSpace(c.Query("search")),
PrNumber: strings.TrimSpace(c.Query("pr_number")),
CreatedFrom: strings.TrimSpace(c.Query("created_from")), CreatedFrom: strings.TrimSpace(c.Query("created_from")),
CreatedTo: strings.TrimSpace(c.Query("created_to")), CreatedTo: strings.TrimSpace(c.Query("created_to")),
SupplierID: uint(c.QueryInt("supplier_id", 0)),
AreaID: uint(c.QueryInt("area_id", 0)),
LocationID: uint(c.QueryInt("location_id", 0)),
ProductCategoryID: uint(c.QueryInt("product_category_id", 0)),
} }
if supplierID := c.QueryInt("supplier_id", 0); supplierID > 0 { if query.Page < 1 || query.Limit < 1 {
query.SupplierID = uint(supplierID) return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
}
if status := strings.TrimSpace(c.Query("status")); status != "" {
query.Status = strings.ToUpper(status)
} }
results, total, err := ctrl.service.GetAll(c, query) results, total, err := ctrl.service.GetAll(c, query)
@@ -45,24 +43,15 @@ func (ctrl *PurchaseController) GetAll(c *fiber.Ctx) error {
return err return err
} }
limit := query.Limit
if limit <= 0 {
limit = 10
}
page := query.Page
if page <= 0 {
page = 1
}
return c.Status(fiber.StatusOK). return c.Status(fiber.StatusOK).
JSON(response.SuccessWithPaginate[dto.PurchaseListItemDTO]{ JSON(response.SuccessWithPaginate[dto.PurchaseListDTO]{
Code: fiber.StatusOK, Code: fiber.StatusOK,
Status: "success", Status: "success",
Message: "Purchase fetched successfully", Message: "Purchase fetched successfully",
Meta: response.Meta{ Meta: response.Meta{
Page: page, Page: query.Page,
Limit: limit, Limit: query.Limit,
TotalPages: int64(math.Ceil(float64(total) / float64(limit))), TotalPages: int64(math.Ceil(float64(total) / float64(query.Limit))),
TotalResults: total, TotalResults: total,
}, },
Data: dto.ToPurchaseListDTOs(results), Data: dto.ToPurchaseListDTOs(results),
@@ -71,12 +60,13 @@ func (ctrl *PurchaseController) GetAll(c *fiber.Ctx) error {
func (ctrl *PurchaseController) GetOne(c *fiber.Ctx) error { func (ctrl *PurchaseController) GetOne(c *fiber.Ctx) error {
param := c.Params("id") param := c.Params("id")
id, err := strconv.ParseUint(param, 10, 64)
id, err := strconv.Atoi(param)
if err != nil || id == 0 { if err != nil || id == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id") return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id")
} }
result, err := ctrl.service.GetOne(c, id) result, err := ctrl.service.GetOne(c, uint(id))
if err != nil { if err != nil {
return err return err
} }
@@ -96,7 +86,7 @@ func (ctrl *PurchaseController) CreateOne(c *fiber.Ctx) error {
if err := c.BodyParser(req); err != nil { if err := c.BodyParser(req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
} }
result, err := ctrl.service.CreateOne(c, req) result, err := ctrl.service.CreateOne(c, req)
if err != nil { if err != nil {
return err return err
@@ -113,7 +103,7 @@ func (ctrl *PurchaseController) CreateOne(c *fiber.Ctx) error {
func (ctrl *PurchaseController) ApproveStaffPurchase(c *fiber.Ctx) error { func (ctrl *PurchaseController) ApproveStaffPurchase(c *fiber.Ctx) error {
param := c.Params("id") param := c.Params("id")
id, err := strconv.ParseUint(param, 10, 64) id, err := strconv.Atoi(param)
if err != nil || id == 0 { if err != nil || id == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id") return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id")
} }
@@ -123,7 +113,7 @@ func (ctrl *PurchaseController) ApproveStaffPurchase(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Invalid request body: %v", err)) return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Invalid request body: %v", err))
} }
result, err := ctrl.service.ApproveStaffPurchase(c, id, req) result, err := ctrl.service.ApproveStaffPurchase(c, uint(id), req)
if err != nil { if err != nil {
return err return err
} }
@@ -137,10 +127,9 @@ func (ctrl *PurchaseController) ApproveStaffPurchase(c *fiber.Ctx) error {
}) })
} }
func (ctrl *PurchaseController) ApproveManagerPurchase(c *fiber.Ctx) error { func (ctrl *PurchaseController) ApproveManagerPurchase(c *fiber.Ctx) error {
param := c.Params("id") param := c.Params("id")
id, err := strconv.ParseUint(param, 10, 64) id, err := strconv.Atoi(param)
if err != nil || id == 0 { if err != nil || id == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id") return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id")
} }
@@ -150,7 +139,7 @@ func (ctrl *PurchaseController) ApproveManagerPurchase(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
} }
result, err := ctrl.service.ApproveManagerPurchase(c, id, req) result, err := ctrl.service.ApproveManagerPurchase(c, uint(id), req)
if err != nil { if err != nil {
return err return err
} }
@@ -166,7 +155,7 @@ func (ctrl *PurchaseController) ApproveManagerPurchase(c *fiber.Ctx) error {
func (ctrl *PurchaseController) ReceiveProducts(c *fiber.Ctx) error { func (ctrl *PurchaseController) ReceiveProducts(c *fiber.Ctx) error {
param := c.Params("id") param := c.Params("id")
id, err := strconv.ParseUint(param, 10, 64) id, err := strconv.Atoi(param)
if err != nil || id == 0 { if err != nil || id == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id") return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id")
} }
@@ -176,7 +165,7 @@ func (ctrl *PurchaseController) ReceiveProducts(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
} }
result, err := ctrl.service.ReceiveProducts(c, id, req) result, err := ctrl.service.ReceiveProducts(c, uint(id), req)
if err != nil { if err != nil {
return err return err
} }
@@ -192,7 +181,7 @@ func (ctrl *PurchaseController) ReceiveProducts(c *fiber.Ctx) error {
func (ctrl *PurchaseController) DeleteItems(c *fiber.Ctx) error { func (ctrl *PurchaseController) DeleteItems(c *fiber.Ctx) error {
param := c.Params("id") param := c.Params("id")
id, err := strconv.ParseUint(param, 10, 64) id, err := strconv.Atoi(param)
if err != nil || id == 0 { if err != nil || id == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id") return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id")
} }
@@ -202,7 +191,7 @@ func (ctrl *PurchaseController) DeleteItems(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
} }
result, err := ctrl.service.DeleteItems(c, id, req) result, err := ctrl.service.DeleteItems(c, uint(id), req)
if err != nil { if err != nil {
return err return err
} }
@@ -218,12 +207,12 @@ func (ctrl *PurchaseController) DeleteItems(c *fiber.Ctx) error {
func (ctrl *PurchaseController) DeletePurchase(c *fiber.Ctx) error { func (ctrl *PurchaseController) DeletePurchase(c *fiber.Ctx) error {
param := c.Params("id") param := c.Params("id")
id, err := strconv.ParseUint(param, 10, 64) id, err := strconv.Atoi(param)
if err != nil || id == 0 { if err != nil || id == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id") return fiber.NewError(fiber.StatusBadRequest, "Invalid purchase id")
} }
if err := ctrl.service.DeletePurchase(c, id); err != nil { if err := ctrl.service.DeletePurchase(c, uint(id)); err != nil {
return err return err
} }
+111 -84
View File
@@ -10,46 +10,51 @@ import (
productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto" productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto"
supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto" supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto"
warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto" warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto"
userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
) )
type PurchaseListItemDTO struct { type PurchaseRelationDTO struct {
Id uint64 `json:"id"` Id uint `json:"id"`
PrNumber string `json:"pr_number"` PrNumber string `json:"pr_number"`
PoNumber *string `json:"po_number"` PoNumber *string `json:"po_number"`
Supplier *supplierDTO.SupplierRelationDTO `json:"supplier"` PoDate *time.Time `json:"po_date"`
CreditTerm *int `json:"credit_term"` Notes *string `json:"notes"`
DueDate *time.Time `json:"due_date"` }
PoDate *time.Time `json:"po_date"`
GrandTotal float64 `json:"grand_total"`
Notes *string `json:"notes"` type PurchaseListDTO struct {
CreatedAt time.Time `json:"created_at"` PurchaseRelationDTO
UpdatedAt time.Time `json:"updated_at"` Supplier *supplierDTO.SupplierRelationDTO `json:"supplier"`
Approval *approvalDTO.ApprovalRelationDTO `json:"approval"` CreditTerm *int `json:"credit_term"`
DueDate *time.Time `json:"due_date"`
GrandTotal float64 `json:"grand_total"`
CreatedUser *userDTO.UserRelationDTO `json:"created_user"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LatestApproval *approvalDTO.ApprovalRelationDTO `json:"latest_approval"`
} }
type PurchaseDetailDTO struct { type PurchaseDetailDTO struct {
Id uint64 `json:"id"` PurchaseRelationDTO
PrNumber string `json:"pr_number"` Supplier *supplierDTO.SupplierRelationDTO `json:"supplier"`
PoNumber *string `json:"po_number"` CreditTerm *int `json:"credit_term"`
Supplier *supplierDTO.SupplierRelationDTO `json:"supplier"` DueDate *time.Time `json:"due_date"`
CreditTerm *int `json:"credit_term"` GrandTotal float64 `json:"grand_total"`
DueDate *time.Time `json:"due_date"` Items []PurchaseItemDTO `json:"items"`
PoDate *time.Time `json:"po_date"` CreatedUser *userDTO.UserRelationDTO `json:"created_user"`
GrandTotal float64 `json:"grand_total"` CreatedAt time.Time `json:"created_at"`
Notes *string `json:"notes"` UpdatedAt time.Time `json:"updated_at"`
Items []PurchaseItemDTO `json:"items"` LatestApproval *approvalDTO.ApprovalRelationDTO `json:"latest_approval"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Approval *approvalDTO.ApprovalRelationDTO `json:"approval"`
} }
type PurchaseItemDTO struct { type PurchaseItemDTO struct {
Id uint64 `json:"id"` Id uint `json:"id"`
ProductID uint64 `json:"product_id"` ProductID uint `json:"product_id"`
Product *productDTO.ProductRelationDTO `json:"product"` Product *productDTO.ProductRelationDTO `json:"product"`
WarehouseID uint64 `json:"warehouse_id"` WarehouseID uint `json:"warehouse_id"`
Warehouse *warehouseDTO.WarehouseRelationDTO `json:"warehouse"` Warehouse *warehouseDTO.WarehouseRelationDTO `json:"warehouse"`
ProductWarehouseID *uint64 `json:"product_warehouse_id"` ProductWarehouseID *uint `json:"product_warehouse_id"`
SubQty float64 `json:"sub_qty"` SubQty float64 `json:"sub_qty"`
TotalQty float64 `json:"total_qty"` TotalQty float64 `json:"total_qty"`
TotalUsed float64 `json:"total_used"` TotalUsed float64 `json:"total_used"`
@@ -61,6 +66,17 @@ type PurchaseItemDTO struct {
VehicleNumber *string `json:"vehicle_number"` VehicleNumber *string `json:"vehicle_number"`
} }
func ToPurchaseRelationDTO(p *entity.Purchase) PurchaseRelationDTO {
return PurchaseRelationDTO{
Id: p.Id,
PrNumber: p.PrNumber,
PoNumber: p.PoNumber,
PoDate: p.PoDate,
Notes: p.Notes,
}
}
func ToPurchaseItemDTO(item entity.PurchaseItem) PurchaseItemDTO { func ToPurchaseItemDTO(item entity.PurchaseItem) PurchaseItemDTO {
dto := PurchaseItemDTO{ dto := PurchaseItemDTO{
Id: item.Id, Id: item.Id,
@@ -77,10 +93,12 @@ func ToPurchaseItemDTO(item entity.PurchaseItem) PurchaseItemDTO {
TravelDocumentPath: item.TravelNumberDocs, TravelDocumentPath: item.TravelNumberDocs,
VehicleNumber: item.VehicleNumber, VehicleNumber: item.VehicleNumber,
} }
if item.Product != nil && item.Product.Id != 0 { if item.Product != nil && item.Product.Id != 0 {
summary := productDTO.ToProductRelationDTO(*item.Product) summary := productDTO.ToProductRelationDTO(*item.Product)
dto.Product = &summary dto.Product = &summary
} }
if item.Warehouse != nil && item.Warehouse.Id != 0 { if item.Warehouse != nil && item.Warehouse.Id != 0 {
summary := warehouseDTO.ToWarehouseRelationDTO(*item.Warehouse) summary := warehouseDTO.ToWarehouseRelationDTO(*item.Warehouse)
if item.Warehouse.Area.Id != 0 { if item.Warehouse.Area.Id != 0 {
@@ -93,6 +111,7 @@ func ToPurchaseItemDTO(item entity.PurchaseItem) PurchaseItemDTO {
} }
dto.Warehouse = &summary dto.Warehouse = &summary
} }
return dto return dto
} }
@@ -104,70 +123,78 @@ func ToPurchaseItemDTOs(items []entity.PurchaseItem) []PurchaseItemDTO {
return result return result
} }
func ToPurchaseDetailDTO(p entity.Purchase) PurchaseDetailDTO { func ToPurchaseListDTO(p entity.Purchase) PurchaseListDTO {
dto := PurchaseDetailDTO{ var supplier *supplierDTO.SupplierRelationDTO
Id: p.Id, if p.Supplier.Id != 0 {
PrNumber: p.PrNumber, mapped := supplierDTO.ToSupplierRelationDTO(p.Supplier)
PoNumber: p.PoNumber, supplier = &mapped
Supplier: mapSupplier(p.Supplier),
CreditTerm: p.CreditTerm,
DueDate: p.DueDate,
PoDate: p.PoDate,
GrandTotal: p.GrandTotal,
Notes: p.Notes,
Items: ToPurchaseItemDTOs(p.Items),
CreatedAt: p.CreatedAt,
UpdatedAt: p.UpdatedAt,
} }
if approval := toPurchaseApprovalDTO(p); approval != nil {
dto.Approval = approval var createdUser *userDTO.UserRelationDTO
if p.CreatedUser.Id != 0 {
mapped := userDTO.ToUserRelationDTO(p.CreatedUser)
createdUser = &mapped
}
var latestApproval *approvalDTO.ApprovalRelationDTO
if p.LatestApproval != nil && p.LatestApproval.Id != 0 {
mapped := approvalDTO.ToApprovalDTO(*p.LatestApproval)
latestApproval = &mapped
}
return PurchaseListDTO{
PurchaseRelationDTO: ToPurchaseRelationDTO(&p),
Supplier: supplier,
CreditTerm: p.CreditTerm,
DueDate: p.DueDate,
GrandTotal: p.GrandTotal,
CreatedUser: createdUser,
CreatedAt: p.CreatedAt,
UpdatedAt: p.UpdatedAt,
LatestApproval: latestApproval,
} }
return dto
} }
func ToPurchaseListDTO(p entity.Purchase) PurchaseListItemDTO { func ToPurchaseListDTOs(items []entity.Purchase) []PurchaseListDTO {
dto := PurchaseListItemDTO{
Id: p.Id,
PrNumber: p.PrNumber,
PoNumber: p.PoNumber,
Supplier: mapSupplier(p.Supplier),
CreditTerm: p.CreditTerm,
DueDate: p.DueDate,
PoDate: p.PoDate,
GrandTotal: p.GrandTotal,
Notes: p.Notes,
CreatedAt: p.CreatedAt,
UpdatedAt: p.UpdatedAt,
}
if approval := toPurchaseApprovalDTO(p); approval != nil {
dto.Approval = approval
}
return dto
}
func mapSupplier(s entity.Supplier) *supplierDTO.SupplierRelationDTO {
if s.Id == 0 {
return nil
}
summary := supplierDTO.ToSupplierRelationDTO(s)
return &summary
}
func ToPurchaseListDTOs(items []entity.Purchase) []PurchaseListItemDTO {
if len(items) == 0 { if len(items) == 0 {
return nil return make([]PurchaseListDTO, 0)
} }
result := make([]PurchaseListItemDTO, len(items)) result := make([]PurchaseListDTO, len(items))
for i, item := range items { for i, item := range items {
result[i] = ToPurchaseListDTO(item) result[i] = ToPurchaseListDTO(item)
} }
return result return result
} }
func toPurchaseApprovalDTO(p entity.Purchase) *approvalDTO.ApprovalRelationDTO { func ToPurchaseDetailDTO(p entity.Purchase) PurchaseDetailDTO {
if p.LatestApproval == nil || p.LatestApproval.Id == 0 { var supplier *supplierDTO.SupplierRelationDTO
return nil if p.Supplier.Id != 0 {
mapped := supplierDTO.ToSupplierRelationDTO(p.Supplier)
supplier = &mapped
} }
mapped := approvalDTO.ToApprovalDTO(*p.LatestApproval)
return &mapped var createdUser *userDTO.UserRelationDTO
} if p.CreatedUser.Id != 0 {
mapped := userDTO.ToUserRelationDTO(p.CreatedUser)
createdUser = &mapped
}
var latestApproval *approvalDTO.ApprovalRelationDTO
if p.LatestApproval != nil && p.LatestApproval.Id != 0 {
mapped := approvalDTO.ToApprovalDTO(*p.LatestApproval)
latestApproval = &mapped
}
return PurchaseDetailDTO{
PurchaseRelationDTO: ToPurchaseRelationDTO(&p),
Supplier: supplier,
CreditTerm: p.CreditTerm,
DueDate: p.DueDate,
GrandTotal: p.GrandTotal,
Items: ToPurchaseItemDTOs(p.Items),
CreatedUser: createdUser,
CreatedAt: p.CreatedAt,
UpdatedAt: p.UpdatedAt,
LatestApproval: latestApproval,
}
}
-1
View File
@@ -43,7 +43,6 @@ func (PurchaseModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
warehouseRepo, warehouseRepo,
supplierRepo, supplierRepo,
productWarehouseRepo, productWarehouseRepo,
approvalRepo,
approvalService, approvalService,
expenseBridge, expenseBridge,
) )
@@ -18,14 +18,11 @@ import (
type PurchaseRepository interface { type PurchaseRepository interface {
repository.BaseRepository[entity.Purchase] repository.BaseRepository[entity.Purchase]
CreateWithItems(ctx context.Context, purchase *entity.Purchase, items []*entity.PurchaseItem) error CreateWithItems(ctx context.Context, purchase *entity.Purchase, items []*entity.PurchaseItem) error
CreateItems(ctx context.Context, purchaseID uint64, items []*entity.PurchaseItem) error CreateItems(ctx context.Context, purchaseID uint, items []*entity.PurchaseItem) error
GetByIDWithRelations(ctx context.Context, id uint64) (*entity.Purchase, error) UpdatePricing(ctx context.Context, purchaseID uint, updates []PurchasePricingUpdate, grandTotal float64) error
GetAllWithFilters(ctx context.Context, offset, limit int, filter *PurchaseListFilter) ([]entity.Purchase, int64, error) UpdateReceivingDetails(ctx context.Context, purchaseID uint, updates []PurchaseReceivingUpdate) error
UpdatePricing(ctx context.Context, purchaseID uint64, updates []PurchasePricingUpdate, grandTotal float64) error DeleteItems(ctx context.Context, purchaseID uint, itemIDs []uint) error
UpdateReceivingDetails(ctx context.Context, purchaseID uint64, updates []PurchaseReceivingUpdate) error UpdateGrandTotal(ctx context.Context, purchaseID uint, grandTotal float64) error
DeleteItems(ctx context.Context, purchaseID uint64, itemIDs []uint64) error
WithListRelations() func(*gorm.DB) *gorm.DB
UpdateGrandTotal(ctx context.Context, purchaseID uint64, grandTotal float64) error
NextPrNumber(ctx context.Context, tx *gorm.DB) (string, error) NextPrNumber(ctx context.Context, tx *gorm.DB) (string, error)
NextPoNumber(ctx context.Context, tx *gorm.DB) (string, error) NextPoNumber(ctx context.Context, tx *gorm.DB) (string, error)
} }
@@ -40,19 +37,10 @@ func NewPurchaseRepository(db *gorm.DB) PurchaseRepository {
} }
} }
type PurchaseListFilter struct {
SupplierID uint
Search string
PrNumber string
CreatedFrom *time.Time
CreatedTo *time.Time
Status *entity.ApprovalAction
CompletedOnly bool
}
func (r *PurchaseRepositoryImpl) CreateWithItems(ctx context.Context, purchase *entity.Purchase, items []*entity.PurchaseItem) error { func (r *PurchaseRepositoryImpl) CreateWithItems(ctx context.Context, purchase *entity.Purchase, items []*entity.PurchaseItem) error {
db := r.DB().WithContext(ctx) db := r.DB().WithContext(ctx)
//ambil dari base repository
if err := db.Create(purchase).Error; err != nil { if err := db.Create(purchase).Error; err != nil {
return err return err
} }
@@ -71,7 +59,7 @@ func (r *PurchaseRepositoryImpl) CreateWithItems(ctx context.Context, purchase *
return nil return nil
} }
func (r *PurchaseRepositoryImpl) CreateItems(ctx context.Context, purchaseID uint64, items []*entity.PurchaseItem) error { func (r *PurchaseRepositoryImpl) CreateItems(ctx context.Context, purchaseID uint, items []*entity.PurchaseItem) error {
if len(items) == 0 { if len(items) == 0 {
return nil return nil
} }
@@ -86,52 +74,9 @@ func (r *PurchaseRepositoryImpl) CreateItems(ctx context.Context, purchaseID uin
return r.DB().WithContext(ctx).Create(&items).Error return r.DB().WithContext(ctx).Create(&items).Error
} }
func (r *PurchaseRepositoryImpl) GetByIDWithRelations(ctx context.Context, id uint64) (*entity.Purchase, error) {
var purchase entity.Purchase
err := r.DB().WithContext(ctx).
Scopes(r.withDetailRelations).
First(&purchase, id).Error
if err != nil {
return nil, err
}
return &purchase, nil
}
func (r *PurchaseRepositoryImpl) GetAllWithFilters(ctx context.Context, offset, limit int, filter *PurchaseListFilter) ([]entity.Purchase, int64, error) {
return r.GetAll(ctx, offset, limit, func(db *gorm.DB) *gorm.DB {
db = r.withListRelations(db)
return r.applyListFilters(db, filter)
})
}
func (r *PurchaseRepositoryImpl) WithListRelations() func(*gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
return r.withListRelations(db)
}
}
func (r *PurchaseRepositoryImpl) withDetailRelations(db *gorm.DB) *gorm.DB {
return db.
Preload("Supplier").
Preload("Items", func(db *gorm.DB) *gorm.DB {
return db.Order("id ASC")
}).
Preload("Items.Product").
Preload("Items.Warehouse").
Preload("Items.Warehouse.Area").
Preload("Items.Warehouse.Location").
Preload("Items.ProductWarehouse")
}
func (r *PurchaseRepositoryImpl) WithDetailRelations() func(*gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
return r.withDetailRelations(db)
}
}
type PurchasePricingUpdate struct { type PurchasePricingUpdate struct {
ItemID uint64 ItemID uint
ProductID *uint64 ProductID *uint
Price float64 Price float64
TotalPrice float64 TotalPrice float64
Quantity *float64 Quantity *float64
@@ -139,7 +84,7 @@ type PurchasePricingUpdate struct {
} }
type PurchaseReceivingUpdate struct { type PurchaseReceivingUpdate struct {
ItemID uint64 ItemID uint
ReceivedDate *time.Time ReceivedDate *time.Time
TravelNumber *string TravelNumber *string
TravelDocumentPath *string TravelDocumentPath *string
@@ -152,7 +97,7 @@ type PurchaseReceivingUpdate struct {
func (r *PurchaseRepositoryImpl) UpdatePricing( func (r *PurchaseRepositoryImpl) UpdatePricing(
ctx context.Context, ctx context.Context,
purchaseID uint64, purchaseID uint,
updates []PurchasePricingUpdate, updates []PurchasePricingUpdate,
grandTotal float64, grandTotal float64,
) error { ) error {
@@ -192,7 +137,6 @@ func (r *PurchaseRepositoryImpl) UpdatePricing(
Where("id = ?", purchaseID). Where("id = ?", purchaseID).
Updates(map[string]interface{}{ Updates(map[string]interface{}{
"grand_total": grandTotal, "grand_total": grandTotal,
"updated_at": gorm.Expr("NOW()"),
}).Error; err != nil { }).Error; err != nil {
return err return err
} }
@@ -202,7 +146,7 @@ func (r *PurchaseRepositoryImpl) UpdatePricing(
func (r *PurchaseRepositoryImpl) UpdateReceivingDetails( func (r *PurchaseRepositoryImpl) UpdateReceivingDetails(
ctx context.Context, ctx context.Context,
purchaseID uint64, purchaseID uint,
updates []PurchaseReceivingUpdate, updates []PurchaseReceivingUpdate,
) error { ) error {
if len(updates) == 0 { if len(updates) == 0 {
@@ -259,7 +203,7 @@ func (r *PurchaseRepositoryImpl) UpdateReceivingDetails(
func (r *PurchaseRepositoryImpl) UpdateGrandTotal( func (r *PurchaseRepositoryImpl) UpdateGrandTotal(
ctx context.Context, ctx context.Context,
purchaseID uint64, purchaseID uint,
grandTotal float64, grandTotal float64,
) error { ) error {
return r.DB().WithContext(ctx). return r.DB().WithContext(ctx).
@@ -271,7 +215,7 @@ func (r *PurchaseRepositoryImpl) UpdateGrandTotal(
}).Error }).Error
} }
func (r *PurchaseRepositoryImpl) DeleteItems(ctx context.Context, purchaseID uint64, itemIDs []uint64) error { func (r *PurchaseRepositoryImpl) DeleteItems(ctx context.Context, purchaseID uint, itemIDs []uint) error {
if len(itemIDs) == 0 { if len(itemIDs) == 0 {
return errors.New("itemIDs cannot be empty") return errors.New("itemIDs cannot be empty")
} }
@@ -361,63 +305,3 @@ func parseNumericSuffix(value, prefix string) (int, bool) {
} }
return number, true return number, true
} }
func (r *PurchaseRepositoryImpl) withListRelations(db *gorm.DB) *gorm.DB {
return db.Preload("Supplier")
}
func (r *PurchaseRepositoryImpl) applyListFilters(db *gorm.DB, filter *PurchaseListFilter) *gorm.DB {
if filter == nil {
return db
}
if filter.SupplierID > 0 {
db = db.Where("purchases.supplier_id = ?", filter.SupplierID)
}
if search := strings.ToLower(strings.TrimSpace(filter.Search)); search != "" {
like := "%" + search + "%"
db = db.Where("(LOWER(purchases.pr_number) LIKE ? OR LOWER(COALESCE(purchases.notes, '')) LIKE ?)", like, like)
}
if pr := strings.TrimSpace(filter.PrNumber); pr != "" {
db = db.Where("purchases.pr_number ILIKE ?", "%"+pr+"%")
}
if filter.CreatedFrom != nil {
db = db.Where("purchases.created_at >= ?", *filter.CreatedFrom)
}
if filter.CreatedTo != nil {
db = db.Where("purchases.created_at < ?", *filter.CreatedTo)
}
if filter.CompletedOnly {
step := uint16(utils.PurchaseStepCompleted)
db = r.applyLatestApprovalFilter(db, entity.ApprovalActionApproved, &step)
} else if filter.Status != nil {
db = r.applyLatestApprovalFilter(db, *filter.Status, nil)
}
return db.Order("purchases.created_at DESC").Order("purchases.id DESC")
}
func (r *PurchaseRepositoryImpl) applyLatestApprovalFilter(db *gorm.DB, action entity.ApprovalAction, minStep *uint16) *gorm.DB {
latestSub := r.DB().
Model(&entity.Approval{}).
Select("approvable_id, MAX(action_at) AS latest_action_at").
Where("approvable_type = ?", utils.ApprovalWorkflowPurchase.String()).
Group("approvable_id")
db = db.
Joins("LEFT JOIN (?) AS latest_purchase_approvals ON latest_purchase_approvals.approvable_id = purchases.id", latestSub).
Joins(
"LEFT JOIN approvals ON approvals.approvable_id = purchases.id AND approvals.approvable_type = ? AND approvals.action_at = latest_purchase_approvals.latest_action_at",
utils.ApprovalWorkflowPurchase.String(),
).
Where("approvals.action = ?", string(action))
if minStep != nil {
db = db.Where("approvals.step_number >= ?", *minStep)
}
return db
}
+2 -2
View File
@@ -3,7 +3,7 @@ package purchases
import ( import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
middleware "gitlab.com/mbugroup/lti-api.git/internal/middleware" m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/controllers"
service "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/services" service "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,7 +13,7 @@ func Routes(router fiber.Router, purchaseService service.PurchaseService, userSe
ctrl := controller.NewPurchaseController(purchaseService) ctrl := controller.NewPurchaseController(purchaseService)
route := router.Group("/purchases") route := router.Group("/purchases")
route.Use(middleware.Auth(userService)) route.Use(m.Auth(userService))
route.Get("/", ctrl.GetAll) route.Get("/", ctrl.GetAll)
route.Get("/:id", ctrl.GetOne) route.Get("/:id", ctrl.GetOne)
@@ -9,16 +9,16 @@ import (
// PurchaseExpenseBridge defines hooks that allow purchase flows to stay in sync with expense data once it exists. // PurchaseExpenseBridge defines hooks that allow purchase flows to stay in sync with expense data once it exists.
type PurchaseExpenseBridge interface { type PurchaseExpenseBridge interface {
OnItemsCreated(ctx context.Context, purchaseID uint64, items []entity.PurchaseItem) error OnItemsCreated(ctx context.Context, purchaseID uint, items []entity.PurchaseItem) error
OnItemsDeleted(ctx context.Context, purchaseID uint64, itemIDs []uint64) error OnItemsDeleted(ctx context.Context, purchaseID uint, itemIDs []uint) error
OnItemsReceived(ctx context.Context, purchaseID uint64, updates []ExpenseReceivingPayload) error OnItemsReceived(ctx context.Context, purchaseID uint, updates []ExpenseReceivingPayload) error
} }
// ExpenseReceivingPayload captures the minimum data expense integration will need once available. // ExpenseReceivingPayload captures the minimum data expense integration will need once available.
type ExpenseReceivingPayload struct { type ExpenseReceivingPayload struct {
PurchaseItemID uint64 PurchaseItemID uint
ProductID uint64 ProductID uint
WarehouseID uint64 WarehouseID uint
ReceivedQty float64 ReceivedQty float64
ReceivedDate *time.Time ReceivedDate *time.Time
} }
@@ -30,14 +30,14 @@ func NewNoopPurchaseExpenseBridge() PurchaseExpenseBridge {
return &noopPurchaseExpenseBridge{} return &noopPurchaseExpenseBridge{}
} }
func (n *noopPurchaseExpenseBridge) OnItemsCreated(_ context.Context, _ uint64, _ []entity.PurchaseItem) error { func (n *noopPurchaseExpenseBridge) OnItemsCreated(_ context.Context, _ uint, _ []entity.PurchaseItem) error {
return nil return nil
} }
func (n *noopPurchaseExpenseBridge) OnItemsDeleted(_ context.Context, _ uint64, _ []uint64) error { func (n *noopPurchaseExpenseBridge) OnItemsDeleted(_ context.Context, _ uint, _ []uint) error {
return nil return nil
} }
func (n *noopPurchaseExpenseBridge) OnItemsReceived(_ context.Context, _ uint64, _ []ExpenseReceivingPayload) error { func (n *noopPurchaseExpenseBridge) OnItemsReceived(_ context.Context, _ uint, _ []ExpenseReceivingPayload) error {
return nil return nil
} }
File diff suppressed because it is too large Load Diff
@@ -14,26 +14,28 @@ type CreatePurchaseRequest struct {
} }
type StaffPurchaseApprovalItem struct { type StaffPurchaseApprovalItem struct {
PurchaseItemID uint64 `json:"purchase_item_id,omitempty" validate:"omitempty,gt=0"` PurchaseItemID uint `json:"purchase_item_id,omitempty" validate:"omitempty,gt=0"`
// For new items (no purchase_item_id), product_id is required. // For new items (no purchase_item_id), product_id is required.
ProductID uint64 `json:"product_id,omitempty" validate:"required_without=PurchaseItemID,omitempty,gt=0"` ProductID uint `json:"product_id,omitempty" validate:"required_without=PurchaseItemID,omitempty,gt=0"`
WarehouseID uint64 `json:"warehouse_id,omitempty" validate:"required_without=PurchaseItemID,omitempty,gt=0"` WarehouseID uint `json:"warehouse_id,omitempty" validate:"required_without=PurchaseItemID,omitempty,gt=0"`
Qty *float64 `json:"qty,omitempty" validate:"required_without=PurchaseItemID,omitempty,gt=0"` Qty *float64 `json:"qty,omitempty" validate:"required_without=PurchaseItemID,omitempty,gt=0"`
Price float64 `json:"price" validate:"required,gt=0"` Price float64 `json:"price" validate:"required,gt=0"`
TotalPrice float64 `json:"total_price" validate:"required,gt=0"` TotalPrice float64 `json:"total_price" validate:"required,gt=0"`
} }
type ApproveStaffPurchaseRequest struct { type ApproveStaffPurchaseRequest struct {
Items []StaffPurchaseApprovalItem `json:"items" validate:"required,min=1,dive"` Action string `json:"action" validate:"required,oneof=APPROVED REJECTED"`
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"` Items []StaffPurchaseApprovalItem `json:"items,omitempty" validate:"omitempty,min=1,dive"`
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"`
} }
type ApproveManagerPurchaseRequest struct { type ApproveManagerPurchaseRequest struct {
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"` Action string `json:"action" validate:"required,oneof=APPROVED REJECTED"`
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"`
} }
type ReceivePurchaseItemRequest struct { type ReceivePurchaseItemRequest struct {
PurchaseItemID uint64 `json:"purchase_item_id" validate:"required,gt=0"` PurchaseItemID uint `json:"purchase_item_id" validate:"required,gt=0"`
WarehouseID *uint `json:"warehouse_id" validate:"omitempty,gt=0"` WarehouseID *uint `json:"warehouse_id" validate:"omitempty,gt=0"`
ReceivedDate string `json:"received_date" validate:"required,datetime=2006-01-02"` ReceivedDate string `json:"received_date" validate:"required,datetime=2006-01-02"`
TravelNumber *string `json:"travel_number" validate:"omitempty,max=100"` TravelNumber *string `json:"travel_number" validate:"omitempty,max=100"`
@@ -43,21 +45,23 @@ type ReceivePurchaseItemRequest struct {
} }
type ReceivePurchaseRequest struct { type ReceivePurchaseRequest struct {
Items []ReceivePurchaseItemRequest `json:"items" validate:"required,min=1,dive"` Action string `json:"action" validate:"required,oneof=APPROVED REJECTED"`
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"` Items []ReceivePurchaseItemRequest `json:"items,omitempty" validate:"omitempty,min=1,dive"`
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"`
} }
type DeletePurchaseItemsRequest struct { type DeletePurchaseItemsRequest struct {
ItemIDs []uint64 `json:"item_ids" validate:"required,min=1,dive,gt=0"` ItemIDs []uint `json:"item_ids" validate:"required,min=1,dive,gt=0"`
} }
type PurchaseQuery struct { type Query struct {
Page int `query:"page" validate:"omitempty,number,min=1"` Page int `query:"page" validate:"omitempty,number,min=1"`
Limit int `query:"limit" validate:"omitempty,number,min=1,max=100"` Limit int `query:"limit" validate:"omitempty,number,min=1,max=100"`
SupplierID uint `query:"supplier_id" validate:"omitempty,gt=0"` SupplierID uint `query:"supplier_id" validate:"omitempty,gt=0"`
Search string `query:"search" validate:"omitempty,max=100"` AreaID uint `query:"area_id" validate:"omitempty,gt=0"`
PrNumber string `query:"pr_number" validate:"omitempty,max=50"` LocationID uint `query:"location_id" validate:"omitempty,gt=0"`
CreatedFrom string `query:"created_from" validate:"omitempty,datetime=2006-01-02"` ProductCategoryID uint `query:"product_category_id" validate:"omitempty,gt=0"`
CreatedTo string `query:"created_to" validate:"omitempty,datetime=2006-01-02"` Search string `query:"search" validate:"omitempty,max=100"`
Status string `query:"status" validate:"omitempty,oneof=CREATED UPDATED APPROVED REJECTED COMPLETED"` CreatedFrom string `query:"created_from" validate:"omitempty,datetime=2006-01-02"`
CreatedTo string `query:"created_to" validate:"omitempty,datetime=2006-01-02"`
} }