Merge branch 'feat/BE/Sprint-8' into 'development'

[FEAT/BE] Partial Merge #3

See merge request mbugroup/lti-api!116
This commit is contained in:
Hafizh A. Y.
2025-12-30 12:06:19 +00:00
36 changed files with 369 additions and 161 deletions
Vendored
BIN
View File
Binary file not shown.
@@ -0,0 +1,7 @@
DROP INDEX IF EXISTS idx_project_flocks_production_standard_id;
ALTER TABLE project_flocks
DROP CONSTRAINT IF EXISTS fk_project_flocks_production_standard_id;
ALTER TABLE project_flocks
DROP COLUMN IF EXISTS production_standard_id;
@@ -0,0 +1,15 @@
-- Add production_standard_id to project_flocks
ALTER TABLE project_flocks
ADD COLUMN IF NOT EXISTS production_standard_id BIGINT;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_tables WHERE tablename = 'production_standards') THEN
ALTER TABLE project_flocks
ADD CONSTRAINT fk_project_flocks_production_standard_id
FOREIGN KEY (production_standard_id) REFERENCES production_standards (id) ON DELETE RESTRICT ON UPDATE CASCADE;
END IF;
END $$;
CREATE INDEX IF NOT EXISTS idx_project_flocks_production_standard_id
ON project_flocks (production_standard_id);
@@ -0,0 +1,3 @@
-- Remove standard_fcr column from production_standard_details table
ALTER TABLE production_standard_details
DROP COLUMN IF EXISTS standard_fcr;
@@ -0,0 +1,3 @@
-- Add standard_fcr column to production_standard_details table
ALTER TABLE production_standard_details
ADD COLUMN standard_fcr NUMERIC(15, 3);
+22 -10
View File
@@ -891,14 +891,14 @@ func seedProductWarehouse(tx *gorm.DB, createdBy uint) error {
WarehouseName string WarehouseName string
Quantity float64 Quantity float64
}{ }{
{ProductName: "DOC Broiler", WarehouseName: "Gudang Priangan", Quantity: 100}, {ProductName: "DOC Broiler", WarehouseName: "Gudang Priangan", Quantity: 0},
{ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Singaparna", Quantity: 200}, {ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Singaparna", Quantity: 0},
{ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Banten", Quantity: 300}, {ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Banten", Quantity: 0},
{ProductName: "DOC Broiler", WarehouseName: "Gudang Singaparna 1", Quantity: 5000}, {ProductName: "DOC Broiler", WarehouseName: "Gudang Singaparna 1", Quantity: 0},
{ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Singaparna 1", Quantity: 600}, {ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Singaparna 1", Quantity: 0},
{ProductName: "Telur Pecah", WarehouseName: "Gudang Singaparna 1", Quantity: 80}, {ProductName: "Telur Pecah", WarehouseName: "Gudang Singaparna 1", Quantity: 0},
{ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Cikaum 1", Quantity: 450}, {ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Cikaum 1", Quantity: 0},
{ProductName: "Telur Pecah", WarehouseName: "Gudang Cikaum 1", Quantity: 60}, {ProductName: "Telur Pecah", WarehouseName: "Gudang Cikaum 1", Quantity: 0},
} }
for _, seed := range seeds { for _, seed := range seeds {
@@ -962,12 +962,24 @@ func seedTransferStock(tx *gorm.DB) error {
{ {
StockTransferId: transfer.Id, StockTransferId: transfer.Id,
ProductId: 1, ProductId: 1,
Quantity: 10,
SourceProductWarehouseID: func() *uint64 { id := uint64(1); return &id }(),
DestProductWarehouseID: func() *uint64 { id := uint64(2); return &id }(),
UsageQty: 10,
PendingQty: 0,
TotalQty: 10,
TotalUsed: 0,
}, },
{ {
StockTransferId: transfer.Id, StockTransferId: transfer.Id,
ProductId: 2, ProductId: 2,
Quantity: 5,
SourceProductWarehouseID: func() *uint64 { id := uint64(1); return &id }(),
DestProductWarehouseID: func() *uint64 { id := uint64(2); return &id }(),
UsageQty: 5,
PendingQty: 0,
TotalQty: 5,
TotalUsed: 0,
}, },
} }
for i := range details { for i := range details {
@@ -12,6 +12,7 @@ type ProductionStandardDetail struct {
TargetHenHouseProduction *float64 `gorm:"type:numeric(15,3)"` TargetHenHouseProduction *float64 `gorm:"type:numeric(15,3)"`
TargetEggWeight *float64 `gorm:"type:numeric(15,3)"` TargetEggWeight *float64 `gorm:"type:numeric(15,3)"`
TargetEggMass *float64 `gorm:"type:numeric(15,3)"` TargetEggMass *float64 `gorm:"type:numeric(15,3)"`
StandardFCR *float64 `gorm:"type:numeric(15,3)"`
CreatedAt time.Time `gorm:"type:timestamptz;not null"` CreatedAt time.Time `gorm:"type:timestamptz;not null"`
UpdatedAt time.Time `gorm:"type:timestamptz;not null"` UpdatedAt time.Time `gorm:"type:timestamptz;not null"`
+2
View File
@@ -12,6 +12,7 @@ type ProjectFlock struct {
AreaId uint `gorm:"not null"` AreaId uint `gorm:"not null"`
Category string `gorm:"type:varchar(20);not null"` Category string `gorm:"type:varchar(20);not null"`
FcrId uint `gorm:"not null"` FcrId uint `gorm:"not null"`
ProductionStandardId uint `gorm:"column:production_standard_id"`
LocationId uint `gorm:"not null"` LocationId uint `gorm:"not null"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
@@ -20,6 +21,7 @@ type ProjectFlock struct {
Area Area `gorm:"foreignKey:AreaId;references:Id"` Area Area `gorm:"foreignKey:AreaId;references:Id"`
Fcr Fcr `gorm:"foreignKey:FcrId;references:Id"` Fcr Fcr `gorm:"foreignKey:FcrId;references:Id"`
ProductionStandard ProductionStandard `gorm:"foreignKey:ProductionStandardId;references:Id"`
Location Location `gorm:"foreignKey:LocationId;references:Id"` Location Location `gorm:"foreignKey:LocationId;references:Id"`
CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"` CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"`
Kandangs []Kandang `gorm:"many2many:project_flock_kandangs;joinTableForeignKey:project_flock_id;joinTableReferences:kandang_id" json:"kandangs,omitempty"` Kandangs []Kandang `gorm:"many2many:project_flock_kandangs;joinTableForeignKey:project_flock_id;joinTableReferences:kandang_id" json:"kandangs,omitempty"`
+5 -6
View File
@@ -104,12 +104,11 @@ func AuthenticatedUser(c *fiber.Ctx) (*entity.User, bool) {
} }
func ActorIDFromContext(c *fiber.Ctx) (uint, error) { func ActorIDFromContext(c *fiber.Ctx) (uint, error) {
// user, ok := AuthenticatedUser(c) user, ok := AuthenticatedUser(c)
// if !ok || user == nil || user.Id == 0 { if !ok || user == nil || user.Id == 0 {
// return 0, fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") return 0, fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
// } }
// return user.Id, nil return user.Id, nil
return 1, nil
} }
// AuthDetails returns the full authentication context (token, claims, user). // AuthDetails returns the full authentication context (token, claims, user).
+24
View File
@@ -162,8 +162,32 @@ const (
P_WarehousesCreateOne = "lti.master.warehouses.create" P_WarehousesCreateOne = "lti.master.warehouses.create"
P_WarehousesUpdateOne = "lti.master.warehouses.update" P_WarehousesUpdateOne = "lti.master.warehouses.update"
P_WarehousesDeleteOne = "lti.master.warehouses.delete" P_WarehousesDeleteOne = "lti.master.warehouses.delete"
P_Production_Standart_GetAll = "lti.master.production_standards.list"
P_Production_Standart_CreateOne = "lti.master.production_standards.create"
P_Production_Standart_GetOne = "lti.master.production_standards.detail"
P_Production_Standart_UpdateOne = "lti.master.production_standards.update"
P_Production_Standart_DeleteOne = "lti.master.production_standards.delete"
) )
// finance
const (
P_Finances_Initial_Balances_CreateOne = "lti.finance.initial_balances.create"
P_Finances_Initial_Balances_GetOne = "lti.finance.initial_balances.detail"
P_Finances_Initial_Balances_UpdateOne = "lti.finance.initial_balances.update"
P_Finances_Injections_CreateOne = "lti.finance.injections.create"
P_Finances_Injections_GetOne = "lti.finance.injections.detail"
P_Finances_Injections_UpdateOne = "lti.finance.injections.update"
P_Finances_Payments_CreateOne = "lti.finance.payments.create"
P_Finances_Payments_UpdateOne = "lti.finance.payments.update"
P_Finances_Payments_GetOne = "lti.finance.payments.detail"
P_Finances_Transaction_GetAll = "lti.finance.transactions.list"
P_Finances_Transaction_GetOne = "lti.finance.transactions.detail"
P_Finances_Transaction_DeleteOne = "lti.finance.transactions.delete"
)
const ( const (
P_ChickinsCreateOne = "lti.production.chickins.create" P_ChickinsCreateOne = "lti.production.chickins.create"
P_ChickinsGetOne = "lti.production.chickins.detail" P_ChickinsGetOne = "lti.production.chickins.detail"
+26 -24
View File
@@ -28,18 +28,19 @@ type ClosingDetailDTO struct {
} }
type ClosingListItemDTO struct { type ClosingListItemDTO struct {
Id uint `json:"id"` Id uint `json:"id"`
LocationID uint `json:"location_id"` ProjectName string `json:"project_name"`
LocationName string `json:"location_name"` LocationID uint `json:"location_id"`
ProjectCategory string `json:"project_category"` LocationName string `json:"location_name"`
Period int `json:"period"` ProjectCategory string `json:"project_category"`
ClosingDate string `json:"closing_date"` Period int `json:"period"`
ShedLabel string `json:"shed_label"` ClosingDate string `json:"closing_date"`
ShedCount int `json:"shed_count"` ShedLabel string `json:"shed_label"`
SalesPaidAmount int64 `json:"sales_paid_amount"` ShedCount int `json:"shed_count"`
SalesRemainingAmount int64 `json:"sales_remaining_amount"` // SalesPaidAmount int64 `json:"sales_paid_amount"`
SalesPaymentStatus string `json:"sales_payment_status"` // SalesRemainingAmount int64 `json:"sales_remaining_amount"`
ProjectStatus string `json:"project_status"` // SalesPaymentStatus string `json:"sales_payment_status"`
ProjectStatus string `json:"project_status"`
} }
type ClosingSummaryDTO struct { type ClosingSummaryDTO struct {
@@ -133,18 +134,19 @@ func ToClosingListItemDTO(project entity.ProjectFlock, projectStatus string) Clo
shedCount := len(project.KandangHistory) shedCount := len(project.KandangHistory)
return ClosingListItemDTO{ return ClosingListItemDTO{
Id: project.Id, Id: project.Id,
LocationID: project.LocationId, ProjectName: project.FlockName,
LocationName: project.Location.Name, LocationID: project.LocationId,
ProjectCategory: project.Category, LocationName: project.Location.Name,
Period: maxPeriod(project.KandangHistory), ProjectCategory: project.Category,
ClosingDate: "17-Nov-2025", Period: maxPeriod(project.KandangHistory),
ShedLabel: fmt.Sprintf("%d Kandang", shedCount), ClosingDate: "17-Nov-2025",
ShedCount: shedCount, ShedLabel: fmt.Sprintf("%d Kandang", shedCount),
SalesPaidAmount: 21993726, ShedCount: shedCount,
SalesRemainingAmount: 11075919, // SalesPaidAmount: 21993726,
SalesPaymentStatus: "Lunas", // SalesRemainingAmount: 11075919,
ProjectStatus: projectStatus, // SalesPaymentStatus: "Lunas",
ProjectStatus: projectStatus,
} }
} }
@@ -330,13 +330,33 @@ SELECT
COALESCE(p.po_number, '') AS reference_number, COALESCE(p.po_number, '') AS reference_number,
'Purchase' AS transaction_type, 'Purchase' AS transaction_type,
prod.name AS product_name, prod.name AS product_name,
pc.name AS product_category,
COALESCE(( COALESCE((
SELECT string_agg(f.name, ' ') SELECT string_agg(
f.name,
' ' ORDER BY
CASE
WHEN UPPER(f.name) IN ('DOC', 'PAKAN', 'OVK', 'PULLET') THEN 0
ELSE 1
END,
f.name
)
FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_category,
COALESCE((
SELECT string_agg(
f.name,
' ' ORDER BY
CASE
WHEN UPPER(f.name) IN ('DOC', 'PAKAN', 'OVK', 'PULLET') THEN 0
ELSE 1
END,
f.name
)
FROM flags f FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_sub_category, ), '') AS product_sub_category,
'External Supplier' AS source_warehouse, '-' AS source_warehouse,
w.name AS destination_warehouse, w.name AS destination_warehouse,
'' AS destination, '' AS destination,
pi.total_qty AS quantity, pi.total_qty AS quantity,
@@ -345,7 +365,6 @@ SELECT
FROM purchase_items pi FROM purchase_items pi
JOIN purchases p ON p.id = pi.purchase_id JOIN purchases p ON p.id = pi.purchase_id
JOIN products prod ON prod.id = pi.product_id JOIN products prod ON prod.id = pi.product_id
JOIN product_categories pc ON pc.id = prod.product_category_id
JOIN uoms u ON u.id = prod.uom_id JOIN uoms u ON u.id = prod.uom_id
JOIN warehouses w ON w.id = pi.warehouse_id JOIN warehouses w ON w.id = pi.warehouse_id
WHERE pi.warehouse_id IN ? WHERE pi.warehouse_id IN ?
@@ -359,9 +378,29 @@ SELECT
st.movement_number AS reference_number, st.movement_number AS reference_number,
'Internal Transfer In' AS transaction_type, 'Internal Transfer In' AS transaction_type,
prod.name AS product_name, prod.name AS product_name,
pc.name AS product_category,
COALESCE(( COALESCE((
SELECT string_agg(f.name, ' ') SELECT string_agg(
f.name,
' ' ORDER BY
CASE
WHEN UPPER(f.name) IN ('DOC', 'PAKAN', 'OVK', 'PULLET') THEN 0
ELSE 1
END,
f.name
)
FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_category,
COALESCE((
SELECT string_agg(
f.name,
' ' ORDER BY
CASE
WHEN UPPER(f.name) IN ('DOC', 'PAKAN', 'OVK', 'PULLET') THEN 0
ELSE 1
END,
f.name
)
FROM flags f FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_sub_category, ), '') AS product_sub_category,
@@ -376,7 +415,6 @@ JOIN stock_transfers st ON st.id = std.stock_transfer_id
LEFT JOIN warehouses fw ON fw.id = st.from_warehouse_id LEFT JOIN warehouses fw ON fw.id = st.from_warehouse_id
LEFT JOIN warehouses tw ON tw.id = st.to_warehouse_id LEFT JOIN warehouses tw ON tw.id = st.to_warehouse_id
JOIN products prod ON prod.id = std.product_id JOIN products prod ON prod.id = std.product_id
JOIN product_categories pc ON pc.id = prod.product_category_id
JOIN uoms u ON u.id = prod.uom_id JOIN uoms u ON u.id = prod.uom_id
WHERE st.to_warehouse_id IN ? WHERE st.to_warehouse_id IN ?
` `
@@ -389,9 +427,29 @@ SELECT
st.movement_number AS reference_number, st.movement_number AS reference_number,
'Internal Transfer Out' AS transaction_type, 'Internal Transfer Out' AS transaction_type,
prod.name AS product_name, prod.name AS product_name,
pc.name AS product_category,
COALESCE(( COALESCE((
SELECT string_agg(f.name, ' ') SELECT string_agg(
f.name,
' ' ORDER BY
CASE
WHEN UPPER(f.name) IN ('DOC', 'PAKAN', 'OVK', 'PULLET') THEN 0
ELSE 1
END,
f.name
)
FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_category,
COALESCE((
SELECT string_agg(
f.name,
' ' ORDER BY
CASE
WHEN UPPER(f.name) IN ('DOC', 'PAKAN', 'OVK', 'PULLET') THEN 0
ELSE 1
END,
f.name
)
FROM flags f FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_sub_category, ), '') AS product_sub_category,
@@ -406,7 +464,6 @@ JOIN stock_transfers st ON st.id = std.stock_transfer_id
LEFT JOIN warehouses fw ON fw.id = st.from_warehouse_id LEFT JOIN warehouses fw ON fw.id = st.from_warehouse_id
LEFT JOIN warehouses tw ON tw.id = st.to_warehouse_id LEFT JOIN warehouses tw ON tw.id = st.to_warehouse_id
JOIN products prod ON prod.id = std.product_id JOIN products prod ON prod.id = std.product_id
JOIN product_categories pc ON pc.id = prod.product_category_id
JOIN uoms u ON u.id = prod.uom_id JOIN uoms u ON u.id = prod.uom_id
WHERE st.from_warehouse_id IN ? WHERE st.from_warehouse_id IN ?
` `
@@ -419,9 +476,29 @@ SELECT
m.so_number AS reference_number, m.so_number AS reference_number,
'Trading Sales' AS transaction_type, 'Trading Sales' AS transaction_type,
prod.name AS product_name, prod.name AS product_name,
pc.name AS product_category,
COALESCE(( COALESCE((
SELECT string_agg(f.name, ' ') SELECT string_agg(
f.name,
' ' ORDER BY
CASE
WHEN UPPER(f.name) IN ('DOC', 'PAKAN', 'OVK', 'PULLET') THEN 0
ELSE 1
END,
f.name
)
FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_category,
COALESCE((
SELECT string_agg(
f.name,
' ' ORDER BY
CASE
WHEN UPPER(f.name) IN ('DOC', 'PAKAN', 'OVK', 'PULLET') THEN 0
ELSE 1
END,
f.name
)
FROM flags f FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_sub_category, ), '') AS product_sub_category,
@@ -435,7 +512,6 @@ FROM marketing_products mp
JOIN marketings m ON m.id = mp.marketing_id JOIN marketings m ON m.id = mp.marketing_id
JOIN product_warehouses pw ON pw.id = mp.product_warehouse_id JOIN product_warehouses pw ON pw.id = mp.product_warehouse_id
JOIN products prod ON prod.id = pw.product_id JOIN products prod ON prod.id = pw.product_id
JOIN product_categories pc ON pc.id = prod.product_category_id
JOIN uoms u ON u.id = prod.uom_id JOIN uoms u ON u.id = prod.uom_id
JOIN warehouses w ON w.id = pw.warehouse_id JOIN warehouses w ON w.id = pw.warehouse_id
WHERE pw.project_flock_kandang_id IN ? WHERE pw.project_flock_kandang_id IN ?
@@ -808,12 +884,12 @@ func (r *ClosingRepositoryImpl) FetchSapronakTransfers(ctx context.Context, kand
} }
type ActualUsageCostRow struct { type ActualUsageCostRow struct {
ProductID uint `gorm:"column:product_id"` ProductID uint `gorm:"column:product_id"`
ProductName string `gorm:"column:product_name"` ProductName string `gorm:"column:product_name"`
FlagName string `gorm:"column:flag_name"` FlagName string `gorm:"column:flag_name"`
TotalQty float64 `gorm:"column:total_qty"` TotalQty float64 `gorm:"column:total_qty"`
TotalPrice float64 `gorm:"column:total_price"` TotalPrice float64 `gorm:"column:total_price"`
AveragePrice float64 `gorm:"column:average_price"` AveragePrice float64 `gorm:"column:average_price"`
} }
func (r *ClosingRepositoryImpl) GetActualUsageCostByProjectFlockID(ctx context.Context, projectFlockID uint) ([]ActualUsageCostRow, error) { func (r *ClosingRepositoryImpl) GetActualUsageCostByProjectFlockID(ctx context.Context, projectFlockID uint) ([]ActualUsageCostRow, error) {
@@ -6,6 +6,7 @@ import (
"math" "math"
"strconv" "strconv"
"strings" "strings"
"time"
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"
@@ -332,18 +333,20 @@ func (s closingService) getApprovalStatuses(ctx context.Context, projectFlockID
} }
var ( var (
minStep uint16 minStep uint16
statusProject string statusProject string
completed int completed int
latestActionAt time.Time
) )
for _, rec := range records { for _, rec := range records {
if minStep == 0 || rec.StepNumber < minStep { if minStep == 0 || rec.StepNumber < minStep {
minStep = rec.StepNumber minStep = rec.StepNumber
statusProject = rec.StepName
} }
if rec.StepNumber == uint16(utils.ProjectFlockStepAktif) {
completed++ if latestActionAt.IsZero() || rec.ActionAt.After(latestActionAt) {
latestActionAt = rec.ActionAt
statusProject = rec.StepName
} }
} }
+5 -5
View File
@@ -1,7 +1,7 @@
package initials package initials
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/finance/initials/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/initials/controllers"
initial "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/initials/services" initial "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/initials/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,9 +13,9 @@ func InitialRoutes(v1 fiber.Router, u user.UserService, s initial.InitialService
ctrl := controller.NewInitialController(s) ctrl := controller.NewInitialController(s)
route := v1.Group("/initial-balances") route := v1.Group("/initial-balances")
// route.Use(m.Auth(u)) route.Use(m.Auth(u))
route.Post("/", ctrl.CreateOne) route.Post("/",m.RequirePermissions(m.P_Finances_Initial_Balances_CreateOne), ctrl.CreateOne)
route.Get("/:id", ctrl.GetOne) route.Get("/:id",m.RequirePermissions(m.P_Finances_Initial_Balances_GetOne), ctrl.GetOne)
route.Patch("/:id", ctrl.UpdateOne) route.Patch("/:id",m.RequirePermissions(m.P_Finances_Initial_Balances_UpdateOne), ctrl.UpdateOne)
} }
+5 -5
View File
@@ -1,7 +1,7 @@
package injections package injections
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/finance/injections/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/injections/controllers"
injection "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/injections/services" injection "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/injections/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,9 +13,9 @@ func InjectionRoutes(v1 fiber.Router, u user.UserService, s injection.InjectionS
ctrl := controller.NewInjectionController(s) ctrl := controller.NewInjectionController(s)
route := v1.Group("/injections") route := v1.Group("/injections")
// route.Use(m.Auth(u)) route.Use(m.Auth(u))
route.Post("/", ctrl.CreateOne) route.Post("/", m.RequirePermissions(m.P_Finances_Injections_CreateOne), ctrl.CreateOne)
route.Get("/:id", ctrl.GetOne) route.Get("/:id", m.RequirePermissions(m.P_Finances_Injections_GetOne), ctrl.GetOne)
route.Patch("/:id", ctrl.UpdateOne) route.Patch("/:id", m.RequirePermissions(m.P_Finances_Injections_UpdateOne), ctrl.UpdateOne)
} }
+5 -5
View File
@@ -1,7 +1,7 @@
package payments package payments
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/finance/payments/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/payments/controllers"
payment "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/payments/services" payment "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/payments/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,9 +13,9 @@ func PaymentRoutes(v1 fiber.Router, u user.UserService, s payment.PaymentService
ctrl := controller.NewPaymentController(s) ctrl := controller.NewPaymentController(s)
route := v1.Group("/payments") route := v1.Group("/payments")
// route.Use(m.Auth(u)) route.Use(m.Auth(u))
route.Post("/", ctrl.CreateOne) route.Post("/",m.RequirePermissions(m.P_Finances_Payments_CreateOne), ctrl.CreateOne)
route.Get("/:id", ctrl.GetOne) route.Get("/:id",m.RequirePermissions(m.P_Finances_Payments_GetOne), ctrl.GetOne)
route.Patch("/:id", ctrl.UpdateOne) route.Patch("/:id",m.RequirePermissions(m.P_Finances_Payments_UpdateOne), ctrl.UpdateOne)
} }
@@ -1,7 +1,7 @@
package transactions package transactions
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/finance/transactions/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/transactions/controllers"
transaction "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/transactions/services" transaction "gitlab.com/mbugroup/lti-api.git/internal/modules/finance/transactions/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -13,9 +13,9 @@ func TransactionRoutes(v1 fiber.Router, u user.UserService, s transaction.Transa
ctrl := controller.NewTransactionController(s) ctrl := controller.NewTransactionController(s)
route := v1.Group("/transactions") route := v1.Group("/transactions")
// route.Use(m.Auth(u)) route.Use(m.Auth(u))
route.Get("/", ctrl.GetAll) route.Get("/",m.RequirePermissions(m.P_Finances_Transaction_GetAll), ctrl.GetAll)
route.Get("/:id", ctrl.GetOne) route.Get("/:id",m.RequirePermissions(m.P_Finances_Transaction_GetOne), ctrl.GetOne)
route.Delete("/:id", ctrl.DeleteOne) route.Delete("/:id",m.RequirePermissions(m.P_Finances_Transaction_DeleteOne), ctrl.DeleteOne)
} }
@@ -117,39 +117,37 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
var createdLogId uint var createdLogId uint
isProductWarehouseExist, err := s.ProductWarehouseRepo.ProductWarehouseExistByProductAndWarehouseID(ctx, uint(req.ProductID), uint(req.WarehouseID)) var projectFlockKandangID *uint
if err != nil { pfk, err := s.ProjectFlockKandangRepo.GetActiveByKandangID(ctx, uint(req.WarehouseID))
s.Log.Errorf("Failed to check product warehouse existence: %+v", err) if err == nil && pfk != nil {
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to validate product warehouse") idCopy := uint(pfk.Id)
projectFlockKandangID = &idCopy
} }
if !isProductWarehouseExist {
projectFlockKandangID, err := s.getActiveProjectFlockKandangID(ctx, uint(req.WarehouseID)) pw, err := s.ProductWarehouseRepo.FindByProductWarehouseAndPfk(
if err != nil { ctx,
return nil, err uint(req.ProductID),
uint(req.WarehouseID),
projectFlockKandangID,
)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
s.Log.Errorf("Failed to find product warehouse: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to get product warehouse")
} }
newPW := &entity.ProductWarehouse{ newPW := &entity.ProductWarehouse{
ProductId: uint(req.ProductID), ProductId: uint(req.ProductID),
WarehouseId: uint(req.WarehouseID), WarehouseId: uint(req.WarehouseID),
Quantity: 0, Quantity: 0,
ProjectFlockKandangId: &projectFlockKandangID, ProjectFlockKandangId: projectFlockKandangID,
// CreatedBy: 1, // TODO: should Get from auth middleware
} }
if err := s.ProductWarehouseRepo.CreateOne(ctx, newPW, nil); err != nil { if err := s.ProductWarehouseRepo.CreateOne(ctx, newPW, nil); err != nil {
s.Log.Errorf("Failed to create product warehouse: %+v", err) s.Log.Errorf("Failed to create product warehouse: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to create product warehouse") return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to create product warehouse")
} }
s.Log.Infof("Product warehouse created: %+v", newPW.Id) pw = newPW
}
pw, err := s.ProductWarehouseRepo.GetProductWarehouseByProductAndWarehouseID(
ctx,
uint(req.ProductID),
uint(req.WarehouseID),
)
if err != nil {
s.Log.Errorf("Failed to get product warehouse for project flock check: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to validate product warehouse")
} }
if err := common.EnsureProjectFlockNotClosedForProductWarehouses( if err := common.EnsureProjectFlockNotClosedForProductWarehouses(
@@ -18,6 +18,7 @@ type ProductWarehouseRepository interface {
ProductWarehouseExistByProductAndWarehouseID(ctx context.Context, productId, warehouseId uint) (bool, error) ProductWarehouseExistByProductAndWarehouseID(ctx context.Context, productId, warehouseId uint) (bool, error)
ExistsByID(ctx context.Context, id uint) (bool, error) ExistsByID(ctx context.Context, id uint) (bool, error)
GetProductWarehouseByProductAndWarehouseID(ctx context.Context, productId, warehouseId uint) (*entity.ProductWarehouse, error) GetProductWarehouseByProductAndWarehouseID(ctx context.Context, productId, warehouseId uint) (*entity.ProductWarehouse, error)
FindByProductWarehouseAndPfk(ctx context.Context, productID uint, warehouseID uint, projectFlockKandangID *uint) (*entity.ProductWarehouse, error)
GetByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint) ([]entity.ProductWarehouse, error) GetByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint) ([]entity.ProductWarehouse, error)
GetLatestByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint, db *gorm.DB) (*entity.ProductWarehouse, error) GetLatestByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint, db *gorm.DB) (*entity.ProductWarehouse, error)
GetByFlagAndWarehouseID(ctx context.Context, flagName string, warehouseId uint) ([]entity.ProductWarehouse, error) GetByFlagAndWarehouseID(ctx context.Context, flagName string, warehouseId uint) ([]entity.ProductWarehouse, error)
@@ -107,6 +108,20 @@ func (r *ProductWarehouseRepositoryImpl) GetProductWarehouseByProductAndWarehous
return &productWarehouse, nil return &productWarehouse, nil
} }
func (r *ProductWarehouseRepositoryImpl) FindByProductWarehouseAndPfk(ctx context.Context, productID uint, warehouseID uint, projectFlockKandangID *uint) (*entity.ProductWarehouse, error) {
var productWarehouse entity.ProductWarehouse
err := r.DB().WithContext(ctx).
Where("product_id = ? AND warehouse_id = ? AND project_flock_kandang_id IS NOT DISTINCT FROM ?", productID, warehouseID, projectFlockKandangID).
First(&productWarehouse).Error
if err != nil {
return nil, err
}
return &productWarehouse, nil
}
func (r *ProductWarehouseRepositoryImpl) GetByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint) ([]entity.ProductWarehouse, error) { func (r *ProductWarehouseRepositoryImpl) GetByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint) ([]entity.ProductWarehouse, error) {
var productWarehouses []entity.ProductWarehouse var productWarehouses []entity.ProductWarehouse
q := r.DB().WithContext(ctx).Model(&entity.ProductWarehouse{}). q := r.DB().WithContext(ctx).Model(&entity.ProductWarehouse{}).
@@ -106,23 +106,17 @@ func (s transferService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entit
} }
func (s transferService) GetOne(c *fiber.Ctx, id uint) (*entity.StockTransfer, error) { func (s transferService) GetOne(c *fiber.Ctx, id uint) (*entity.StockTransfer, error) {
s.Log.Infof("Attempting to get StockTransfer with ID: %d", id)
transferPtr, err := s.StockTransferRepo.GetByID(c.Context(), id, func(db *gorm.DB) *gorm.DB { transferPtr, err := s.StockTransferRepo.GetByID(c.Context(), id, func(db *gorm.DB) *gorm.DB {
return s.withRelations(db) return s.withRelations(db)
}) })
if err != nil { if err != nil {
s.Log.Errorf("Error getting StockTransfer ID %d: %+v", id, err)
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "Transfer not found") return nil, fiber.NewError(fiber.StatusNotFound, "Transfer not found")
} }
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to get transfer") return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to get transfer")
} }
if transferPtr != nil {
s.Log.Infof("StockTransfer %d has %d documents", transferPtr.Id, len(transferPtr.Documents))
}
return transferPtr, nil return transferPtr, nil
} }
@@ -336,7 +330,9 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
Files: documentFiles, Files: documentFiles,
}) })
if err != nil { if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to upload document for delivery %d", idx+1)) s.Log.WithError(err).Errorf("Failed to upload document for delivery %d (delivery_id: %d, filename: %s)",
idx+1, deliveries[idx].Id, file.Filename)
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to upload document for delivery %d: %v", idx+1, err))
} }
} }
} }
@@ -396,7 +392,6 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
}) })
if err != nil { if err != nil {
s.Log.Errorf("Transaction failed in CreateOne: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to process transfer transaction: %v", err)) return nil, fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to process transfer transaction: %v", err))
} }
@@ -247,11 +247,15 @@ func (s *deliveryOrdersService) CreateOne(c *fiber.Ctx, req *validation.Delivery
itemDeliveryDate = &parsedDate itemDeliveryDate = &parsedDate
} }
// Hitung total_weight dan total_price otomatis
totalWeight := requestedProduct.Qty * requestedProduct.AvgWeight
totalPrice := requestedProduct.UnitPrice * requestedProduct.Qty
deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId
deliveryProduct.UnitPrice = requestedProduct.UnitPrice deliveryProduct.UnitPrice = requestedProduct.UnitPrice
deliveryProduct.AvgWeight = requestedProduct.AvgWeight deliveryProduct.AvgWeight = requestedProduct.AvgWeight
deliveryProduct.TotalWeight = requestedProduct.TotalWeight deliveryProduct.TotalWeight = totalWeight
deliveryProduct.TotalPrice = requestedProduct.TotalPrice deliveryProduct.TotalPrice = totalPrice
deliveryProduct.DeliveryDate = itemDeliveryDate deliveryProduct.DeliveryDate = itemDeliveryDate
deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber
@@ -357,11 +361,15 @@ func (s deliveryOrdersService) UpdateOne(c *fiber.Ctx, req *validation.DeliveryO
oldRequestedQty := deliveryProduct.UsageQty + deliveryProduct.PendingQty oldRequestedQty := deliveryProduct.UsageQty + deliveryProduct.PendingQty
// Hitung total_weight dan total_price otomatis
totalWeight := requestedProduct.Qty * requestedProduct.AvgWeight
totalPrice := requestedProduct.UnitPrice * requestedProduct.Qty
deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId
deliveryProduct.UnitPrice = requestedProduct.UnitPrice deliveryProduct.UnitPrice = requestedProduct.UnitPrice
deliveryProduct.AvgWeight = requestedProduct.AvgWeight deliveryProduct.AvgWeight = requestedProduct.AvgWeight
deliveryProduct.TotalWeight = requestedProduct.TotalWeight deliveryProduct.TotalWeight = totalWeight
deliveryProduct.TotalPrice = requestedProduct.TotalPrice deliveryProduct.TotalPrice = totalPrice
deliveryProduct.DeliveryDate = itemDeliveryDate deliveryProduct.DeliveryDate = itemDeliveryDate
deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber
@@ -75,7 +75,6 @@ func (s salesOrdersService) getOne(c *fiber.Ctx, id uint) (*entity.Marketing, er
return nil, fiber.NewError(fiber.StatusNotFound, "SalesOrders not found") return nil, fiber.NewError(fiber.StatusNotFound, "SalesOrders not found")
} }
if err != nil { if err != nil {
s.Log.Errorf("Failed get marketing by id: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch sales order") return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch sales order")
} }
@@ -293,13 +292,17 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
for _, rp := range req.MarketingProducts { for _, rp := range req.MarketingProducts {
if old, ok := oldByPW[rp.ProductWarehouseId]; ok { if old, ok := oldByPW[rp.ProductWarehouseId]; ok {
// Hitung total_weight dan total_price otomatis
totalWeight := rp.Qty * rp.AvgWeight
totalPrice := rp.UnitPrice * rp.Qty
updateBody := map[string]any{ updateBody := map[string]any{
"product_warehouse_id": rp.ProductWarehouseId, "product_warehouse_id": rp.ProductWarehouseId,
"qty": rp.Qty, "qty": rp.Qty,
"unit_price": rp.UnitPrice, "unit_price": rp.UnitPrice,
"avg_weight": rp.AvgWeight, "avg_weight": rp.AvgWeight,
"total_weight": rp.TotalWeight, "total_weight": totalWeight,
"total_price": rp.TotalPrice, "total_price": totalPrice,
} }
if err := marketingProductRepoTx.PatchOne(c.Context(), old.Id, updateBody, nil); err != nil { if err := marketingProductRepoTx.PatchOne(c.Context(), old.Id, updateBody, nil); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update marketing product") return fiber.NewError(fiber.StatusInternalServerError, "Failed to update marketing product")
@@ -589,30 +592,34 @@ func (s salesOrdersService) Approval(c *fiber.Ctx, req *validation.Approve) ([]e
func (s *salesOrdersService) createMarketingProductWithDelivery(ctx context.Context, marketingId uint, rp validation.CreateMarketingProduct, marketingProductRepo repository.MarketingProductRepository, invDeliveryRepo repository.MarketingDeliveryProductRepository) error { func (s *salesOrdersService) createMarketingProductWithDelivery(ctx context.Context, marketingId uint, rp validation.CreateMarketingProduct, marketingProductRepo repository.MarketingProductRepository, invDeliveryRepo repository.MarketingDeliveryProductRepository) error {
// Hitung total_weight dan total_price otomatis
totalWeight := rp.Qty * rp.AvgWeight
totalPrice := rp.UnitPrice * rp.Qty
marketingProduct := &entity.MarketingProduct{ marketingProduct := &entity.MarketingProduct{
MarketingId: marketingId, MarketingId: marketingId,
ProductWarehouseId: rp.ProductWarehouseId, ProductWarehouseId: rp.ProductWarehouseId,
Qty: rp.Qty, Qty: rp.Qty,
UnitPrice: rp.UnitPrice, UnitPrice: rp.UnitPrice,
AvgWeight: rp.AvgWeight, AvgWeight: rp.AvgWeight,
TotalWeight: rp.TotalWeight, TotalWeight: totalWeight,
TotalPrice: rp.TotalPrice, TotalPrice: totalPrice,
} }
if err := marketingProductRepo.CreateOne(ctx, marketingProduct, nil); err != nil { if err := marketingProductRepo.CreateOne(ctx, marketingProduct, nil); err != nil {
return err return err
} }
marketingDeliveryProduct := &entity.MarketingDeliveryProduct{ marketingDeliveryProduct := &entity.MarketingDeliveryProduct{
MarketingProductId: marketingProduct.Id, MarketingProductId: marketingProduct.Id,
ProductWarehouseId: marketingProduct.ProductWarehouseId, ProductWarehouseId: marketingProduct.ProductWarehouseId,
UnitPrice: 0, UnitPrice: 0,
TotalWeight: 0, TotalWeight: 0,
AvgWeight: 0, AvgWeight: 0,
TotalPrice: 0, TotalPrice: 0,
DeliveryDate: nil, DeliveryDate: nil,
VehicleNumber: rp.VehicleNumber, VehicleNumber: rp.VehicleNumber,
UsageQty: 0, UsageQty: 0,
PendingQty: 0, PendingQty: 0,
} }
if err := invDeliveryRepo.CreateOne(ctx, marketingDeliveryProduct, nil); err != nil { if err := invDeliveryRepo.CreateOne(ctx, marketingDeliveryProduct, nil); err != nil {
return err return err
@@ -5,8 +5,6 @@ type DeliveryProduct struct {
Qty float64 `json:"qty" validate:"omitempty,gte=0"` Qty float64 `json:"qty" validate:"omitempty,gte=0"`
UnitPrice float64 `json:"unit_price" validate:"omitempty,gte=0"` UnitPrice float64 `json:"unit_price" validate:"omitempty,gte=0"`
AvgWeight float64 `json:"avg_weight" validate:"omitempty,gte=0"` AvgWeight float64 `json:"avg_weight" validate:"omitempty,gte=0"`
TotalWeight float64 `json:"total_weight" validate:"omitempty,gte=0"`
TotalPrice float64 `json:"total_price" validate:"omitempty,gte=0"`
DeliveryDate string `json:"delivery_date" validate:"omitempty,datetime=2006-01-02"` DeliveryDate string `json:"delivery_date" validate:"omitempty,datetime=2006-01-02"`
VehicleNumber string `json:"vehicle_number" validate:"omitempty,max=50"` VehicleNumber string `json:"vehicle_number" validate:"omitempty,max=50"`
} }
@@ -12,10 +12,8 @@ type CreateMarketingProduct struct {
VehicleNumber string `json:"vehicle_number" validate:"required,min=1,max=50"` VehicleNumber string `json:"vehicle_number" validate:"required,min=1,max=50"`
ProductWarehouseId uint `json:"product_warehouse_id" validate:"required,gt=0"` ProductWarehouseId uint `json:"product_warehouse_id" validate:"required,gt=0"`
UnitPrice float64 `json:"unit_price" validate:"required,gt=0"` UnitPrice float64 `json:"unit_price" validate:"required,gt=0"`
TotalWeight float64 `json:"total_weight" validate:"required,gt=0"`
Qty float64 `json:"qty" validate:"required,gt=0"` Qty float64 `json:"qty" validate:"required,gt=0"`
AvgWeight float64 `json:"avg_weight" validate:"required,gt=0"` AvgWeight float64 `json:"avg_weight" validate:"required,gt=0"`
TotalPrice float64 `json:"total_price" validate:"required,gt=0"`
} }
type Update struct { type Update struct {
@@ -40,7 +40,7 @@ func (u *ProductionStandardController) GetAll(c *fiber.Ctx) error {
} }
return c.Status(fiber.StatusOK). return c.Status(fiber.StatusOK).
JSON(response.SuccessWithPaginate[dto.ProductionStandardListDTO]{ JSON(response.SuccessWithPaginate[dto.ProductionStandardRelationDTO]{
Code: fiber.StatusOK, Code: fiber.StatusOK,
Status: "success", Status: "success",
Message: "Get all productionStandards successfully", Message: "Get all productionStandards successfully",
@@ -7,7 +7,7 @@ import (
// === DTO Structs === // === DTO Structs ===
type ProductionStandardListDTO struct { type ProductionStandardRelationDTO struct {
Id uint `json:"id"` Id uint `json:"id"`
Name string `json:"name"` Name string `json:"name"`
ProjectCategory string `json:"project_category"` ProjectCategory string `json:"project_category"`
@@ -15,7 +15,7 @@ type ProductionStandardListDTO struct {
} }
type ProductionStandardDetailDTO struct { type ProductionStandardDetailDTO struct {
ProductionStandardListDTO ProductionStandardRelationDTO
Details []WeeklyProductionStandardDTO `json:"details"` Details []WeeklyProductionStandardDTO `json:"details"`
} }
@@ -33,6 +33,7 @@ type EggProductionStandardDetailDTO struct {
TargetHenHouseProduction *float64 `json:"target_hen_house_production"` TargetHenHouseProduction *float64 `json:"target_hen_house_production"`
TargetEggWeight *float64 `json:"target_egg_weight"` TargetEggWeight *float64 `json:"target_egg_weight"`
TargetEggMass *float64 `json:"target_egg_mass"` TargetEggMass *float64 `json:"target_egg_mass"`
StandardFCR *float64 `json:"standard_fcr"`
} }
type WeeklyProductionStandardDTO struct { type WeeklyProductionStandardDTO struct {
@@ -43,14 +44,14 @@ type WeeklyProductionStandardDTO struct {
// === Mapper Functions === // === Mapper Functions ===
func ToProductionStandardListDTO(e entity.ProductionStandard) ProductionStandardListDTO { func ToProductionStandardListDTO(e entity.ProductionStandard) ProductionStandardRelationDTO {
var createdUser *userDTO.UserRelationDTO var createdUser *userDTO.UserRelationDTO
if e.CreatedUser.Id != 0 { if e.CreatedUser.Id != 0 {
mapped := userDTO.ToUserRelationDTO(e.CreatedUser) mapped := userDTO.ToUserRelationDTO(e.CreatedUser)
createdUser = &mapped createdUser = &mapped
} }
return ProductionStandardListDTO{ return ProductionStandardRelationDTO{
Id: e.Id, Id: e.Id,
Name: e.Name, Name: e.Name,
ProjectCategory: e.ProjectCategory, ProjectCategory: e.ProjectCategory,
@@ -58,8 +59,16 @@ func ToProductionStandardListDTO(e entity.ProductionStandard) ProductionStandard
} }
} }
func ToProductionStandardListDTOs(e []entity.ProductionStandard) []ProductionStandardListDTO { func ToProductionStandardRelationDTO(e entity.ProductionStandard) ProductionStandardRelationDTO {
result := make([]ProductionStandardListDTO, len(e)) return ProductionStandardRelationDTO{
Id: e.Id,
Name: e.Name,
ProjectCategory: e.ProjectCategory,
}
}
func ToProductionStandardListDTOs(e []entity.ProductionStandard) []ProductionStandardRelationDTO {
result := make([]ProductionStandardRelationDTO, len(e))
for i, r := range e { for i, r := range e {
result[i] = ToProductionStandardListDTO(r) result[i] = ToProductionStandardListDTO(r)
} }
@@ -87,6 +96,7 @@ func ToWeeklyProductionStandardDTOWithDetails(growth entity.StandardGrowthDetail
TargetHenHouseProduction: detail.TargetHenHouseProduction, TargetHenHouseProduction: detail.TargetHenHouseProduction,
TargetEggWeight: detail.TargetEggWeight, TargetEggWeight: detail.TargetEggWeight,
TargetEggMass: detail.TargetEggMass, TargetEggMass: detail.TargetEggMass,
StandardFCR: detail.StandardFCR,
} }
return WeeklyProductionStandardDTO{ return WeeklyProductionStandardDTO{
@@ -140,6 +150,7 @@ func ToEggProductionStandardDetailDTO(e entity.ProductionStandardDetail) EggProd
TargetHenHouseProduction: e.TargetHenHouseProduction, TargetHenHouseProduction: e.TargetHenHouseProduction,
TargetEggWeight: e.TargetEggWeight, TargetEggWeight: e.TargetEggWeight,
TargetEggMass: e.TargetEggMass, TargetEggMass: e.TargetEggMass,
StandardFCR: e.StandardFCR,
} }
} }
@@ -149,7 +160,7 @@ func ToProductionStandardDetailDTO(
productionStandardDetails []entity.ProductionStandardDetail, productionStandardDetails []entity.ProductionStandardDetail,
) ProductionStandardDetailDTO { ) ProductionStandardDetailDTO {
return ProductionStandardDetailDTO{ return ProductionStandardDetailDTO{
ProductionStandardListDTO: ToProductionStandardListDTO(standard), ProductionStandardRelationDTO: ToProductionStandardRelationDTO(standard),
Details: ToWeeklyProductionStandardDTOsWithDetails(growthDetails, productionStandardDetails), Details: ToWeeklyProductionStandardDTOsWithDetails(growthDetails, productionStandardDetails),
} }
} }
@@ -15,9 +15,9 @@ func ProductionStandardRoutes(v1 fiber.Router, u user.UserService, s productionS
route := v1.Group("/production-standards") route := v1.Group("/production-standards")
route.Use(m.Auth(u)) route.Use(m.Auth(u))
route.Get("/", ctrl.GetAll) route.Get("/", m.RequirePermissions(m.P_Production_Standart_GetAll), ctrl.GetAll)
route.Post("/", ctrl.CreateOne) route.Post("/", m.RequirePermissions(m.P_Production_Standart_CreateOne), ctrl.CreateOne)
route.Get("/:id", ctrl.GetOne) route.Get("/:id", m.RequirePermissions(m.P_Production_Standart_GetOne), ctrl.GetOne)
route.Patch("/:id", ctrl.UpdateOne) route.Patch("/:id", m.RequirePermissions(m.P_Production_Standart_UpdateOne), ctrl.UpdateOne)
route.Delete("/:id", ctrl.DeleteOne) route.Delete("/:id", m.RequirePermissions(m.P_Production_Standart_DeleteOne), ctrl.DeleteOne)
} }
@@ -84,7 +84,6 @@ func (s productionStandardService) GetOne(c *fiber.Ctx, id uint) (*entity.Produc
return nil, fiber.NewError(fiber.StatusNotFound, "ProductionStandard not found") return nil, fiber.NewError(fiber.StatusNotFound, "ProductionStandard not found")
} }
if err != nil { if err != nil {
s.Log.Errorf("Failed get productionStandard by id: %+v", err)
return nil, err return nil, err
} }
return productionStandard, nil return productionStandard, nil
@@ -111,6 +110,7 @@ func (s *productionStandardService) CreateOne(c *fiber.Ctx, req *validation.Crea
var createdStandard *entity.ProductionStandard var createdStandard *entity.ProductionStandard
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error { err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
standardRepoTx := repository.NewProductionStandardRepository(tx) standardRepoTx := repository.NewProductionStandardRepository(tx)
productionStandardDetailRepoTx := repository.NewProductionStandardDetailRepository(tx) productionStandardDetailRepoTx := repository.NewProductionStandardDetailRepository(tx)
standardGrowthDetailRepoTx := repository.NewStandardGrowthDetailRepository(tx) standardGrowthDetailRepoTx := repository.NewStandardGrowthDetailRepository(tx)
@@ -142,6 +142,7 @@ func (s *productionStandardService) CreateOne(c *fiber.Ctx, req *validation.Crea
TargetHenHouseProduction: detailReq.ProductionStandardDetails.TargetHenHouseProduction, TargetHenHouseProduction: detailReq.ProductionStandardDetails.TargetHenHouseProduction,
TargetEggWeight: detailReq.ProductionStandardDetails.TargetEggWeight, TargetEggWeight: detailReq.ProductionStandardDetails.TargetEggWeight,
TargetEggMass: detailReq.ProductionStandardDetails.TargetEggMass, TargetEggMass: detailReq.ProductionStandardDetails.TargetEggMass,
StandardFCR: detailReq.ProductionStandardDetails.StandardFCR,
} }
if err := productionStandardDetailRepoTx.CreateOne(c.Context(), productionStandardDetail, nil); err != nil { if err := productionStandardDetailRepoTx.CreateOne(c.Context(), productionStandardDetail, nil); err != nil {
@@ -206,7 +207,6 @@ func (s productionStandardService) UpdateOne(c *fiber.Ctx, req *validation.Updat
nameExists, err := s.Repository.NameExists(c.Context(), *req.Name, &id) nameExists, err := s.Repository.NameExists(c.Context(), *req.Name, &id)
if err != nil { if err != nil {
s.Log.Errorf("Failed to check existing production standard: %+v", err)
return err return err
} }
if nameExists { if nameExists {
@@ -255,6 +255,7 @@ func (s productionStandardService) UpdateOne(c *fiber.Ctx, req *validation.Updat
TargetHenHouseProduction: detailReq.ProductionStandardDetails.TargetHenHouseProduction, TargetHenHouseProduction: detailReq.ProductionStandardDetails.TargetHenHouseProduction,
TargetEggWeight: detailReq.ProductionStandardDetails.TargetEggWeight, TargetEggWeight: detailReq.ProductionStandardDetails.TargetEggWeight,
TargetEggMass: detailReq.ProductionStandardDetails.TargetEggMass, TargetEggMass: detailReq.ProductionStandardDetails.TargetEggMass,
StandardFCR: detailReq.ProductionStandardDetails.StandardFCR,
} }
if err := productionStandardDetailRepoTx.CreateOne(c.Context(), productionStandardDetail, nil); err != nil { if err := productionStandardDetailRepoTx.CreateOne(c.Context(), productionStandardDetail, nil); err != nil {
@@ -283,7 +284,6 @@ func (s productionStandardService) UpdateOne(c *fiber.Ctx, req *validation.Updat
}) })
if err != nil { if err != nil {
s.Log.Errorf("Failed to update production standard: %+v", err)
return nil, err return nil, err
} }
@@ -295,7 +295,6 @@ func (s productionStandardService) DeleteOne(c *fiber.Ctx, id uint) error {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, "ProductionStandard not found") return fiber.NewError(fiber.StatusNotFound, "ProductionStandard not found")
} }
s.Log.Errorf("Failed to delete productionStandard: %+v", err)
return err return err
} }
return nil return nil
@@ -5,6 +5,7 @@ type ProductionStandardDetailItem struct {
TargetHenHouseProduction *float64 `json:"target_hen_house_production" validate:"omitempty,gte=0"` TargetHenHouseProduction *float64 `json:"target_hen_house_production" validate:"omitempty,gte=0"`
TargetEggWeight *float64 `json:"target_egg_weight" validate:"omitempty,gte=0"` TargetEggWeight *float64 `json:"target_egg_weight" validate:"omitempty,gte=0"`
TargetEggMass *float64 `json:"target_egg_mass" validate:"omitempty,gte=0"` TargetEggMass *float64 `json:"target_egg_mass" validate:"omitempty,gte=0"`
StandardFCR *float64 `json:"standard_fcr" validate:"omitempty,gte=0"`
} }
type StandardGrowthDetailItem struct { type StandardGrowthDetailItem struct {
@@ -70,6 +70,7 @@ func (s productService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity
products, total, err := s.Repository.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB { products, total, err := s.Repository.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB {
db = s.withRelations(db) db = s.withRelations(db)
db = db.Where("is_visible = ?", true)
if params.Search != "" { if params.Search != "" {
return db.Where("name LIKE ?", "%"+params.Search+"%") return db.Where("name LIKE ?", "%"+params.Search+"%")
} }
@@ -10,6 +10,7 @@ import (
fcrDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto" fcrDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto"
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto" kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto" locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
productionStandardDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/dto"
productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto" productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/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"
chickinDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/dto" chickinDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/dto"
@@ -30,6 +31,7 @@ type ProjectFlockDTO struct {
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"` Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
Category string `json:"category"` Category string `json:"category"`
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"` Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"`
ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"`
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"` Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"` CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
@@ -82,6 +84,7 @@ func toProjectFlockDTO(pf *projectFlockDTO.ProjectFlockListDTO) *ProjectFlockDTO
Area: pf.Area, Area: pf.Area,
Category: pf.Category, Category: pf.Category,
Fcr: pf.Fcr, Fcr: pf.Fcr,
ProductionStandard: pf.ProductionStandard,
Location: pf.Location, Location: pf.Location,
CreatedUser: pf.CreatedUser, CreatedUser: pf.CreatedUser,
CreatedAt: pf.CreatedAt, CreatedAt: pf.CreatedAt,
@@ -10,6 +10,7 @@ import (
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto" kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto" locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
nonstockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/nonstocks/dto" nonstockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/nonstocks/dto"
productionStandardDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/dto"
// pfutils "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/utils" // pfutils "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/utils"
userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto" userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
@@ -28,6 +29,7 @@ type ProjectFlockListDTO struct {
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"` Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
Category string `json:"category"` Category string `json:"category"`
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"` Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"`
ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"`
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"` Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
Kandangs []KandangWithProjectFlockIdDTO `json:"kandangs,omitempty"` Kandangs []KandangWithProjectFlockIdDTO `json:"kandangs,omitempty"`
ProjectBudgets []ProjectBudgetDTO `json:"project_budgets,omitempty"` ProjectBudgets []ProjectBudgetDTO `json:"project_budgets,omitempty"`
@@ -103,6 +105,12 @@ func ToProjectFlockListDTOWithPeriod(e entity.ProjectFlock, period int) ProjectF
fcrSummary = &mapped fcrSummary = &mapped
} }
var productionStandardSummary *productionStandardDTO.ProductionStandardRelationDTO
if e.ProductionStandard.Id != 0 {
mapped := productionStandardDTO.ToProductionStandardRelationDTO(e.ProductionStandard)
productionStandardSummary = &mapped
}
var locationSummary *locationDTO.LocationRelationDTO var locationSummary *locationDTO.LocationRelationDTO
if e.Location.Id != 0 { if e.Location.Id != 0 {
mapped := locationDTO.ToLocationRelationDTO(e.Location) mapped := locationDTO.ToLocationRelationDTO(e.Location)
@@ -122,6 +130,7 @@ func ToProjectFlockListDTOWithPeriod(e entity.ProjectFlock, period int) ProjectF
ProjectBudgets: ToProjectBudgetDTOs(e.Budgets), ProjectBudgets: ToProjectBudgetDTOs(e.Budgets),
Category: e.Category, Category: e.Category,
Fcr: fcrSummary, Fcr: fcrSummary,
ProductionStandard: productionStandardSummary,
Location: locationSummary, Location: locationSummary,
CreatedAt: e.CreatedAt, CreatedAt: e.CreatedAt,
UpdatedAt: e.UpdatedAt, UpdatedAt: e.UpdatedAt,
@@ -6,6 +6,7 @@ import (
fcrDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto" fcrDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto"
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto" kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto" locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
productionStandardDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/dto"
userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto" userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
) )
@@ -19,6 +20,7 @@ type ProjectFlockWithPivotDTO struct {
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"` Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
Category string `json:"category"` Category string `json:"category"`
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"` Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"`
ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"`
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"` Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
Kandangs []KandangWithPivotDTO `json:"kandangs,omitempty"` Kandangs []KandangWithPivotDTO `json:"kandangs,omitempty"`
CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"` CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"`
@@ -61,6 +63,10 @@ func ToProjectFlockKandangDTO(e entity.ProjectFlockKandang) ProjectFlockKandangD
mapped := fcrDTO.ToFcrRelationDTO(e.ProjectFlock.Fcr) mapped := fcrDTO.ToFcrRelationDTO(e.ProjectFlock.Fcr)
pfLocal.Fcr = &mapped pfLocal.Fcr = &mapped
} }
if e.ProjectFlock.ProductionStandard.Id != 0 {
mapped := productionStandardDTO.ToProductionStandardRelationDTO(e.ProjectFlock.ProductionStandard)
pfLocal.ProductionStandard = &mapped
}
if e.ProjectFlock.Location.Id != 0 { if e.ProjectFlock.Location.Id != 0 {
mapped := locationDTO.ToLocationRelationDTO(e.ProjectFlock.Location) mapped := locationDTO.ToLocationRelationDTO(e.ProjectFlock.Location)
pfLocal.Location = &mapped pfLocal.Location = &mapped
@@ -22,6 +22,7 @@ type ProjectflockRepository interface {
GetActiveByLocationID(ctx context.Context, locationID uint64) ([]entity.ProjectFlock, error) GetActiveByLocationID(ctx context.Context, locationID uint64) ([]entity.ProjectFlock, error)
AreaExists(ctx context.Context, id uint) (bool, error) AreaExists(ctx context.Context, id uint) (bool, error)
FcrExists(ctx context.Context, id uint) (bool, error) FcrExists(ctx context.Context, id uint) (bool, error)
ProductionStandardExists(ctx context.Context, id uint) (bool, error)
LocationExists(ctx context.Context, id uint) (bool, error) LocationExists(ctx context.Context, id uint) (bool, error)
} }
type KandangPeriodRow struct { type KandangPeriodRow struct {
@@ -52,6 +53,7 @@ func (r *ProjectflockRepositoryImpl) WithDefaultRelations() func(*gorm.DB) *gorm
Preload("CreatedUser"). Preload("CreatedUser").
Preload("Area"). Preload("Area").
Preload("Fcr"). Preload("Fcr").
Preload("ProductionStandard").
Preload("Location"). Preload("Location").
Preload("Kandangs"). Preload("Kandangs").
Preload("KandangHistory"). Preload("KandangHistory").
@@ -118,12 +120,14 @@ func (r *ProjectflockRepositoryImpl) applySearchFilters(db *gorm.DB, rawSearch s
return db. return db.
Joins("LEFT JOIN areas ON areas.id = project_flocks.area_id"). Joins("LEFT JOIN areas ON areas.id = project_flocks.area_id").
Joins("LEFT JOIN fcrs ON fcrs.id = project_flocks.fcr_id"). Joins("LEFT JOIN fcrs ON fcrs.id = project_flocks.fcr_id").
Joins("LEFT JOIN production_standards ON production_standards.id = project_flocks.production_standard_id").
Joins("LEFT JOIN locations ON locations.id = project_flocks.location_id"). Joins("LEFT JOIN locations ON locations.id = project_flocks.location_id").
Joins("LEFT JOIN users AS created_users ON created_users.id = project_flocks.created_by"). Joins("LEFT JOIN users AS created_users ON created_users.id = project_flocks.created_by").
Where(` Where(`
LOWER(areas.name) LIKE ? LOWER(areas.name) LIKE ?
OR LOWER(project_flocks.category) LIKE ? OR LOWER(project_flocks.category) LIKE ?
OR LOWER(fcrs.name) LIKE ? OR LOWER(fcrs.name) LIKE ?
OR LOWER(production_standards.name) LIKE ?
OR LOWER(locations.name) LIKE ? OR LOWER(locations.name) LIKE ?
OR LOWER(locations.address) LIKE ? OR LOWER(locations.address) LIKE ?
OR LOWER(created_users.name) LIKE ? OR LOWER(created_users.name) LIKE ?
@@ -153,6 +157,7 @@ func (r *ProjectflockRepositoryImpl) applySearchFilters(db *gorm.DB, rawSearch s
likeQuery, likeQuery,
likeQuery, likeQuery,
likeQuery, likeQuery,
likeQuery,
) )
} }
@@ -164,6 +169,10 @@ func (r *ProjectflockRepositoryImpl) FcrExists(ctx context.Context, id uint) (bo
return repository.Exists[entity.Fcr](ctx, r.DB(), id) return repository.Exists[entity.Fcr](ctx, r.DB(), id)
} }
func (r *ProjectflockRepositoryImpl) ProductionStandardExists(ctx context.Context, id uint) (bool, error) {
return repository.Exists[entity.ProductionStandard](ctx, r.DB(), id)
}
func (r *ProjectflockRepositoryImpl) LocationExists(ctx context.Context, id uint) (bool, error) { func (r *ProjectflockRepositoryImpl) LocationExists(ctx context.Context, id uint) (bool, error) {
return repository.Exists[entity.Location](ctx, r.DB(), id) return repository.Exists[entity.Location](ctx, r.DB(), id)
} }
@@ -249,6 +249,7 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
if err := commonSvc.EnsureRelations(c.Context(), if err := commonSvc.EnsureRelations(c.Context(),
commonSvc.RelationCheck{Name: "Area", ID: &req.AreaId, Exists: s.Repository.AreaExists}, commonSvc.RelationCheck{Name: "Area", ID: &req.AreaId, Exists: s.Repository.AreaExists},
commonSvc.RelationCheck{Name: "FCR", ID: &req.FcrId, Exists: s.Repository.FcrExists}, commonSvc.RelationCheck{Name: "FCR", ID: &req.FcrId, Exists: s.Repository.FcrExists},
commonSvc.RelationCheck{Name: "Production Standard", ID: &req.ProductionStandardId, Exists: s.Repository.ProductionStandardExists},
commonSvc.RelationCheck{Name: "Location", ID: &req.LocationId, Exists: s.Repository.LocationExists}, commonSvc.RelationCheck{Name: "Location", ID: &req.LocationId, Exists: s.Repository.LocationExists},
); err != nil { ); err != nil {
return nil, err return nil, err
@@ -300,6 +301,7 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
AreaId: req.AreaId, AreaId: req.AreaId,
Category: cat, Category: cat,
FcrId: req.FcrId, FcrId: req.FcrId,
ProductionStandardId: req.ProductionStandardId,
LocationId: req.LocationId, LocationId: req.LocationId,
CreatedBy: actorID, CreatedBy: actorID,
} }
@@ -1,13 +1,14 @@
package validation package validation
type Create struct { type Create struct {
FlockName string `json:"flock_name" validate:"required_strict"` FlockName string `json:"flock_name" 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"`
Category string `json:"category" validate:"required_strict"` Category string `json:"category" validate:"required_strict"`
FcrId uint `json:"fcr_id" validate:"required_strict,number,gt=0"` FcrId uint `json:"fcr_id" validate:"required_strict,number,gt=0"`
LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"` ProductionStandardId uint `json:"production_standard_id" validate:"required_strict,number,gt=0"`
KandangIds []uint `json:"kandang_ids" validate:"required,min=1,dive,gt=0"` LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"`
ProjectBudgets []ProjectBudget `json:"project_budgets" validate:"required,min=1,dive"` KandangIds []uint `json:"kandang_ids" validate:"required,min=1,dive,gt=0"`
ProjectBudgets []ProjectBudget `json:"project_budgets" validate:"required,min=1,dive"`
} }
type Query struct { type Query struct {