mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
fix[BE]: fix logic pengambilan quatity untuk chick in dan penggunaan helper common
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
DROP TABLE IF EXISTS stock_availabilities;
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
CREATE TABLE stock_availabilities (
|
|
||||||
id BIGSERIAL PRIMARY KEY,
|
|
||||||
entity_type VARCHAR(50) NOT NULL,
|
|
||||||
entity_id BIGINT NOT NULL,
|
|
||||||
product_id BIGINT,
|
|
||||||
quantity NUMERIC(15, 3) NOT NULL DEFAULT 0,
|
|
||||||
reserved_quantity NUMERIC(15, 3) NOT NULL DEFAULT 0,
|
|
||||||
unit VARCHAR(20),
|
|
||||||
last_updated TIMESTAMPTZ DEFAULT now(),
|
|
||||||
created_at TIMESTAMPTZ DEFAULT now(),
|
|
||||||
deleted_at TIMESTAMPTZ
|
|
||||||
);
|
|
||||||
|
|
||||||
ALTER TABLE stock_availabilities
|
|
||||||
ADD CONSTRAINT fk_product_id FOREIGN KEY (product_id) REFERENCES products (id);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
DROP TABLE IF EXISTS audit_logs;
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
CREATE TABLE audit_logs (
|
|
||||||
id BIGSERIAL PRIMARY KEY,
|
|
||||||
table_name VARCHAR(100) NOT NULL,
|
|
||||||
record_id BIGINT NOT NULL,
|
|
||||||
action VARCHAR(30) NOT NULL,
|
|
||||||
before_data JSONB,
|
|
||||||
after_data JSONB,
|
|
||||||
changed_by BIGINT,
|
|
||||||
created_at TIMESTAMPTZ DEFAULT now()
|
|
||||||
);
|
|
||||||
|
|
||||||
ALTER TABLE audit_logs
|
|
||||||
ADD CONSTRAINT fk_changed_by FOREIGN KEY (changed_by) REFERENCES users (id);
|
|
||||||
@@ -49,8 +49,8 @@ func (u *AdjustmentController) AdjustmentHistory(c *fiber.Ctx) error {
|
|||||||
query := &validation.Query{
|
query := &validation.Query{
|
||||||
Page: c.QueryInt("page", 1),
|
Page: c.QueryInt("page", 1),
|
||||||
Limit: c.QueryInt("limit", 10),
|
Limit: c.QueryInt("limit", 10),
|
||||||
ProductID: c.QueryInt("product_id", 0),
|
ProductID: uint(c.QueryInt("product_id", 0)),
|
||||||
WarehouseID: c.QueryInt("warehouse_id", 0),
|
WarehouseID: uint(c.QueryInt("warehouse_id", 0)),
|
||||||
TransactionType: c.Query("transaction_type", ""),
|
TransactionType: c.Query("transaction_type", ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
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"
|
||||||
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"
|
||||||
@@ -77,22 +79,11 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
|
|||||||
}
|
}
|
||||||
ctx := c.Context()
|
ctx := c.Context()
|
||||||
|
|
||||||
isProductExist, err := s.ProductRepo.IdExists(c.Context(), uint(req.ProductID))
|
if err := common.EnsureRelations(c.Context(),
|
||||||
if err != nil {
|
common.RelationCheck{Name: "Product", ID: &req.ProductID, Exists: s.ProductRepo.IdExists},
|
||||||
s.Log.Errorf("Failed to check product existence: %+v", err)
|
common.RelationCheck{Name: "Warehouse", ID: &req.WarehouseID, Exists: s.WarehouseRepo.IdExists},
|
||||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to validate product")
|
); err != nil {
|
||||||
}
|
return nil, err
|
||||||
if !isProductExist {
|
|
||||||
return nil, fiber.NewError(fiber.StatusNotFound, "Product not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
isWarehouseExist, err := s.WarehouseRepo.IdExists(c.Context(), uint(req.WarehouseID))
|
|
||||||
if err != nil {
|
|
||||||
s.Log.Errorf("Failed to check warehouse existence: %+v", err)
|
|
||||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to validate warehouse")
|
|
||||||
}
|
|
||||||
if !isWarehouseExist {
|
|
||||||
return nil, fiber.NewError(fiber.StatusNotFound, "Warehouse not found")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Quantity <= 0 {
|
if req.Quantity <= 0 {
|
||||||
@@ -118,6 +109,7 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
|
|||||||
Quantity: 0,
|
Quantity: 0,
|
||||||
CreatedBy: 1, // TODO: should Get from auth middleware
|
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")
|
||||||
@@ -126,7 +118,6 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = s.StockLogsRepository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
err = s.StockLogsRepository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||||
|
|
||||||
productWarehouse, err := s.ProductWarehouseRepo.GetProductWarehouseByProductAndWarehouseID(ctx, uint(req.ProductID), uint(req.WarehouseID))
|
productWarehouse, err := s.ProductWarehouseRepo.GetProductWarehouseByProductAndWarehouseID(ctx, uint(req.ProductID), uint(req.WarehouseID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log.Errorf("Failed to get product warehouse: %+v", err)
|
s.Log.Errorf("Failed to get product warehouse: %+v", err)
|
||||||
@@ -159,14 +150,12 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
|
|||||||
s.Log.Errorf("Failed to create stock log: %+v", err)
|
s.Log.Errorf("Failed to create stock log: %+v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Log.Infof("Stock log created: %+v", newLog.Id)
|
|
||||||
|
|
||||||
productWarehouse.Quantity = afterQuantity
|
productWarehouse.Quantity = afterQuantity
|
||||||
if err := s.ProductWarehouseRepo.WithTx(tx).UpdateOne(ctx, productWarehouse.Id, productWarehouse, nil); err != nil {
|
if err := s.ProductWarehouseRepo.WithTx(tx).UpdateOne(ctx, productWarehouse.Id, productWarehouse, nil); err != nil {
|
||||||
s.Log.Errorf("Failed to update product warehouse quantity: %+v", err)
|
s.Log.Errorf("Failed to update product warehouse quantity: %+v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Log.Infof("Product warehouse quantity updated: %+v", productWarehouse.Id)
|
|
||||||
|
|
||||||
createdLogId = newLog.Id
|
createdLogId = newLog.Id
|
||||||
return nil
|
return nil
|
||||||
@@ -184,7 +173,6 @@ func (s *adjustmentService) AdjustmentHistory(c *fiber.Ctx, query *validation.Qu
|
|||||||
if err := s.Validate.Struct(query); err != nil {
|
if err := s.Validate.Struct(query); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
offset := (query.Page - 1) * query.Limit
|
offset := (query.Page - 1) * query.Limit
|
||||||
|
|
||||||
isWarehousesExist, err := s.WarehouseRepo.IdExists(c.Context(), uint(query.WarehouseID))
|
isWarehousesExist, err := s.WarehouseRepo.IdExists(c.Context(), uint(query.WarehouseID))
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ type Create struct {
|
|||||||
type Query struct {
|
type Query struct {
|
||||||
Page int `query:"page" validate:"omitempty,min=1"`
|
Page int `query:"page" validate:"omitempty,min=1"`
|
||||||
Limit int `query:"limit" validate:"omitempty,min=1,max=100"`
|
Limit int `query:"limit" validate:"omitempty,min=1,max=100"`
|
||||||
ProductID int `query:"product_id" validate:"omitempty,min=0"`
|
ProductID uint `query:"product_id" validate:"omitempty,min=0"`
|
||||||
WarehouseID int `query:"warehouse_id" validate:"omitempty,min=0"`
|
WarehouseID uint `query:"warehouse_id" validate:"omitempty,min=0"`
|
||||||
TransactionType string `query:"transaction_type" validate:"omitempty,oneof=increase decrease"`
|
TransactionType string `query:"transaction_type" validate:"omitempty,oneof=increase decrease"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,27 +132,33 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit
|
|||||||
s.Log.Errorf("Failed to get project flock: %+v", err)
|
s.Log.Errorf("Failed to get project flock: %+v", err)
|
||||||
return nil, fiber.NewError(fiber.StatusNotFound, "Project Flock not found")
|
return nil, fiber.NewError(fiber.StatusNotFound, "Project Flock not found")
|
||||||
}
|
}
|
||||||
|
var productWarehouses []entity.ProductWarehouse
|
||||||
var productWarehouse entity.ProductWarehouse
|
|
||||||
err = s.ProductWarehouseRepo.DB().
|
err = s.ProductWarehouseRepo.DB().
|
||||||
WithContext(c.Context()).
|
WithContext(c.Context()).
|
||||||
Joins("JOIN products ON products.id = product_warehouses.product_id").
|
Joins("JOIN products ON products.id = product_warehouses.product_id").
|
||||||
Joins("JOIN product_categories ON product_categories.id = products.product_category_id").
|
Joins("JOIN product_categories ON product_categories.id = products.product_category_id").
|
||||||
Where("product_categories.code = ? AND product_warehouses.warehouse_id = ?", projectFlock.ProductCategory.Code, warehouse.Id).
|
Where("product_categories.code = ? AND product_warehouses.warehouse_id = ?", projectFlock.ProductCategory.Code, warehouse.Id).
|
||||||
Order("created_at DESC").
|
Order("created_at DESC").
|
||||||
First(&productWarehouse).Error
|
Find(&productWarehouses).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
s.Log.Errorf("Failed to get product warehouses: %+v", err)
|
||||||
return nil, fiber.NewError(fiber.StatusNotFound, "Product Warehouse not found for the given Project Flock and Warehouse")
|
|
||||||
}
|
|
||||||
s.Log.Errorf("Failed to get product warehouse: %+v", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(productWarehouses) == 0 {
|
||||||
if productWarehouse.Quantity < 1 {
|
return nil, fiber.NewError(fiber.StatusNotFound, "Product Warehouse not found for the given Project Flock and Warehouse")
|
||||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Insufficient product quantity in warehouse")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Jumlahkan semua quantity DOC
|
||||||
|
totalQuantity := 0.0
|
||||||
|
for _, pw := range productWarehouses {
|
||||||
|
totalQuantity += pw.Quantity
|
||||||
|
}
|
||||||
|
|
||||||
|
if totalQuantity < 1 {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Insufficient quantity in Product Warehouses")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat satu chickin dengan total quantity
|
||||||
chickinDate, err := utils.ParseDateString(req.ChickInDate)
|
chickinDate, err := utils.ParseDateString(req.ChickInDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log.Errorf("Failed to parse chickin date: %+v", err)
|
s.Log.Errorf("Failed to parse chickin date: %+v", err)
|
||||||
@@ -161,9 +167,9 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit
|
|||||||
newChickin := &entity.ProjectChickin{
|
newChickin := &entity.ProjectChickin{
|
||||||
ProjectFlockKandangId: projectflockkandang.ProjectFlockId,
|
ProjectFlockKandangId: projectflockkandang.ProjectFlockId,
|
||||||
ChickInDate: chickinDate,
|
ChickInDate: chickinDate,
|
||||||
Quantity: productWarehouse.Quantity,
|
Quantity: totalQuantity,
|
||||||
Note: "",
|
Note: "",
|
||||||
CreatedBy: 1, //todo: ganti dengan
|
CreatedBy: 1, //todo: ganti dengan user login
|
||||||
}
|
}
|
||||||
err = s.Repository.CreateOne(c.Context(), newChickin, nil)
|
err = s.Repository.CreateOne(c.Context(), newChickin, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -171,16 +177,15 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedQuantity := productWarehouse.Quantity - newChickin.Quantity
|
// Update semua product warehouse: set quantity jadi 0
|
||||||
if updatedQuantity < 0 {
|
for _, pw := range productWarehouses {
|
||||||
updatedQuantity = 0
|
err = s.ProductWarehouseRepo.PatchOne(c.Context(), pw.Id, map[string]any{
|
||||||
}
|
"quantity": 0,
|
||||||
err = s.ProductWarehouseRepo.PatchOne(c.Context(), productWarehouse.Id, map[string]any{
|
}, nil)
|
||||||
"quantity": updatedQuantity,
|
if err != nil {
|
||||||
}, nil)
|
s.Log.Errorf("Failed to update product warehouse quantity: %+v", err)
|
||||||
if err != nil {
|
return nil, err
|
||||||
s.Log.Errorf("Failed to update product warehouse quantity: %+v", err)
|
}
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
existingPopulation, err := s.ProjectflockPopulationRepo.GetByProjectFlockKandangID(c.Context(), req.ProjectFlockKandangId)
|
existingPopulation, err := s.ProjectflockPopulationRepo.GetByProjectFlockKandangID(c.Context(), req.ProjectFlockKandangId)
|
||||||
|
|||||||
Reference in New Issue
Block a user