mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
init depresiasi
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||
@@ -358,6 +359,7 @@ func (s *expenseService) CreateOne(c *fiber.Ctx, req *validation.Create) (*expen
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.invalidateDepreciationSnapshotsByExpense(c.Context(), nil, uint(expense.Id), expenseDate, nil)
|
||||
return responseDTO, nil
|
||||
}
|
||||
|
||||
@@ -385,6 +387,7 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
||||
}
|
||||
|
||||
updateBody := make(map[string]any)
|
||||
var requestedTransactionDate *time.Time
|
||||
|
||||
if req.TransactionDate != nil {
|
||||
expenseDate, err := utils.ParseDateString(*req.TransactionDate)
|
||||
@@ -392,6 +395,7 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid transaction_date format")
|
||||
}
|
||||
updateBody["transaction_date"] = expenseDate
|
||||
requestedTransactionDate = &expenseDate
|
||||
}
|
||||
|
||||
if req.Category != nil {
|
||||
@@ -429,6 +433,8 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
||||
return responseDTO, nil
|
||||
}
|
||||
|
||||
var invalidationFromDate time.Time
|
||||
var invalidationFarmIDs []uint
|
||||
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
expenseRepoTx := repository.NewExpenseRepository(tx)
|
||||
@@ -446,6 +452,16 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
||||
if err := s.ensureProjectFlockNotClosedForExpense(c.Context(), currentExpense); err != nil {
|
||||
return err
|
||||
}
|
||||
oldFarmIDs, resolveOldFarmErr := commonSvc.ResolveProjectFlockIDsByExpenseID(c.Context(), tx, id)
|
||||
if resolveOldFarmErr != nil {
|
||||
s.Log.Warnf("Failed to resolve old expense farm ids for invalidation (expense_id=%d): %+v", id, resolveOldFarmErr)
|
||||
}
|
||||
invalidationFarmIDs = append(invalidationFarmIDs, oldFarmIDs...)
|
||||
|
||||
invalidationFromDate = currentExpense.TransactionDate
|
||||
if requestedTransactionDate != nil {
|
||||
invalidationFromDate = commonSvc.MinNonZeroDateOnlyUTC(currentExpense.TransactionDate, *requestedTransactionDate)
|
||||
}
|
||||
categoryChanged := false
|
||||
var newCategory string
|
||||
if req.Category != nil && *req.Category != currentExpense.Category {
|
||||
@@ -631,6 +647,12 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
||||
}
|
||||
}
|
||||
|
||||
newFarmIDs, resolveNewFarmErr := commonSvc.ResolveProjectFlockIDsByExpenseID(c.Context(), tx, id)
|
||||
if resolveNewFarmErr != nil {
|
||||
s.Log.Warnf("Failed to resolve new expense farm ids for invalidation (expense_id=%d): %+v", id, resolveNewFarmErr)
|
||||
}
|
||||
invalidationFarmIDs = append(invalidationFarmIDs, newFarmIDs...)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -645,6 +667,7 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.invalidateDepreciationSnapshots(c.Context(), nil, invalidationFarmIDs, invalidationFromDate)
|
||||
return responseDTO, nil
|
||||
}
|
||||
|
||||
@@ -671,6 +694,10 @@ func (s expenseService) DeleteOne(c *fiber.Ctx, id uint64) error {
|
||||
if err := s.ensureProjectFlockNotClosedForExpense(c.Context(), expense); err != nil {
|
||||
return err
|
||||
}
|
||||
farmIDs, resolveFarmErr := commonSvc.ResolveProjectFlockIDsByExpenseID(c.Context(), s.Repository.DB(), idUint)
|
||||
if resolveFarmErr != nil {
|
||||
s.Log.Warnf("Failed to resolve expense farm ids before delete (expense_id=%d): %+v", idUint, resolveFarmErr)
|
||||
}
|
||||
if err := s.Repository.DeleteOne(c.Context(), idUint); err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
s.Log.Errorf("Expense not found for ID %d: %+v", id, err)
|
||||
@@ -680,6 +707,8 @@ func (s expenseService) DeleteOne(c *fiber.Ctx, id uint64) error {
|
||||
return err
|
||||
}
|
||||
s.Log.Infof("Successfully deleted expense with ID %d", id)
|
||||
invalidationFromDate := commonSvc.MinNonZeroDateOnlyUTC(expense.TransactionDate, expense.RealizationDate)
|
||||
s.invalidateDepreciationSnapshots(c.Context(), nil, farmIDs, invalidationFromDate)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -800,6 +829,8 @@ func (s *expenseService) CreateRealization(c *fiber.Ctx, expenseID uint, req *va
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
invalidateFromDate := commonSvc.MinNonZeroDateOnlyUTC(expense.TransactionDate, realizationDate, expense.RealizationDate)
|
||||
s.invalidateDepreciationSnapshotsByExpense(c.Context(), nil, expenseID, invalidateFromDate, nil)
|
||||
return responseDTO, nil
|
||||
}
|
||||
|
||||
@@ -857,6 +888,13 @@ func (s *expenseService) CompleteExpense(c *fiber.Ctx, id uint, notes *string) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
expense, expenseErr := s.Repository.GetByID(c.Context(), id, nil)
|
||||
if expenseErr != nil {
|
||||
s.Log.Warnf("Failed to load expense for depreciation invalidation after complete (expense_id=%d): %+v", id, expenseErr)
|
||||
} else {
|
||||
invalidateFromDate := commonSvc.MinNonZeroDateOnlyUTC(expense.TransactionDate, expense.RealizationDate)
|
||||
s.invalidateDepreciationSnapshotsByExpense(c.Context(), nil, id, invalidateFromDate, nil)
|
||||
}
|
||||
return responseDTO, nil
|
||||
}
|
||||
|
||||
@@ -884,6 +922,12 @@ func (s *expenseService) UpdateRealization(c *fiber.Ctx, expenseID uint, req *va
|
||||
if err := s.ensureProjectFlockNotClosedForExpense(c.Context(), expense); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
invalidateFromDate := commonSvc.MinNonZeroDateOnlyUTC(expense.TransactionDate, expense.RealizationDate)
|
||||
if req.RealizationDate != nil {
|
||||
if parsedDate, parseErr := utils.ParseDateString(*req.RealizationDate); parseErr == nil {
|
||||
invalidateFromDate = commonSvc.MinNonZeroDateOnlyUTC(invalidateFromDate, parsedDate)
|
||||
}
|
||||
}
|
||||
latestApproval, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowExpense, expenseID, nil)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to validate workflow")
|
||||
@@ -996,6 +1040,7 @@ func (s *expenseService) UpdateRealization(c *fiber.Ctx, expenseID uint, req *va
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.invalidateDepreciationSnapshotsByExpense(c.Context(), nil, expenseID, invalidateFromDate, nil)
|
||||
return responseDTO, nil
|
||||
}
|
||||
|
||||
@@ -1057,6 +1102,7 @@ func (s *expenseService) Approval(c *fiber.Ctx, req *validation.ApprovalRequest,
|
||||
}
|
||||
|
||||
var results []expenseDto.ExpenseDetailDTO
|
||||
invalidateFromDateByExpenseID := make(map[uint]time.Time)
|
||||
|
||||
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
@@ -1069,6 +1115,17 @@ func (s *expenseService) Approval(c *fiber.Ctx, req *validation.ApprovalRequest,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
expenseForInvalidation, err := expenseRepoTx.GetByID(c.Context(), id, nil)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fiber.NewError(fiber.StatusNotFound, "Expense not found")
|
||||
}
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to load expense")
|
||||
}
|
||||
invalidateFromDateByExpenseID[id] = commonSvc.MinNonZeroDateOnlyUTC(
|
||||
expenseForInvalidation.TransactionDate,
|
||||
expenseForInvalidation.RealizationDate,
|
||||
)
|
||||
|
||||
latestApproval, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowExpense, id, nil)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
@@ -1170,10 +1227,73 @@ func (s *expenseService) Approval(c *fiber.Ctx, req *validation.ApprovalRequest,
|
||||
}
|
||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed approve expenses")
|
||||
}
|
||||
for expenseID, invalidateFromDate := range invalidateFromDateByExpenseID {
|
||||
s.invalidateDepreciationSnapshotsByExpense(c.Context(), nil, expenseID, invalidateFromDate, nil)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *expenseService) invalidateDepreciationSnapshotsByExpense(
|
||||
ctx context.Context,
|
||||
tx *gorm.DB,
|
||||
expenseID uint,
|
||||
fromDate time.Time,
|
||||
fallbackFarmIDs []uint,
|
||||
) {
|
||||
targetDB := s.Repository.DB()
|
||||
if tx != nil {
|
||||
targetDB = tx
|
||||
}
|
||||
|
||||
farmIDs := append([]uint{}, fallbackFarmIDs...)
|
||||
if expenseID != 0 {
|
||||
resolvedFarmIDs, err := commonSvc.ResolveProjectFlockIDsByExpenseID(ctx, targetDB, expenseID)
|
||||
if err != nil {
|
||||
s.Log.Warnf("Failed to resolve expense farm ids for invalidation (expense_id=%d): %+v", expenseID, err)
|
||||
} else {
|
||||
farmIDs = append(farmIDs, resolvedFarmIDs...)
|
||||
}
|
||||
}
|
||||
s.invalidateDepreciationSnapshots(ctx, tx, farmIDs, fromDate)
|
||||
}
|
||||
|
||||
func (s *expenseService) invalidateDepreciationSnapshots(
|
||||
ctx context.Context,
|
||||
tx *gorm.DB,
|
||||
farmIDs []uint,
|
||||
fromDate time.Time,
|
||||
) {
|
||||
if fromDate.IsZero() {
|
||||
return
|
||||
}
|
||||
|
||||
targetDB := s.Repository.DB()
|
||||
if tx != nil {
|
||||
targetDB = tx
|
||||
}
|
||||
farmIDs = utils.UniqueUintSlice(farmIDs)
|
||||
if len(farmIDs) == 0 {
|
||||
if err := commonSvc.InvalidateFarmDepreciationSnapshotsFromDate(ctx, targetDB, nil, fromDate); err != nil {
|
||||
s.Log.Warnf(
|
||||
"Failed to invalidate depreciation snapshots globally (from=%s): %+v",
|
||||
fromDate.Format("2006-01-02"),
|
||||
err,
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := commonSvc.InvalidateFarmDepreciationSnapshotsFromDate(ctx, targetDB, farmIDs, fromDate); err != nil {
|
||||
s.Log.Warnf(
|
||||
"Failed to invalidate depreciation snapshots (farm_ids=%v, from=%s): %+v",
|
||||
farmIDs,
|
||||
fromDate.Format("2006-01-02"),
|
||||
err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *expenseService) generatePoNumber(ctx *gorm.DB, expenseID uint) (string, error) {
|
||||
|
||||
expenseRepoTx := repository.NewExpenseRepository(ctx)
|
||||
|
||||
Reference in New Issue
Block a user