mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
feat(BE): add file size validation and improve document indexing for transfer creation
This commit is contained in:
@@ -75,6 +75,8 @@ func (u *TransferController) GetOne(c *fiber.Ctx) error {
|
|||||||
func (u *TransferController) CreateOne(c *fiber.Ctx) error {
|
func (u *TransferController) CreateOne(c *fiber.Ctx) error {
|
||||||
data := c.FormValue("data")
|
data := c.FormValue("data")
|
||||||
|
|
||||||
|
const maxFileSize = 5 * 1024 * 1024
|
||||||
|
|
||||||
var req validation.TransferRequest
|
var req validation.TransferRequest
|
||||||
if err := json.Unmarshal([]byte(data), &req); err != nil {
|
if err := json.Unmarshal([]byte(data), &req); err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||||
@@ -87,9 +89,11 @@ func (u *TransferController) CreateOne(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
files := form.File["documents"]
|
files := form.File["documents"]
|
||||||
|
|
||||||
if len(files) != len(req.Deliveries) {
|
for i, file := range files {
|
||||||
return fiber.NewError(fiber.StatusBadRequest,
|
if file.Size > maxFileSize {
|
||||||
fiber.NewError(fiber.StatusBadRequest, "Jumlah dokumen harus sama dengan jumlah deliveries").Message)
|
return fiber.NewError(fiber.StatusBadRequest,
|
||||||
|
"Dokumen ke-"+strconv.Itoa(i+1)+" melebihi ukuran maksimal 5MB")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := u.TransferService.CreateOne(c, &req, files)
|
result, err := u.TransferService.CreateOne(c, &req, files)
|
||||||
|
|||||||
@@ -128,7 +128,6 @@ func (s transferService) GetOne(c *fiber.Ctx, id uint) (*entity.StockTransfer, e
|
|||||||
|
|
||||||
func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferRequest, files []*multipart.FileHeader) (*entity.StockTransfer, error) {
|
func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferRequest, files []*multipart.FileHeader) (*entity.StockTransfer, error) {
|
||||||
|
|
||||||
// === VALIDASI SOURCE WAREHOUSE ===
|
|
||||||
pwIDs := make([]uint, 0, len(req.Products))
|
pwIDs := make([]uint, 0, len(req.Products))
|
||||||
|
|
||||||
for _, product := range req.Products {
|
for _, product := range req.Products {
|
||||||
@@ -201,7 +200,6 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
|||||||
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Supplier dengan ID %d bukan kategori BOP", delivery.SupplierID))
|
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Supplier dengan ID %d bukan kategori BOP", delivery.SupplierID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
seqNum, err := s.StockTransferRepo.GetNextMovementNumber(c.Context())
|
seqNum, err := s.StockTransferRepo.GetNextMovementNumber(c.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to generate movement number")
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to generate movement number")
|
||||||
@@ -226,12 +224,11 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare details and fetch product warehouses
|
|
||||||
details := make([]*entity.StockTransferDetail, 0, len(req.Products))
|
details := make([]*entity.StockTransferDetail, 0, len(req.Products))
|
||||||
detailMap := make(map[uint64]*entity.StockTransferDetail)
|
detailMap := make(map[uint64]*entity.StockTransferDetail)
|
||||||
|
|
||||||
for _, product := range req.Products {
|
for _, product := range req.Products {
|
||||||
// Get source product warehouse
|
|
||||||
sourcePW, err := s.ProductWarehouseRepo.GetProductWarehouseByProductAndWarehouseID(
|
sourcePW, err := s.ProductWarehouseRepo.GetProductWarehouseByProductAndWarehouseID(
|
||||||
c.Context(), uint(product.ProductID), uint(req.SourceWarehouseID),
|
c.Context(), uint(product.ProductID), uint(req.SourceWarehouseID),
|
||||||
)
|
)
|
||||||
@@ -242,7 +239,6 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
|||||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data product warehouse source")
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data product warehouse source")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get or create destination product warehouse
|
|
||||||
destPW, err := s.ProductWarehouseRepo.GetProductWarehouseByProductAndWarehouseID(
|
destPW, err := s.ProductWarehouseRepo.GetProductWarehouseByProductAndWarehouseID(
|
||||||
c.Context(), uint(product.ProductID), uint(req.DestinationWarehouseID),
|
c.Context(), uint(product.ProductID), uint(req.DestinationWarehouseID),
|
||||||
)
|
)
|
||||||
@@ -323,24 +319,38 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
|||||||
|
|
||||||
if s.DocumentSvc != nil && len(files) > 0 {
|
if s.DocumentSvc != nil && len(files) > 0 {
|
||||||
|
|
||||||
for idx, file := range files {
|
for deliveryIdx, delivery := range deliveries {
|
||||||
|
reqDelivery := req.Deliveries[deliveryIdx]
|
||||||
|
|
||||||
|
if reqDelivery.DocumentIndex < 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if reqDelivery.DocumentIndex >= len(files) {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest,
|
||||||
|
fmt.Sprintf("DocumentIndex %d untuk delivery %d melebihi jumlah file yang diupload (%d)",
|
||||||
|
reqDelivery.DocumentIndex, deliveryIdx+1, len(files)))
|
||||||
|
}
|
||||||
|
|
||||||
|
file := files[reqDelivery.DocumentIndex]
|
||||||
|
|
||||||
documentFiles := []commonSvc.DocumentFile{
|
documentFiles := []commonSvc.DocumentFile{
|
||||||
{
|
{
|
||||||
File: file,
|
File: file,
|
||||||
Type: string(utils.DocumentTypeTransfer),
|
Type: string(utils.DocumentTypeTransfer),
|
||||||
Index: &idx,
|
Index: &reqDelivery.DocumentIndex,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := s.DocumentSvc.UploadDocuments(c.Context(), commonSvc.DocumentUploadRequest{
|
_, err := s.DocumentSvc.UploadDocuments(c.Context(), commonSvc.DocumentUploadRequest{
|
||||||
DocumentableType: string(utils.DocumentableTypeTransfer),
|
DocumentableType: string(utils.DocumentableTypeTransfer),
|
||||||
DocumentableID: deliveries[idx].Id,
|
DocumentableID: delivery.Id,
|
||||||
CreatedBy: &actorID,
|
CreatedBy: &actorID,
|
||||||
Files: documentFiles,
|
Files: documentFiles,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log.WithError(err).Errorf("Failed to upload document for delivery %d (delivery_id: %d, filename: %s)",
|
s.Log.WithError(err).Errorf("Failed to upload document for delivery %d (delivery_id: %d, filename: %s)",
|
||||||
idx+1, deliveries[idx].Id, file.Filename)
|
deliveryIdx+1, delivery.Id, file.Filename)
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to upload document for delivery %d: %v", idx+1, err))
|
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to upload document for delivery %d: %v", deliveryIdx+1, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type TransferDeliveryProduct struct {
|
|||||||
type TransferDelivery struct {
|
type TransferDelivery struct {
|
||||||
DeliveryCost float64 `json:"delivery_cost" validate:"required"`
|
DeliveryCost float64 `json:"delivery_cost" validate:"required"`
|
||||||
DeliveryCostPerItem float64 `json:"delivery_cost_per_item" validate:"required"`
|
DeliveryCostPerItem float64 `json:"delivery_cost_per_item" validate:"required"`
|
||||||
DocumentIndex int `json:"document_index" validate:"min=0"`
|
DocumentIndex int `json:"document_index" validate:"omitempty,min=-1" default:"-1"`
|
||||||
DriverName string `json:"driver_name" validate:"required"`
|
DriverName string `json:"driver_name" validate:"required"`
|
||||||
VehiclePlate string `json:"vehicle_plate" validate:"required"`
|
VehiclePlate string `json:"vehicle_plate" validate:"required"`
|
||||||
SupplierID uint `json:"supplier_id" validate:"required"`
|
SupplierID uint `json:"supplier_id" validate:"required"`
|
||||||
|
|||||||
Reference in New Issue
Block a user