mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-23 23:05:44 +00:00
Merge branch 'staging' into 'production'
Revert "Merge branch 'staging' into 'development'" See merge request mbugroup/lti-api!225
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
# .air.toml
|
||||||
|
root = "."
|
||||||
|
tmp_dir = "tmp"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
cmd = "go build -buildvcs=false -o ./tmp/main ./cmd/api"
|
||||||
|
bin = "tmp/main"
|
||||||
|
full_bin = "APP_ENV=dev ./tmp/main"
|
||||||
|
include_ext = ["go", "tpl", "tmpl", "html"]
|
||||||
|
exclude_dir = ["vendor", "tmp"]
|
||||||
|
|
||||||
|
[log]
|
||||||
|
time = true
|
||||||
@@ -237,6 +237,8 @@ func (u *ClosingController) GetClosingSapronak(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
query := &validation.ClosingSapronakQuery{
|
query := &validation.ClosingSapronakQuery{
|
||||||
Type: strings.ToLower(c.Query("type")),
|
Type: strings.ToLower(c.Query("type")),
|
||||||
|
Page: c.QueryInt("page", 1),
|
||||||
|
Limit: c.QueryInt("limit", 10),
|
||||||
Search: c.Query("search"),
|
Search: c.Query("search"),
|
||||||
}
|
}
|
||||||
if raw := c.Query("kandang_id"); raw != "" {
|
if raw := c.Query("kandang_id"); raw != "" {
|
||||||
@@ -248,6 +250,10 @@ func (u *ClosingController) GetClosingSapronak(c *fiber.Ctx) error {
|
|||||||
query.KandangID = &kandangUint
|
query.KandangID = &kandangUint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if query.Page < 1 || query.Limit < 1 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
|
||||||
|
}
|
||||||
|
|
||||||
if query.Type != validation.SapronakTypeIncoming && query.Type != validation.SapronakTypeOutgoing {
|
if query.Type != validation.SapronakTypeIncoming && query.Type != validation.SapronakTypeOutgoing {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "type must be either incoming or outgoing")
|
return fiber.NewError(fiber.StatusBadRequest, "type must be either incoming or outgoing")
|
||||||
}
|
}
|
||||||
@@ -282,8 +288,6 @@ func (u *ClosingController) GetClosingSapronakSummary(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
query := &validation.ClosingSapronakQuery{
|
query := &validation.ClosingSapronakQuery{
|
||||||
Type: strings.ToLower(c.Query("type")),
|
Type: strings.ToLower(c.Query("type")),
|
||||||
Page: c.QueryInt("page", 1),
|
|
||||||
Limit: c.QueryInt("limit", 10),
|
|
||||||
Search: c.Query("search"),
|
Search: c.Query("search"),
|
||||||
}
|
}
|
||||||
if raw := c.Query("kandang_id"); raw != "" {
|
if raw := c.Query("kandang_id"); raw != "" {
|
||||||
@@ -295,10 +299,6 @@ func (u *ClosingController) GetClosingSapronakSummary(c *fiber.Ctx) error {
|
|||||||
query.KandangID = &kandangUint
|
query.KandangID = &kandangUint
|
||||||
}
|
}
|
||||||
|
|
||||||
if query.Page < 1 || query.Limit < 1 {
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
if query.Type != validation.SapronakTypeIncoming && query.Type != validation.SapronakTypeOutgoing {
|
if query.Type != validation.SapronakTypeIncoming && query.Type != validation.SapronakTypeOutgoing {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "type must be either incoming or outgoing")
|
return fiber.NewError(fiber.StatusBadRequest, "type must be either incoming or outgoing")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ func ClosingRoutes(v1 fiber.Router, u user.UserService, s closing.ClosingService
|
|||||||
route.Get("/:project_flock_id/:project_flock_kandang_id/perhitungan_sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetSapronakByKandang)
|
route.Get("/:project_flock_id/:project_flock_kandang_id/perhitungan_sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetSapronakByKandang)
|
||||||
route.Get("/:project_flock_id/perhitungan_sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetSapronakByProject)
|
route.Get("/:project_flock_id/perhitungan_sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetSapronakByProject)
|
||||||
route.Get("/:projectFlockId/sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetClosingSapronak)
|
route.Get("/:projectFlockId/sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetClosingSapronak)
|
||||||
|
route.Get("/:projectFlockId/sapronak/summary", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetClosingSapronakSummary)
|
||||||
route.Get("/:project_flock_id/expedition-hpp", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetExpeditionHPP)
|
route.Get("/:project_flock_id/expedition-hpp", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetExpeditionHPP)
|
||||||
route.Get("/:project_flock_id/:project_flock_kandang_id/expedition-hpp", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetExpeditionHPPByKandang)
|
route.Get("/:project_flock_id/:project_flock_kandang_id/expedition-hpp", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetExpeditionHPPByKandang)
|
||||||
route.Get("/:projectFlockId/production-data", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetClosingDataProduksi)
|
route.Get("/:projectFlockId/production-data", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetClosingDataProduksi)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ type SummaryQuery struct {
|
|||||||
|
|
||||||
type ReportQuery struct {
|
type ReportQuery struct {
|
||||||
Page int `query:"page" validate:"required,number,min=1,gt=0"`
|
Page int `query:"page" validate:"required,number,min=1,gt=0"`
|
||||||
Limit int `query:"limit" validate:"required,number,min=1,max=100,gt=0"`
|
Limit int `query:"limit" validate:"required,number,min=1,gt=0"`
|
||||||
Month int `query:"bulan" validate:"required,number,min=1,max=12"`
|
Month int `query:"bulan" validate:"required,number,min=1,max=12"`
|
||||||
Year int `query:"tahun" validate:"required,number,min=1900"`
|
Year int `query:"tahun" validate:"required,number,min=1900"`
|
||||||
AreaID *uint `query:"area_id" validate:"omitempty"`
|
AreaID *uint `query:"area_id" validate:"omitempty"`
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ func (s *configChecklistService) CreateOne(c *fiber.Ctx, req *validation.Create)
|
|||||||
if err := s.Validate.Struct(req); err != nil {
|
if err := s.Validate.Struct(req); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if req.PercentageThresholdBad > req.PercentageThresholdEnough {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "percentage_threshold_bad cannot be greater than percentage_threshold_enough")
|
||||||
|
}
|
||||||
|
|
||||||
date, err := time.Parse("2006-01-02", req.Date)
|
date, err := time.Parse("2006-01-02", req.Date)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -100,6 +103,11 @@ func (s configChecklistService) UpdateOne(c *fiber.Ctx, req *validation.Update,
|
|||||||
if err := s.Validate.Struct(req); err != nil {
|
if err := s.Validate.Struct(req); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if req.PercentageThresholdBad != nil && req.PercentageThresholdEnough != nil {
|
||||||
|
if *req.PercentageThresholdBad > *req.PercentageThresholdEnough {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "percentage_threshold_bad cannot be greater than percentage_threshold_enough")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateBody := make(map[string]any)
|
updateBody := make(map[string]any)
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,17 @@ func (s *phaseActivityService) CreateOne(c *fiber.Ctx, req *validation.Create) (
|
|||||||
return nil, fiber.NewError(fiber.StatusBadRequest, "time_type cannot be empty")
|
return nil, fiber.NewError(fiber.StatusBadRequest, "time_type cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
existing, err := s.Repository.First(c.Context(), func(db *gorm.DB) *gorm.DB {
|
||||||
|
return db.Where("phase_id = ? AND name = ? AND time_type = ?", phase.Id, name, timeType)
|
||||||
|
})
|
||||||
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
s.Log.Errorf("Failed to check phaseActivity uniqueness: %+v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if existing != nil {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "phase activity with same name and time_type already exists")
|
||||||
|
}
|
||||||
|
|
||||||
createBody := &entity.PhaseActivity{
|
createBody := &entity.PhaseActivity{
|
||||||
PhaseId: phase.Id,
|
PhaseId: phase.Id,
|
||||||
Name: name,
|
Name: name,
|
||||||
|
|||||||
@@ -751,6 +751,9 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
|||||||
if receivedQty > item.SubQty {
|
if receivedQty > item.SubQty {
|
||||||
return nil, utils.BadRequest(fmt.Sprintf("Received quantity for item %d cannot exceed ordered quantity (%.3f)", payload.PurchaseItemID, item.SubQty))
|
return nil, utils.BadRequest(fmt.Sprintf("Received quantity for item %d cannot exceed ordered quantity (%.3f)", payload.PurchaseItemID, item.SubQty))
|
||||||
}
|
}
|
||||||
|
if receivedQty < item.TotalUsed {
|
||||||
|
return nil, utils.BadRequest(fmt.Sprintf("Received quantity for item %d cannot be lower than used amount (%.3f)", payload.PurchaseItemID, item.TotalUsed))
|
||||||
|
}
|
||||||
|
|
||||||
if _, dup := visitedItems[payload.PurchaseItemID]; dup {
|
if _, dup := visitedItems[payload.PurchaseItemID]; dup {
|
||||||
return nil, utils.BadRequest(fmt.Sprintf("Duplicate receiving data for item %d", payload.PurchaseItemID))
|
return nil, utils.BadRequest(fmt.Sprintf("Duplicate receiving data for item %d", payload.PurchaseItemID))
|
||||||
@@ -835,6 +838,7 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
|||||||
affected := make(map[uint]struct{})
|
affected := make(map[uint]struct{})
|
||||||
updates := make([]rPurchase.PurchaseReceivingUpdate, 0, len(prepared))
|
updates := make([]rPurchase.PurchaseReceivingUpdate, 0, len(prepared))
|
||||||
priceUpdates := make([]rPurchase.PurchasePricingUpdate, 0, len(prepared))
|
priceUpdates := make([]rPurchase.PurchasePricingUpdate, 0, len(prepared))
|
||||||
|
totalQtyDeltas := make(map[uint]float64)
|
||||||
fifoAdds := make([]struct {
|
fifoAdds := make([]struct {
|
||||||
itemID uint
|
itemID uint
|
||||||
pwID uint
|
pwID uint
|
||||||
@@ -862,14 +866,20 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
|||||||
deltaQty := prep.receivedQty - item.TotalQty
|
deltaQty := prep.receivedQty - item.TotalQty
|
||||||
switch {
|
switch {
|
||||||
case deltaQty > 0 && newPWID != nil:
|
case deltaQty > 0 && newPWID != nil:
|
||||||
fifoAdds = append(fifoAdds, struct {
|
if s.FifoSvc != nil {
|
||||||
itemID uint
|
fifoAdds = append(fifoAdds, struct {
|
||||||
pwID uint
|
itemID uint
|
||||||
qty float64
|
pwID uint
|
||||||
}{itemID: item.Id, pwID: *newPWID, qty: deltaQty})
|
qty float64
|
||||||
|
}{itemID: item.Id, pwID: *newPWID, qty: deltaQty})
|
||||||
|
} else {
|
||||||
|
deltas[*newPWID] += deltaQty
|
||||||
|
totalQtyDeltas[item.Id] += deltaQty
|
||||||
|
}
|
||||||
case deltaQty < 0 && newPWID != nil:
|
case deltaQty < 0 && newPWID != nil:
|
||||||
deltas[*newPWID] += deltaQty // negative
|
deltas[*newPWID] += deltaQty // negative
|
||||||
affected[*newPWID] = struct{}{}
|
affected[*newPWID] = struct{}{}
|
||||||
|
totalQtyDeltas[item.Id] += deltaQty
|
||||||
}
|
}
|
||||||
|
|
||||||
dateCopy := prep.receivedDate
|
dateCopy := prep.receivedDate
|
||||||
@@ -892,7 +902,7 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
|||||||
|
|
||||||
updates = append(updates, update)
|
updates = append(updates, update)
|
||||||
|
|
||||||
if item.Price > 0 && prep.receivedQty >= 0 {
|
if prep.receivedQty >= 0 {
|
||||||
priceUpdates = append(priceUpdates, rPurchase.PurchasePricingUpdate{
|
priceUpdates = append(priceUpdates, rPurchase.PurchasePricingUpdate{
|
||||||
ItemID: item.Id,
|
ItemID: item.Id,
|
||||||
Price: item.Price,
|
Price: item.Price,
|
||||||
@@ -919,6 +929,19 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(totalQtyDeltas) > 0 {
|
||||||
|
for itemID, delta := range totalQtyDeltas {
|
||||||
|
if delta == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := tx.Model(&entity.PurchaseItem{}).
|
||||||
|
Where("purchase_id = ? AND id = ?", purchase.Id, itemID).
|
||||||
|
Update("total_qty", gorm.Expr("COALESCE(total_qty,0) + ?", delta)).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update due_date based on earliest received date when receiving approved.
|
// Update due_date based on earliest received date when receiving approved.
|
||||||
if earliestReceived != nil {
|
if earliestReceived != nil {
|
||||||
due := earliestReceived.AddDate(0, 0, purchase.CreditTerm)
|
due := earliestReceived.AddDate(0, 0, purchase.CreditTerm)
|
||||||
@@ -1371,10 +1394,6 @@ func (s *purchaseService) buildStaffAdjustmentPayload(
|
|||||||
qtyCopy := effectiveQty
|
qtyCopy := effectiveQty
|
||||||
update.Quantity = &qtyCopy
|
update.Quantity = &qtyCopy
|
||||||
}
|
}
|
||||||
if syncReceiving {
|
|
||||||
qtyCopy := effectiveQty
|
|
||||||
update.TotalQty = &qtyCopy
|
|
||||||
}
|
|
||||||
|
|
||||||
updates = append(updates, update)
|
updates = append(updates, update)
|
||||||
delete(requestItems, item.Id)
|
delete(requestItems, item.Id)
|
||||||
|
|||||||
Reference in New Issue
Block a user