feat: update status field validation in inventory DTOs and add completed constant
Deploy Application / deploy (push) Successful in 37s Details

This commit is contained in:
Habib Fatkhul Rohman 2025-11-24 14:57:41 +07:00
parent 2676a20026
commit 14eccfb336
7 changed files with 163 additions and 163 deletions

View File

@ -26,7 +26,7 @@ type InventoryIssueCreateRequest struct {
IssuerBy string `json:"issuer_by"`
InvRequestID string `json:"inv_request_id"`
ClientID string `json:"client_id" binding:"required"`
Status string `json:"status" binding:"required"`
Status string `json:"status"`
IssueLines []InventoryIssueLineCreateRequest `json:"issue_lines,omitempty" binding:"dive"`
}

View File

@ -29,7 +29,7 @@ type InventoryMovementCreateRequest struct {
MovementDate string `json:"movement_date"`
MovementType string `json:"movement_type"`
ClientID string `json:"client_id" binding:"required"`
Status string `json:"status" binding:"required"`
Status string `json:"status"`
SourceLocationID string `json:"source_location_id"`
DestinationLocationID string `json:"destination_location_id"`
MovementLines []InventoryMovementLineCreateRequest `json:"movement_lines,omitempty" binding:"dive"`

View File

@ -26,8 +26,8 @@ type InventoryReceiptCreateRequest struct {
Source string `json:"source"`
QrCodeFile string `json:"qr_code_file"`
ClientID string `json:"client_id" binding:"required"`
Status string `json:"status" binding:"required"`
ReceiptLines []InventoryReceiptLineCreateRequest `json:"inventory_lines,omitempty" binding:"dive"`
Status string `json:"status"`
ReceiptLines []InventoryReceiptLineCreateRequest `json:"receipt_lines,omitempty" binding:"dive"`
}
type InventoryReceiptLineCreateRequest struct {

View File

@ -27,7 +27,7 @@ type InventoryRequestCreateRequest struct {
RequestType string `json:"request_type"`
Note string `json:"note"`
ClientID string `json:"client_id" binding:"required"`
Status string `json:"status" binding:"required"`
Status string `json:"status"`
RequestLines []InventoryRequestLineCreateRequest `json:"request_lines,omitempty" binding:"dive"`
}

View File

@ -3,7 +3,11 @@ package dto
import (
"errors"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid"
)
const (
@ -164,3 +168,146 @@ type (
InvMoveRef string `json:"inv_move_ref,omitempty"`
}
)
func MapProductToResponse(product entities.MProductEntity) ProductResponse {
crossRefs := make([]ProductVendorResponse, 0, len(product.CrossReferences))
for _, v := range product.CrossReferences {
crossRefs = append(crossRefs, ProductVendorResponse{
ID: v.Vendor.ID.String(),
Name: v.Vendor.Name,
Address: v.Vendor.Address,
ContactPerson: v.Vendor.ContactPerson,
SearchKey: v.Vendor.SearchKey,
})
}
invTransactions := make([]ProductInventoryTransactionResponse, 0, len(product.InventoryTransactions))
for _, it := range product.InventoryTransactions {
var transactionQuantity float64
var lot, locater, invReceiptRef, invIssueRef, invMoveRef string
var transactionDate string
valid := false
// Receipt
if it.InvReceipt.ID != uuid.Nil && it.InvReceipt.Status == constants.COMPLETED {
invReceiptRef = it.InvReceipt.ReferenceNumber
transactionDate = utils.DateTimeToString(it.TransactionDate)
for _, line := range it.InvReceipt.ReceiptLines {
if line.ProductID == it.ProductID {
transactionQuantity = line.Quantity
lot = line.BatchNumber
valid = true
break
}
}
}
// Issue
if it.InvIssue.ID != uuid.Nil && it.InvIssue.Status == constants.COMPLETED {
invIssueRef = it.InvIssue.DocumentNumber
transactionDate = utils.DateTimeToString(it.TransactionDate)
for _, line := range it.InvIssue.IssueLines {
if line.ProductID == it.ProductID {
transactionQuantity = line.IssuedQuantity
valid = true
break
}
}
}
// Move
if it.InvMove.ID != uuid.Nil && it.InvMove.Status == constants.COMPLETED {
invMoveRef = it.InvMove.MovementNumber
transactionDate = utils.DateTimeToString(it.TransactionDate)
for _, line := range it.InvMove.MovementLines {
if line.ProductID == it.ProductID {
transactionQuantity = line.MovedQuantity
valid = true
break
}
}
}
if valid {
invTransactions = append(invTransactions, ProductInventoryTransactionResponse{
ID: it.ID.String(),
TransactionDate: transactionDate,
TransactionType: it.TransactionType,
TransactionQuantity: transactionQuantity,
Lot: lot,
Locater: locater,
InvReceiptRef: invReceiptRef,
InvIssueRef: invIssueRef,
InvMoveRef: invMoveRef,
})
}
}
return ProductResponse{
ID: product.ID.String(),
Name: product.Name,
RefNumber: product.RefNumber,
SKU: product.SKU,
Description: product.Description,
Status: product.Status,
IsReturnable: product.IsReturnable,
DimLength: product.DimLength,
DimWidth: product.DimWidth,
DimHeight: product.DimHeight,
Weight: product.Weight,
Volume: product.Volume,
MaxStackHeight: product.MaxStackHeight,
Temperature: product.Temperature,
IsHazardous: product.IsHazardous,
MinStock: product.MinStock,
MaxStock: product.MaxStock,
ReplenishType: product.ReplenishType,
CycleCount: product.CycleCount,
LotRules: product.LotRules,
LeadTime: product.LeadTime,
MultiplyRate: product.MultiplyRate,
DivideRate: product.DivideRate,
Client: pkgdto.IdNameResponse{
ID: product.Client.ID.String(),
Name: product.Client.Name,
},
Category: pkgdto.IdNameResponse{
ID: product.Category.ID.String(),
Name: product.Category.Name,
},
Uom: pkgdto.IdNameResponse{
ID: product.Uom.ID.String(),
Name: product.Uom.Name,
},
DimUom: pkgdto.IdNameResponse{
ID: product.DimUom.ID.String(),
Name: product.DimUom.Name,
},
WeightUom: pkgdto.IdNameResponse{
ID: product.WeightUom.ID.String(),
Name: product.WeightUom.Name,
},
VolumeUom: pkgdto.IdNameResponse{
ID: product.VolumeUom.ID.String(),
Name: product.VolumeUom.Name,
},
MinStockUom: pkgdto.IdNameResponse{
ID: product.MinStockUom.ID.String(),
Name: product.MinStockUom.Name,
},
MaxStockUom: pkgdto.IdNameResponse{
ID: product.MaxStockUom.ID.String(),
Name: product.MaxStockUom.Name,
},
LeadTimeUom: pkgdto.IdNameResponse{
ID: product.LeadTimeUom.ID.String(),
Name: product.LeadTimeUom.Name,
},
UomToUom: pkgdto.IdNameResponse{
ID: product.UomToUom.ID.String(),
Name: product.UomToUom.Name,
},
CrossReferences: crossRefs,
InvTransactions: invTransactions,
}
}

View File

@ -7,10 +7,7 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/product/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/product/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/product/repository"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
@ -148,7 +145,7 @@ func (s *productService) GetById(ctx context.Context, productId string) (dto.Pro
if err != nil {
return dto.ProductResponse{}, err
}
return mapProductToResponse(product), nil
return dto.MapProductToResponse(product), nil
}
func (s *productService) GetAll(ctx context.Context, filter query.ProductFilter) ([]dto.ProductResponse, int64, error) {
@ -158,7 +155,7 @@ func (s *productService) GetAll(ctx context.Context, filter query.ProductFilter)
}
var responses []dto.ProductResponse
for _, p := range products {
responses = append(responses, mapProductToResponse(p))
responses = append(responses, dto.MapProductToResponse(p))
}
if len(responses) == 0 {
responses = []dto.ProductResponse{} // <-- pastikan slice kosong, bukan nil
@ -322,148 +319,3 @@ func parseUUID(id string) uuid.UUID {
}
return u
}
func mapProductToResponse(product entities.MProductEntity) dto.ProductResponse {
crossRefs := make([]dto.ProductVendorResponse, 0, len(product.CrossReferences))
for _, v := range product.CrossReferences {
crossRefs = append(crossRefs, dto.ProductVendorResponse{
ID: v.Vendor.ID.String(),
Name: v.Vendor.Name,
Address: v.Vendor.Address,
ContactPerson: v.Vendor.ContactPerson,
SearchKey: v.Vendor.SearchKey,
})
}
logrus.Infof("Inventory Transactions Count: %d", len(product.InventoryTransactions))
invTransactions := make([]dto.ProductInventoryTransactionResponse, 0, len(product.InventoryTransactions))
for _, it := range product.InventoryTransactions {
var transactionQuantity float64
var lot, locater, invReceiptRef, invIssueRef, invMoveRef string
var transactionDate string
// Receipt
if it.InvReceipt.ID != uuid.Nil {
invReceiptRef = it.InvReceipt.ReferenceNumber
transactionDate = utils.DateTimeToString(it.TransactionDate)
// Cari line yang sesuai product
for _, line := range it.InvReceipt.ReceiptLines {
if line.ProductID == it.ProductID {
transactionQuantity = line.Quantity
lot = line.BatchNumber
// Jika ada field lokasi, isi di sini
// locater = line.Locater
break
}
}
}
// Issue
if it.InvIssue.ID != uuid.Nil {
invIssueRef = it.InvIssue.DocumentNumber
transactionDate = utils.DateTimeToString(it.TransactionDate)
for _, line := range it.InvIssue.IssueLines {
if line.ProductID == it.ProductID {
transactionQuantity = line.IssuedQuantity
// lot = line.BatchNumber
// locater = line.Locater
break
}
}
}
// Move
if it.InvMove.ID != uuid.Nil {
invMoveRef = it.InvMove.MovementNumber
transactionDate = utils.DateTimeToString(it.TransactionDate)
for _, line := range it.InvMove.MovementLines {
if line.ProductID == it.ProductID {
transactionQuantity = line.MovedQuantity
// lot = line.BatchNumber
// locater = line.Locater
break
}
}
}
invTransactions = append(invTransactions, dto.ProductInventoryTransactionResponse{
ID: it.ID.String(),
TransactionDate: transactionDate,
TransactionType: it.TransactionType,
TransactionQuantity: transactionQuantity,
Lot: lot,
Locater: locater,
InvReceiptRef: invReceiptRef,
InvIssueRef: invIssueRef,
InvMoveRef: invMoveRef,
})
}
return dto.ProductResponse{
ID: product.ID.String(),
Name: product.Name,
RefNumber: product.RefNumber,
SKU: product.SKU,
Description: product.Description,
Status: product.Status,
IsReturnable: product.IsReturnable,
DimLength: product.DimLength,
DimWidth: product.DimWidth,
DimHeight: product.DimHeight,
Weight: product.Weight,
Volume: product.Volume,
MaxStackHeight: product.MaxStackHeight,
Temperature: product.Temperature,
IsHazardous: product.IsHazardous,
MinStock: product.MinStock,
MaxStock: product.MaxStock,
ReplenishType: product.ReplenishType,
CycleCount: product.CycleCount,
LotRules: product.LotRules,
LeadTime: product.LeadTime,
MultiplyRate: product.MultiplyRate,
DivideRate: product.DivideRate,
Client: pkgdto.IdNameResponse{
ID: product.Client.ID.String(),
Name: product.Client.Name,
},
Category: pkgdto.IdNameResponse{
ID: product.Category.ID.String(),
Name: product.Category.Name,
},
Uom: pkgdto.IdNameResponse{
ID: product.Uom.ID.String(),
Name: product.Uom.Name,
},
DimUom: pkgdto.IdNameResponse{
ID: product.DimUom.ID.String(),
Name: product.DimUom.Name,
},
WeightUom: pkgdto.IdNameResponse{
ID: product.WeightUom.ID.String(),
Name: product.WeightUom.Name,
},
VolumeUom: pkgdto.IdNameResponse{
ID: product.VolumeUom.ID.String(),
Name: product.VolumeUom.Name,
},
MinStockUom: pkgdto.IdNameResponse{
ID: product.MinStockUom.ID.String(),
Name: product.MinStockUom.Name,
},
MaxStockUom: pkgdto.IdNameResponse{
ID: product.MaxStockUom.ID.String(),
Name: product.MaxStockUom.Name,
},
LeadTimeUom: pkgdto.IdNameResponse{
ID: product.LeadTimeUom.ID.String(),
Name: product.LeadTimeUom.Name,
},
UomToUom: pkgdto.IdNameResponse{
ID: product.UomToUom.ID.String(),
Name: product.UomToUom.Name,
},
CrossReferences: crossRefs,
InvTransactions: invTransactions,
}
}

View File

@ -14,4 +14,5 @@ const (
JWTService = "JWTService"
LOGGER = "logger"
SUPERADMIN = "superadmin"
COMPLETED = "completed"
)