package mappers import ( "apskel-pos-be/internal/constants" "apskel-pos-be/internal/entities" "apskel-pos-be/internal/models" ) // Amounts are money rounded to two decimals, so anything under half a cent apart // is the same figure. Comparing them directly would leave an advance a hundredth of // a rupiah short of settled. const cashAdvanceAmountEpsilon = 0.005 // cashAdvanceTeamFromEntity renders the team an advance was handed to. Unlike a // purchase order there is always one, so this never returns nil. The category name // is only filled in when TeamCategory was preloaded. func cashAdvanceTeamFromEntity(entity *entities.CashAdvance) *models.PurchaseTeam { team := &models.PurchaseTeam{Scope: entity.TeamScope} switch entity.TeamScope { case constants.PurchaseTeamScopeCentral: team.Name = constants.PurchaseTeamCentralName case constants.PurchaseTeamScopeCategory: team.CategoryID = entity.TeamCategoryID if entity.TeamCategory != nil { team.Name = entity.TeamCategory.Name } } return team } // cashAdvanceSettlementStatus reads the money rather than any stored flag: cash is // accounted for by spending charged to the advance plus what was handed back. A // team that overspent still counts as settled — the excess is owed back to them. func cashAdvanceSettlementStatus(amount, settled, returned float64) string { accounted := settled + returned switch { case accounted <= cashAdvanceAmountEpsilon: return constants.CashAdvanceSettlementOpen case amount-accounted > cashAdvanceAmountEpsilon: return constants.CashAdvanceSettlementPartial default: return constants.CashAdvanceSettlementSettled } } func CashAdvanceEntityToModel(entity *entities.CashAdvance) *models.CashAdvance { if entity == nil { return nil } return &models.CashAdvance{ ID: entity.ID, OrganizationID: entity.OrganizationID, OutletID: entity.OutletID, CodeNumber: entity.CodeNumber, TeamScope: entity.TeamScope, TeamCategoryID: entity.TeamCategoryID, Amount: entity.Amount, ReturnedAmount: entity.ReturnedAmount, IssuedDate: entity.IssuedDate, DueDate: entity.DueDate, Status: entity.Status, Description: entity.Description, CreatedAt: entity.CreatedAt, UpdatedAt: entity.UpdatedAt, } } func CashAdvanceEntityToResponse(entity *entities.CashAdvance) *models.CashAdvanceResponse { if entity == nil { return nil } return &models.CashAdvanceResponse{ ID: entity.ID, OrganizationID: entity.OrganizationID, OutletID: entity.OutletID, CodeNumber: entity.CodeNumber, TeamScope: entity.TeamScope, TeamCategoryID: entity.TeamCategoryID, Amount: entity.Amount, SettledAmount: entity.SettledAmount, ReturnedAmount: entity.ReturnedAmount, RemainingAmount: entity.Amount - entity.SettledAmount - entity.ReturnedAmount, SettlementStatus: cashAdvanceSettlementStatus(entity.Amount, entity.SettledAmount, entity.ReturnedAmount), IssuedDate: entity.IssuedDate, DueDate: entity.DueDate, Status: entity.Status, Description: entity.Description, CreatedAt: entity.CreatedAt, UpdatedAt: entity.UpdatedAt, Team: cashAdvanceTeamFromEntity(entity), } } func CashAdvanceEntitiesToResponses(entities []*entities.CashAdvance) []*models.CashAdvanceResponse { if entities == nil { return nil } responses := make([]*models.CashAdvanceResponse, len(entities)) for i, entity := range entities { responses[i] = CashAdvanceEntityToResponse(entity) } return responses } func CashAdvanceSettlementEntitiesToModels(settlements []*entities.CashAdvanceSettlement) []models.CashAdvanceSettlement { if settlements == nil { return nil } result := make([]models.CashAdvanceSettlement, len(settlements)) for i, settlement := range settlements { result[i] = models.CashAdvanceSettlement{ Type: settlement.Type, ID: settlement.ID, Number: settlement.Number, Date: settlement.Date, Amount: settlement.Amount, Status: settlement.Status, } } return result }