feat: update status field validation in inventory DTOs and add completed constant
Deploy Application / deploy (push) Successful in 37s
Details
Deploy Application / deploy (push) Successful in 37s
Details
This commit is contained in:
parent
2676a20026
commit
14eccfb336
|
|
@ -26,7 +26,7 @@ type InventoryIssueCreateRequest struct {
|
||||||
IssuerBy string `json:"issuer_by"`
|
IssuerBy string `json:"issuer_by"`
|
||||||
InvRequestID string `json:"inv_request_id"`
|
InvRequestID string `json:"inv_request_id"`
|
||||||
ClientID string `json:"client_id" binding:"required"`
|
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"`
|
IssueLines []InventoryIssueLineCreateRequest `json:"issue_lines,omitempty" binding:"dive"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ type InventoryMovementCreateRequest struct {
|
||||||
MovementDate string `json:"movement_date"`
|
MovementDate string `json:"movement_date"`
|
||||||
MovementType string `json:"movement_type"`
|
MovementType string `json:"movement_type"`
|
||||||
ClientID string `json:"client_id" binding:"required"`
|
ClientID string `json:"client_id" binding:"required"`
|
||||||
Status string `json:"status" binding:"required"`
|
Status string `json:"status"`
|
||||||
SourceLocationID string `json:"source_location_id"`
|
SourceLocationID string `json:"source_location_id"`
|
||||||
DestinationLocationID string `json:"destination_location_id"`
|
DestinationLocationID string `json:"destination_location_id"`
|
||||||
MovementLines []InventoryMovementLineCreateRequest `json:"movement_lines,omitempty" binding:"dive"`
|
MovementLines []InventoryMovementLineCreateRequest `json:"movement_lines,omitempty" binding:"dive"`
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ type InventoryReceiptCreateRequest struct {
|
||||||
Source string `json:"source"`
|
Source string `json:"source"`
|
||||||
QrCodeFile string `json:"qr_code_file"`
|
QrCodeFile string `json:"qr_code_file"`
|
||||||
ClientID string `json:"client_id" binding:"required"`
|
ClientID string `json:"client_id" binding:"required"`
|
||||||
Status string `json:"status" binding:"required"`
|
Status string `json:"status"`
|
||||||
ReceiptLines []InventoryReceiptLineCreateRequest `json:"inventory_lines,omitempty" binding:"dive"`
|
ReceiptLines []InventoryReceiptLineCreateRequest `json:"receipt_lines,omitempty" binding:"dive"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type InventoryReceiptLineCreateRequest struct {
|
type InventoryReceiptLineCreateRequest struct {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ type InventoryRequestCreateRequest struct {
|
||||||
RequestType string `json:"request_type"`
|
RequestType string `json:"request_type"`
|
||||||
Note string `json:"note"`
|
Note string `json:"note"`
|
||||||
ClientID string `json:"client_id" binding:"required"`
|
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"`
|
RequestLines []InventoryRequestLineCreateRequest `json:"request_lines,omitempty" binding:"dive"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,11 @@ package dto
|
||||||
import (
|
import (
|
||||||
"errors"
|
"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"
|
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
|
||||||
|
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -164,3 +168,146 @@ type (
|
||||||
InvMoveRef string `json:"inv_move_ref,omitempty"`
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,7 @@ import (
|
||||||
"github.com/Caknoooo/go-gin-clean-starter/modules/product/dto"
|
"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/query"
|
||||||
"github.com/Caknoooo/go-gin-clean-starter/modules/product/repository"
|
"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/google/uuid"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -148,7 +145,7 @@ func (s *productService) GetById(ctx context.Context, productId string) (dto.Pro
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dto.ProductResponse{}, err
|
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) {
|
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
|
var responses []dto.ProductResponse
|
||||||
for _, p := range products {
|
for _, p := range products {
|
||||||
responses = append(responses, mapProductToResponse(p))
|
responses = append(responses, dto.MapProductToResponse(p))
|
||||||
}
|
}
|
||||||
if len(responses) == 0 {
|
if len(responses) == 0 {
|
||||||
responses = []dto.ProductResponse{} // <-- pastikan slice kosong, bukan nil
|
responses = []dto.ProductResponse{} // <-- pastikan slice kosong, bukan nil
|
||||||
|
|
@ -322,148 +319,3 @@ func parseUUID(id string) uuid.UUID {
|
||||||
}
|
}
|
||||||
return u
|
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,5 @@ const (
|
||||||
JWTService = "JWTService"
|
JWTService = "JWTService"
|
||||||
LOGGER = "logger"
|
LOGGER = "logger"
|
||||||
SUPERADMIN = "superadmin"
|
SUPERADMIN = "superadmin"
|
||||||
|
COMPLETED = "completed"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue