Merge branch 'feat/BE/US-279/closing-produksi' into 'feat/BE/Sprint-6'

Feat/be/us 279/closing produksi

See merge request mbugroup/lti-api!93
This commit is contained in:
Hafizh A. Y.
2025-12-10 14:39:00 +00:00
6 changed files with 46 additions and 24 deletions
@@ -0,0 +1,2 @@
ALTER TABLE purchases
DROP COLUMN IF EXISTS credit_term;
@@ -0,0 +1,5 @@
ALTER TABLE purchases
ADD COLUMN IF NOT EXISTS credit_term INT NOT NULL DEFAULT 0;
ALTER TABLE purchases
ALTER COLUMN credit_term DROP DEFAULT;
+3 -2
View File
@@ -5,17 +5,18 @@ import (
)
type Purchase struct {
Id uint `gorm:"primaryKey;autoIncrement"`
Id uint `gorm:"primaryKey;autoIncrement"`
PrNumber string `gorm:"not null"`
PoNumber *string
PoDate *time.Time
SupplierId uint `gorm:"not null"`
CreditTerm int `gorm:"column:credit_term;not null;default:0"`
DueDate *time.Time
Notes *string
CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"`
DeletedAt *time.Time `gorm:"index"`
CreatedBy uint `gorm:"not null"`
CreatedBy uint `gorm:"not null"`
// Relations
Supplier Supplier `gorm:"foreignKey:SupplierId;references:Id"`
+12 -10
View File
@@ -14,11 +14,12 @@ import (
)
type PurchaseRelationDTO struct {
Id uint `json:"id"`
PrNumber string `json:"pr_number"`
PoNumber *string `json:"po_number"`
PoDate *time.Time `json:"po_date"`
Notes *string `json:"notes"`
Id uint `json:"id"`
PrNumber string `json:"pr_number"`
PoNumber *string `json:"po_number"`
PoDate *time.Time `json:"po_date"`
CreditTerm int `json:"credit_term"`
Notes *string `json:"notes"`
}
type PurchaseListDTO struct {
@@ -64,11 +65,12 @@ type PurchaseItemDTO struct {
func ToPurchaseRelationDTO(p *entity.Purchase) PurchaseRelationDTO {
return PurchaseRelationDTO{
Id: p.Id,
PrNumber: p.PrNumber,
PoNumber: p.PoNumber,
PoDate: p.PoDate,
Notes: p.Notes,
Id: p.Id,
PrNumber: p.PrNumber,
PoNumber: p.PoNumber,
PoDate: p.PoDate,
CreditTerm: p.CreditTerm,
Notes: p.Notes,
}
}
@@ -309,21 +309,17 @@ func (s *purchaseService) CreateOne(c *fiber.Ctx, req *validation.CreatePurchase
indexMap[key] = len(aggregated) - 1
}
// var dueDate *time.Time
// if req.DueDate != nil && strings.TrimSpace(*req.DueDate) != "" {
// parsed, err := utils.ParseDateString(strings.TrimSpace(*req.DueDate))
// if err != nil {
// return nil, utils.BadRequest("Invalid due_date, expected YYYY-MM-DD")
// }
// parsed = parsed.UTC()
// dueDate = &parsed
// }
var dueDate *time.Time
now := time.Now().UTC()
d := now.AddDate(0, 0, req.CreditTerm)
dueDate = &d
purchase := &entity.Purchase{
SupplierId: uint(req.SupplierID),
// DueDate: dueDate,
Notes: req.Notes,
CreatedBy: uint(actorID),
CreditTerm: req.CreditTerm,
DueDate: dueDate,
Notes: req.Notes,
CreatedBy: uint(actorID),
}
items := make([]*entity.PurchaseItem, 0, len(aggregated))
@@ -683,6 +679,7 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
visitedItems := make(map[uint]struct{}, len(req.Items))
prepared := make([]preparedReceiving, 0, len(req.Items))
var earliestReceived *time.Time
for _, payload := range req.Items {
item, exists := itemMap[payload.PurchaseItemID]
if !exists {
@@ -694,6 +691,10 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
return nil, utils.BadRequest(fmt.Sprintf("Invalid received_date for item %d", payload.PurchaseItemID))
}
receivedDate = receivedDate.UTC()
if earliestReceived == nil || receivedDate.Before(*earliestReceived) {
copy := receivedDate
earliestReceived = &copy
}
warehouseID := uint(item.WarehouseId)
overrideWarehouse := false
@@ -869,6 +870,16 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
return err
}
// Update due_date based on earliest received date when receiving approved.
if earliestReceived != nil {
due := earliestReceived.AddDate(0, 0, purchase.CreditTerm)
if err := tx.Model(&entity.Purchase{}).
Where("id = ?", purchase.Id).
Update("due_date", due).Error; err != nil {
return err
}
}
if s.FifoSvc != nil {
for _, adj := range fifoAdds {
if adj.pwID == 0 || adj.qty <= 0 {
@@ -8,6 +8,7 @@ type PurchaseItemPayload struct {
type CreatePurchaseRequest struct {
SupplierID uint `json:"supplier_id" validate:"required,gt=0"`
CreditTerm int `json:"credit_term" validate:"required,number,gte=0"`
DueDate *string `json:"due_date,omitempty" validate:"omitempty,datetime=2006-01-02"`
Notes *string `json:"notes" validate:"omitempty,max=500"`
Items []PurchaseItemPayload `json:"items" validate:"required,min=1,dive"`