mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
Merge branch 'feat/BE/US-281-adjustment_recording' into 'development'
Feat/be/us 281 adjustment recording See merge request mbugroup/lti-api!174
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
@@ -22,6 +24,8 @@ type ProductionStandardService interface {
|
||||
CreateOne(ctx *fiber.Ctx, req *validation.Create) (*entity.ProductionStandard, error)
|
||||
UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint) (*entity.ProductionStandard, error)
|
||||
DeleteOne(ctx *fiber.Ctx, id uint) error
|
||||
EnsureWeekStart(ctx context.Context, standardID uint, category string) error
|
||||
EnsureWeekAvailable(ctx context.Context, standardID uint, category string, day int) error
|
||||
}
|
||||
|
||||
type productionStandardService struct {
|
||||
@@ -299,3 +303,80 @@ func (s productionStandardService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s productionStandardService) EnsureWeekStart(ctx context.Context, standardID uint, category string) error {
|
||||
if standardID == 0 || strings.TrimSpace(category) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch strings.ToUpper(category) {
|
||||
case string(utils.ProjectFlockCategoryLaying):
|
||||
details, err := s.ProductionStandardDetailRepo.GetByProductionStandardID(ctx, standardID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
startWeek := 0
|
||||
if len(details) > 0 {
|
||||
startWeek = details[0].Week
|
||||
}
|
||||
if startWeek != 18 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Week tidak sesuai dengan standart kategori project flock")
|
||||
}
|
||||
case string(utils.ProjectFlockCategoryGrowing):
|
||||
details, err := s.StandardGrowthDetailRepo.GetByProductionStandardID(ctx, standardID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
startWeek := 0
|
||||
if len(details) > 0 {
|
||||
startWeek = details[0].Week
|
||||
}
|
||||
if startWeek != 1 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Week tidak sesuai dengan standart kategori project flock")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s productionStandardService) EnsureWeekAvailable(ctx context.Context, standardID uint, category string, day int) error {
|
||||
if standardID == 0 || day <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
upperCategory := strings.ToUpper(category)
|
||||
weekBase := 1
|
||||
if upperCategory == string(utils.ProjectFlockCategoryLaying) {
|
||||
weekBase = 18
|
||||
}
|
||||
week := ((day - 1) / 7) + weekBase
|
||||
if week <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if upperCategory == string(utils.ProjectFlockCategoryLaying) {
|
||||
detail, err := s.ProductionStandardDetailRepo.GetByStandardIDAndWeek(ctx, standardID, week)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Standart production tidak tersedia untuk week %d", week))
|
||||
}
|
||||
return err
|
||||
}
|
||||
if detail == nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Standart production tidak tersedia untuk week %d", week))
|
||||
}
|
||||
}
|
||||
|
||||
growthDetail, err := s.StandardGrowthDetailRepo.GetByStandardIDAndWeek(ctx, standardID, week)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Standart production tidak tersedia untuk week %d", week))
|
||||
}
|
||||
return err
|
||||
}
|
||||
if growthDetail == nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Standart production tidak tersedia untuk week %d", week))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,44 +14,83 @@ import (
|
||||
|
||||
// === DTO Structs ===
|
||||
|
||||
type RecordingProjectFlockDTO struct {
|
||||
ProjectFlockKandangId uint `json:"project_flock_kandang_id"`
|
||||
FlockName string `json:"flock_name"`
|
||||
ProjectFlockCategory string `json:"project_flock_category"`
|
||||
Period int `json:"period"`
|
||||
ProductionStandart *RecordingProductionStandardDTO `json:"production_standart,omitempty"`
|
||||
Fcr *RecordingFcrDTO `json:"fcr,omitempty"`
|
||||
TotalChickQty float64 `json:"total_chick_qty"`
|
||||
}
|
||||
|
||||
type RecordingProductionStandardDTO struct {
|
||||
Id uint `json:"id"`
|
||||
Week int `json:"week"`
|
||||
Name string `json:"name"`
|
||||
HenDayStd float64 `json:"hen_day_std"`
|
||||
HenHouseStd float64 `json:"hen_house_std"`
|
||||
FeedIntakeStd float64 `json:"feed_intake_std"`
|
||||
MaxDepletionStd float64 `json:"max_depletion_std"`
|
||||
EggMassStd float64 `json:"egg_mass_std"`
|
||||
EggWeightStd float64 `json:"egg_weight_std"`
|
||||
}
|
||||
|
||||
type RecordingFcrDTO struct {
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
FcrStd float64 `json:"fcr_std"`
|
||||
}
|
||||
|
||||
type RecordingAreaDTO struct {
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type RecordingLocationDTO struct {
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
type RecordingWarehouseDTO struct {
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Area *RecordingAreaDTO `json:"area,omitempty"`
|
||||
Location *RecordingLocationDTO `json:"location,omitempty"`
|
||||
}
|
||||
|
||||
type RecordingRelationDTO struct {
|
||||
Id uint `json:"id"`
|
||||
ProjectFlockKandangId uint `json:"project_flock_kandang_id"`
|
||||
RecordDatetime time.Time `json:"record_datetime"`
|
||||
Day int `json:"day"`
|
||||
ProjectFlockCategory string `json:"project_flock_category"`
|
||||
TotalDepletionQty float64 `json:"total_depletion_qty"`
|
||||
CumDepletionRate float64 `json:"cum_depletion_rate"`
|
||||
CumIntake int `json:"cum_intake"`
|
||||
FcrValue float64 `json:"fcr_value"`
|
||||
TotalChickQty float64 `json:"total_chick_qty"`
|
||||
HenDay float64 `json:"hen_day"`
|
||||
HenHouse float64 `json:"hen_house"`
|
||||
FeedIntake float64 `json:"feed_intake"`
|
||||
EggMass float64 `json:"egg_mass"`
|
||||
EggWeight float64 `json:"egg_weight"`
|
||||
StandardHenDay *float64 `json:"hen_day_std,omitempty"`
|
||||
StandardHenHouse *float64 `json:"hen_house_std,omitempty"`
|
||||
StandardFeedIntake *float64 `json:"feed_intake_std,omitempty"`
|
||||
StandardMaxDepletion *float64 `json:"max_depletion_std,omitempty"`
|
||||
StandardEggMass *float64 `json:"egg_mass_std,omitempty"`
|
||||
StandardEggWeight *float64 `json:"egg_weight_std,omitempty"`
|
||||
StandardFcr *float64 `json:"fcr_std,omitempty"`
|
||||
Approval approvalDTO.ApprovalRelationDTO `json:"approval"`
|
||||
Id uint `json:"id"`
|
||||
ProjectFlock RecordingProjectFlockDTO `json:"project_flock"`
|
||||
RecordDatetime time.Time `json:"record_datetime"`
|
||||
Day int `json:"day"`
|
||||
TotalDepletionQty float64 `json:"total_depletion_qty"`
|
||||
CumDepletionRate float64 `json:"cum_depletion_rate"`
|
||||
CumIntake int `json:"cum_intake"`
|
||||
FcrValue float64 `json:"fcr_value"`
|
||||
HenDay float64 `json:"hen_day"`
|
||||
HenHouse float64 `json:"hen_house"`
|
||||
FeedIntake float64 `json:"feed_intake"`
|
||||
EggMass float64 `json:"egg_mass"`
|
||||
EggWeight float64 `json:"egg_weight"`
|
||||
Approval approvalDTO.ApprovalRelationDTO `json:"approval"`
|
||||
}
|
||||
|
||||
type RecordingListDTO struct {
|
||||
RecordingRelationDTO
|
||||
CreatedUser *userDTO.UserRelationDTO `json:"created_user"`
|
||||
CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type RecordingDetailDTO struct {
|
||||
RecordingListDTO
|
||||
Depletions []RecordingDepletionDTO `json:"depletions"`
|
||||
Stocks []RecordingStockDTO `json:"stocks"`
|
||||
Eggs []RecordingEggDTO `json:"eggs"`
|
||||
Warehouse *RecordingWarehouseDTO `json:"warehouse,omitempty"`
|
||||
ProductCategory string `json:"product_category"`
|
||||
Depletions []RecordingDepletionDTO `json:"depletions"`
|
||||
Stocks []RecordingStockDTO `json:"stocks"`
|
||||
Eggs []RecordingEggDTO `json:"eggs"`
|
||||
}
|
||||
|
||||
type RecordingDepletionDTO struct {
|
||||
@@ -63,7 +102,7 @@ type RecordingDepletionDTO struct {
|
||||
type RecordingStockDTO struct {
|
||||
ProductWarehouseId uint `json:"product_warehouse_id"`
|
||||
UsageAmount float64 `json:"usage_amount"`
|
||||
PendingQty *float64 `json:"pending_qty,omitempty"`
|
||||
PendingQty float64 `json:"pending_qty"`
|
||||
ProductWarehouse productWarehouseDTO.ProductWarehouseDTO `json:"product_warehouse"`
|
||||
}
|
||||
|
||||
@@ -75,117 +114,10 @@ type RecordingEggDTO struct {
|
||||
ProductWarehouse productWarehouseDTO.ProductWarehouseDTO `json:"product_warehouse"`
|
||||
}
|
||||
|
||||
type RecordingProductWarehouseDTO struct {
|
||||
Id uint `json:"id"`
|
||||
ProductId uint `json:"product_id"`
|
||||
ProductName string `json:"product_name"`
|
||||
WarehouseId uint `json:"warehouse_id"`
|
||||
WarehouseName string `json:"warehouse_name"`
|
||||
}
|
||||
|
||||
// === Mapper Functions ===
|
||||
|
||||
func ToRecordingRelationDTO(e entity.Recording) RecordingRelationDTO {
|
||||
var (
|
||||
projectFlockCategory string
|
||||
day int
|
||||
totalDepletionQty float64
|
||||
cumDepletionRate float64
|
||||
cumIntake int
|
||||
fcrValue float64
|
||||
totalChickQty float64
|
||||
henDay float64
|
||||
henHouse float64
|
||||
feedIntake float64
|
||||
eggMass float64
|
||||
eggWeight float64
|
||||
)
|
||||
|
||||
if e.Day != nil {
|
||||
day = *e.Day
|
||||
}
|
||||
if e.TotalDepletionQty != nil {
|
||||
totalDepletionQty = *e.TotalDepletionQty
|
||||
}
|
||||
if e.CumDepletionRate != nil {
|
||||
cumDepletionRate = *e.CumDepletionRate
|
||||
}
|
||||
if e.CumIntake != nil {
|
||||
cumIntake = *e.CumIntake
|
||||
}
|
||||
if e.FcrValue != nil {
|
||||
fcrValue = *e.FcrValue
|
||||
}
|
||||
if e.TotalChickQty != nil {
|
||||
totalChickQty = *e.TotalChickQty
|
||||
}
|
||||
if e.HenDay != nil {
|
||||
henDay = *e.HenDay
|
||||
}
|
||||
if e.HenHouse != nil {
|
||||
henHouse = *e.HenHouse
|
||||
}
|
||||
if e.FeedIntake != nil {
|
||||
feedIntake = *e.FeedIntake
|
||||
}
|
||||
if e.EggMass != nil {
|
||||
eggMass = *e.EggMass
|
||||
}
|
||||
if e.EggWeight != nil {
|
||||
eggWeight = *e.EggWeight
|
||||
}
|
||||
|
||||
if e.ProjectFlockKandang != nil && e.ProjectFlockKandang.ProjectFlock.Id != 0 {
|
||||
category := e.ProjectFlockKandang.ProjectFlock.Category
|
||||
projectFlockCategory = category
|
||||
}
|
||||
|
||||
latestApproval := defaultRecordingLatestApproval(e)
|
||||
if e.LatestApproval != nil {
|
||||
snapshot := approvalDTO.ToApprovalDTO(*e.LatestApproval)
|
||||
latestApproval = snapshot
|
||||
}
|
||||
|
||||
return RecordingRelationDTO{
|
||||
Id: e.Id,
|
||||
ProjectFlockKandangId: e.ProjectFlockKandangId,
|
||||
RecordDatetime: e.RecordDatetime,
|
||||
Day: day,
|
||||
ProjectFlockCategory: projectFlockCategory,
|
||||
TotalDepletionQty: totalDepletionQty,
|
||||
CumDepletionRate: cumDepletionRate,
|
||||
CumIntake: cumIntake,
|
||||
FcrValue: fcrValue,
|
||||
TotalChickQty: totalChickQty,
|
||||
HenDay: henDay,
|
||||
HenHouse: henHouse,
|
||||
FeedIntake: feedIntake,
|
||||
EggMass: eggMass,
|
||||
EggWeight: eggWeight,
|
||||
StandardHenDay: e.StandardHenDay,
|
||||
StandardHenHouse: e.StandardHenHouse,
|
||||
StandardFeedIntake: e.StandardFeedIntake,
|
||||
StandardMaxDepletion: e.StandardMaxDepletion,
|
||||
StandardEggMass: e.StandardEggMass,
|
||||
StandardEggWeight: e.StandardEggWeight,
|
||||
StandardFcr: e.StandardFcr,
|
||||
Approval: latestApproval,
|
||||
}
|
||||
}
|
||||
|
||||
func ToRecordingListDTO(e entity.Recording) RecordingListDTO {
|
||||
var createdUser *userDTO.UserRelationDTO
|
||||
if e.CreatedUser != nil && e.CreatedUser.Id != 0 {
|
||||
mapped := userDTO.ToUserRelationDTO(*e.CreatedUser)
|
||||
createdUser = &mapped
|
||||
}
|
||||
|
||||
return RecordingListDTO{
|
||||
RecordingRelationDTO: ToRecordingRelationDTO(e),
|
||||
CreatedAt: e.CreatedAt,
|
||||
UpdatedAt: e.UpdatedAt,
|
||||
CreatedUser: createdUser,
|
||||
}
|
||||
return toRecordingListDTO(e)
|
||||
}
|
||||
|
||||
func ToRecordingListDTOs(e []entity.Recording) []RecordingListDTO {
|
||||
@@ -197,20 +129,15 @@ func ToRecordingListDTOs(e []entity.Recording) []RecordingListDTO {
|
||||
}
|
||||
|
||||
func ToRecordingDetailDTO(e entity.Recording) RecordingDetailDTO {
|
||||
listDTO := ToRecordingListDTO(e)
|
||||
|
||||
var eggs []RecordingEggDTO
|
||||
if strings.EqualFold(listDTO.ProjectFlockCategory, string(utils.ProjectFlockCategoryLaying)) {
|
||||
eggs = ToRecordingEggDTOs(e.Eggs)
|
||||
} else if len(e.Eggs) > 0 {
|
||||
eggs = ToRecordingEggDTOs(e.Eggs)
|
||||
}
|
||||
listDTO := toRecordingListDTO(e)
|
||||
|
||||
return RecordingDetailDTO{
|
||||
RecordingListDTO: listDTO,
|
||||
Depletions: ToRecordingDepletionDTOs(e.Depletions),
|
||||
Stocks: ToRecordingStockDTOs(e.Stocks),
|
||||
Eggs: eggs,
|
||||
Warehouse: recordingWarehouseDTO(e),
|
||||
ProductCategory: recordingProductCategory(e),
|
||||
Depletions: ToRecordingDepletionDTOs(e.Depletions),
|
||||
Stocks: ToRecordingStockDTOs(e.Stocks),
|
||||
Eggs: ToRecordingEggDTOs(e.Eggs),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,11 +160,15 @@ func ToRecordingStockDTOs(stocks []entity.RecordingStock) []RecordingStockDTO {
|
||||
if s.UsageQty != nil {
|
||||
usageAmount = *s.UsageQty
|
||||
}
|
||||
var pendingQty float64
|
||||
if s.PendingQty != nil {
|
||||
pendingQty = *s.PendingQty
|
||||
}
|
||||
|
||||
result[i] = RecordingStockDTO{
|
||||
ProductWarehouseId: s.ProductWarehouseId,
|
||||
UsageAmount: usageAmount,
|
||||
PendingQty: s.PendingQty,
|
||||
PendingQty: pendingQty,
|
||||
ProductWarehouse: mapProductWarehouseDTO(&s.ProductWarehouse),
|
||||
}
|
||||
}
|
||||
@@ -258,6 +189,184 @@ func ToRecordingEggDTOs(eggs []entity.RecordingEgg) []RecordingEggDTO {
|
||||
return result
|
||||
}
|
||||
|
||||
func toRecordingListDTO(e entity.Recording) RecordingListDTO {
|
||||
relation := toRecordingRelationDTO(e)
|
||||
|
||||
var createdUser *userDTO.UserRelationDTO
|
||||
if e.CreatedUser != nil && e.CreatedUser.Id != 0 {
|
||||
mapped := userDTO.ToUserRelationDTO(*e.CreatedUser)
|
||||
createdUser = &mapped
|
||||
}
|
||||
|
||||
return RecordingListDTO{
|
||||
RecordingRelationDTO: relation,
|
||||
CreatedAt: e.CreatedAt,
|
||||
UpdatedAt: e.UpdatedAt,
|
||||
CreatedUser: createdUser,
|
||||
}
|
||||
}
|
||||
|
||||
func toRecordingRelationDTO(e entity.Recording) RecordingRelationDTO {
|
||||
latestApproval := defaultRecordingLatestApproval(e)
|
||||
if e.LatestApproval != nil {
|
||||
snapshot := approvalDTO.ToApprovalDTO(*e.LatestApproval)
|
||||
latestApproval = snapshot
|
||||
}
|
||||
|
||||
return RecordingRelationDTO{
|
||||
Id: e.Id,
|
||||
ProjectFlock: toRecordingProjectFlockDTO(e),
|
||||
RecordDatetime: e.RecordDatetime,
|
||||
Day: intValue(e.Day),
|
||||
TotalDepletionQty: floatValue(e.TotalDepletionQty),
|
||||
CumDepletionRate: floatValue(e.CumDepletionRate),
|
||||
CumIntake: intValue(e.CumIntake),
|
||||
FcrValue: floatValue(e.FcrValue),
|
||||
HenDay: floatValue(e.HenDay),
|
||||
HenHouse: floatValue(e.HenHouse),
|
||||
FeedIntake: floatValue(e.FeedIntake),
|
||||
EggMass: floatValue(e.EggMass),
|
||||
EggWeight: floatValue(e.EggWeight),
|
||||
Approval: latestApproval,
|
||||
}
|
||||
}
|
||||
|
||||
func toRecordingProjectFlockDTO(e entity.Recording) RecordingProjectFlockDTO {
|
||||
result := RecordingProjectFlockDTO{
|
||||
ProjectFlockKandangId: e.ProjectFlockKandangId,
|
||||
}
|
||||
|
||||
pfk := e.ProjectFlockKandang
|
||||
if pfk == nil {
|
||||
return result
|
||||
}
|
||||
|
||||
if pfk.ProjectFlock.Id != 0 {
|
||||
result.FlockName = pfk.ProjectFlock.FlockName
|
||||
if pfk.ProjectFlock.Category != "" {
|
||||
result.ProjectFlockCategory = strings.ToUpper(pfk.ProjectFlock.Category)
|
||||
}
|
||||
}
|
||||
|
||||
result.Period = pfk.Period
|
||||
|
||||
if pfk.ProjectFlock.ProductionStandard.Id != 0 {
|
||||
result.ProductionStandart = &RecordingProductionStandardDTO{
|
||||
Id: pfk.ProjectFlock.ProductionStandard.Id,
|
||||
Week: recordingWeekValue(e),
|
||||
Name: pfk.ProjectFlock.ProductionStandard.Name,
|
||||
HenDayStd: floatValue(e.StandardHenDay),
|
||||
HenHouseStd: floatValue(e.StandardHenHouse),
|
||||
FeedIntakeStd: floatValue(e.StandardFeedIntake),
|
||||
MaxDepletionStd: floatValue(e.StandardMaxDepletion),
|
||||
EggMassStd: floatValue(e.StandardEggMass),
|
||||
EggWeightStd: floatValue(e.StandardEggWeight),
|
||||
}
|
||||
}
|
||||
|
||||
if pfk.ProjectFlock.Fcr.Id != 0 || e.StandardFcr != nil {
|
||||
result.Fcr = &RecordingFcrDTO{
|
||||
Id: pfk.ProjectFlock.Fcr.Id,
|
||||
Name: pfk.ProjectFlock.Fcr.Name,
|
||||
FcrStd: floatValue(e.StandardFcr),
|
||||
}
|
||||
}
|
||||
|
||||
result.TotalChickQty = floatValue(e.TotalChickQty)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func recordingWeekValue(e entity.Recording) int {
|
||||
day := intValue(e.Day)
|
||||
if day <= 0 {
|
||||
return 0
|
||||
}
|
||||
weekBase := 1
|
||||
if isLayingRecording(e) {
|
||||
weekBase = 18
|
||||
}
|
||||
return ((day - 1) / 7) + weekBase
|
||||
}
|
||||
|
||||
func isLayingRecording(e entity.Recording) bool {
|
||||
if e.ProjectFlockKandang == nil {
|
||||
return false
|
||||
}
|
||||
return strings.EqualFold(e.ProjectFlockKandang.ProjectFlock.Category, string(utils.ProjectFlockCategoryLaying))
|
||||
}
|
||||
|
||||
func recordingProductCategory(e entity.Recording) string {
|
||||
if e.ProjectFlockKandang == nil {
|
||||
return ""
|
||||
}
|
||||
project := e.ProjectFlockKandang.ProjectFlock
|
||||
if project.Id == 0 {
|
||||
return ""
|
||||
}
|
||||
if project.ProductionStandard.Id != 0 && project.ProductionStandard.ProjectCategory != "" {
|
||||
return strings.ToUpper(project.ProductionStandard.ProjectCategory)
|
||||
}
|
||||
if project.Category != "" {
|
||||
return strings.ToUpper(project.Category)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func recordingWarehouseDTO(e entity.Recording) *RecordingWarehouseDTO {
|
||||
pw := primaryProductWarehouse(e)
|
||||
if pw == nil || pw.Warehouse.Id == 0 {
|
||||
return nil
|
||||
}
|
||||
return mapWarehouseDTO(&pw.Warehouse)
|
||||
}
|
||||
|
||||
func primaryProductWarehouse(e entity.Recording) *entity.ProductWarehouse {
|
||||
if len(e.Stocks) > 0 {
|
||||
pw := e.Stocks[0].ProductWarehouse
|
||||
if pw.Id != 0 {
|
||||
return &pw
|
||||
}
|
||||
}
|
||||
if len(e.Depletions) > 0 {
|
||||
pw := e.Depletions[0].ProductWarehouse
|
||||
if pw.Id != 0 {
|
||||
return &pw
|
||||
}
|
||||
}
|
||||
if len(e.Eggs) > 0 {
|
||||
pw := e.Eggs[0].ProductWarehouse
|
||||
if pw.Id != 0 {
|
||||
return &pw
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func mapWarehouseDTO(wh *entity.Warehouse) *RecordingWarehouseDTO {
|
||||
if wh == nil || wh.Id == 0 {
|
||||
return nil
|
||||
}
|
||||
dto := &RecordingWarehouseDTO{
|
||||
Id: wh.Id,
|
||||
Name: wh.Name,
|
||||
}
|
||||
if wh.Area.Id != 0 {
|
||||
dto.Area = &RecordingAreaDTO{
|
||||
Id: wh.Area.Id,
|
||||
Name: wh.Area.Name,
|
||||
}
|
||||
}
|
||||
if wh.Location != nil && wh.Location.Id != 0 {
|
||||
dto.Location = &RecordingLocationDTO{
|
||||
Id: wh.Location.Id,
|
||||
Name: wh.Location.Name,
|
||||
Address: wh.Location.Address,
|
||||
}
|
||||
}
|
||||
return dto
|
||||
}
|
||||
|
||||
func mapProductWarehouseDTO(pw *entity.ProductWarehouse) productWarehouseDTO.ProductWarehouseDTO {
|
||||
if pw == nil {
|
||||
return productWarehouseDTO.ProductWarehouseDTO{}
|
||||
@@ -271,6 +380,20 @@ func mapProductWarehouseDTO(pw *entity.ProductWarehouse) productWarehouseDTO.Pro
|
||||
return *mapped
|
||||
}
|
||||
|
||||
func floatValue(value *float64) float64 {
|
||||
if value == nil {
|
||||
return 0
|
||||
}
|
||||
return *value
|
||||
}
|
||||
|
||||
func intValue(value *int) int {
|
||||
if value == nil {
|
||||
return 0
|
||||
}
|
||||
return *value
|
||||
}
|
||||
|
||||
func defaultRecordingLatestApproval(e entity.Recording) approvalDTO.ApprovalRelationDTO {
|
||||
result := approvalDTO.ApprovalRelationDTO{}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
||||
rProductionStandard "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/repositories"
|
||||
sProductionStandard "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/services"
|
||||
rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||
rRecording "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories"
|
||||
sRecording "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/services"
|
||||
@@ -29,6 +31,16 @@ func (RecordingModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
||||
projectFlockPopulationRepo := rProjectFlock.NewProjectFlockPopulationRepository(db)
|
||||
productWarehouseRepo := rProductWarehouse.NewProductWarehouseRepository(db)
|
||||
stockAllocationRepo := commonRepo.NewStockAllocationRepository(db)
|
||||
productionStandardRepo := rProductionStandard.NewProductionStandardRepository(db)
|
||||
productionStandardDetailRepo := rProductionStandard.NewProductionStandardDetailRepository(db)
|
||||
standardGrowthDetailRepo := rProductionStandard.NewStandardGrowthDetailRepository(db)
|
||||
|
||||
productionStandardService := sProductionStandard.NewProductionStandardService(
|
||||
productionStandardRepo,
|
||||
productionStandardDetailRepo,
|
||||
standardGrowthDetailRepo,
|
||||
validate,
|
||||
)
|
||||
|
||||
fifoService := commonSvc.NewFifoService(db, stockAllocationRepo, productWarehouseRepo, utils.Log)
|
||||
if err := fifoService.RegisterUsable(fifo.UsableConfig{
|
||||
@@ -63,6 +75,7 @@ func (RecordingModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
||||
approvalRepo,
|
||||
approvalService,
|
||||
fifoService,
|
||||
productionStandardService,
|
||||
validate,
|
||||
)
|
||||
userService := sUser.NewUserService(userRepo, validate)
|
||||
|
||||
@@ -82,19 +82,28 @@ func (r *RecordingRepositoryImpl) WithRelations(db *gorm.DB) *gorm.DB {
|
||||
return db.
|
||||
Preload("CreatedUser").
|
||||
Preload("ProjectFlockKandang").
|
||||
Preload("ProjectFlockKandang.Kandang").
|
||||
Preload("ProjectFlockKandang.ProjectFlock").
|
||||
Preload("ProjectFlockKandang.ProjectFlock.ProductionStandard").
|
||||
Preload("ProjectFlockKandang.ProjectFlock.Fcr").
|
||||
Preload("Depletions").
|
||||
Preload("Depletions.ProductWarehouse").
|
||||
Preload("Depletions.ProductWarehouse.Product").
|
||||
Preload("Depletions.ProductWarehouse.Warehouse").
|
||||
Preload("Depletions.ProductWarehouse.Warehouse.Area").
|
||||
Preload("Depletions.ProductWarehouse.Warehouse.Location").
|
||||
Preload("Stocks").
|
||||
Preload("Stocks.ProductWarehouse").
|
||||
Preload("Stocks.ProductWarehouse.Product").
|
||||
Preload("Stocks.ProductWarehouse.Warehouse").
|
||||
Preload("Stocks.ProductWarehouse.Warehouse.Area").
|
||||
Preload("Stocks.ProductWarehouse.Warehouse.Location").
|
||||
Preload("Eggs").
|
||||
Preload("Eggs.ProductWarehouse").
|
||||
Preload("Eggs.ProductWarehouse.Product").
|
||||
Preload("Eggs.ProductWarehouse.Warehouse")
|
||||
Preload("Eggs.ProductWarehouse.Warehouse").
|
||||
Preload("Eggs.ProductWarehouse.Warehouse.Area").
|
||||
Preload("Eggs.ProductWarehouse.Warehouse.Location")
|
||||
}
|
||||
|
||||
func (r *RecordingRepositoryImpl) GetLatestByProjectFlockKandangID(ctx context.Context, projectFlockKandangId uint) (*entity.Recording, error) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
||||
rProductionStandard "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/repositories"
|
||||
sProductionStandard "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/services"
|
||||
rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories"
|
||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/validations"
|
||||
@@ -53,6 +54,7 @@ type recordingService struct {
|
||||
ProjectFlockPopulationRepo rProjectFlock.ProjectFlockPopulationRepository
|
||||
ApprovalRepo commonRepo.ApprovalRepository
|
||||
ApprovalSvc commonSvc.ApprovalService
|
||||
ProductionStandardSvc sProductionStandard.ProductionStandardService
|
||||
FifoSvc commonSvc.FifoService
|
||||
}
|
||||
|
||||
@@ -64,6 +66,7 @@ func NewRecordingService(
|
||||
approvalRepo commonRepo.ApprovalRepository,
|
||||
approvalSvc commonSvc.ApprovalService,
|
||||
fifoSvc commonSvc.FifoService,
|
||||
productionStandardSvc sProductionStandard.ProductionStandardService,
|
||||
validate *validator.Validate,
|
||||
) RecordingService {
|
||||
return &recordingService{
|
||||
@@ -75,6 +78,7 @@ func NewRecordingService(
|
||||
ProjectFlockPopulationRepo: projectFlockPopulationRepo,
|
||||
ApprovalRepo: approvalRepo,
|
||||
ApprovalSvc: approvalSvc,
|
||||
ProductionStandardSvc: productionStandardSvc,
|
||||
FifoSvc: fifoSvc,
|
||||
}
|
||||
}
|
||||
@@ -169,6 +173,14 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
|
||||
}
|
||||
|
||||
ctx := c.Context()
|
||||
recordTime := time.Now().UTC()
|
||||
if req.RecordDate != nil && strings.TrimSpace(*req.RecordDate) != "" {
|
||||
parsed, err := time.Parse("2006-01-02", strings.TrimSpace(*req.RecordDate))
|
||||
if err != nil {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "record_date must be in YYYY-MM-DD format")
|
||||
}
|
||||
recordTime = parsed.UTC()
|
||||
}
|
||||
|
||||
pfk, err := s.ProjectFlockKandangRepo.GetByID(ctx, req.ProjectFlockKandangId)
|
||||
if err != nil {
|
||||
@@ -188,6 +200,11 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
|
||||
if err := s.ensureChickInExists(ctx, pfk.Id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.ProductionStandardSvc != nil {
|
||||
if err := s.ProductionStandardSvc.EnsureWeekStart(ctx, pfk.ProjectFlock.ProductionStandardId, category); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if !isLaying && len(req.Eggs) > 0 {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Egg details permitted only for laying project flocks")
|
||||
@@ -210,8 +227,12 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
|
||||
s.Log.Errorf("Failed to determine recording day: %+v", err)
|
||||
return err
|
||||
}
|
||||
if s.ProductionStandardSvc != nil {
|
||||
if err := s.ProductionStandardSvc.EnsureWeekAvailable(ctx, pfk.ProjectFlock.ProductionStandardId, category, nextDay); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
recordTime := time.Now().UTC()
|
||||
existsToday, err := s.Repository.ExistsOnDate(ctx, req.ProjectFlockKandangId, recordTime)
|
||||
if err != nil {
|
||||
s.Log.Errorf("Failed to verify existing recording on date: %+v", err)
|
||||
@@ -1157,7 +1178,7 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
|
||||
|
||||
var fcrValue float64
|
||||
if usageInGrams > 0 && totalEggWeightGrams > 0 {
|
||||
fcrValue = totalEggWeightGrams / usageInGrams
|
||||
fcrValue = usageInGrams / totalEggWeightGrams
|
||||
updates["fcr_value"] = fcrValue
|
||||
recording.FcrValue = &fcrValue
|
||||
} else {
|
||||
@@ -1330,12 +1351,16 @@ func (s *recordingService) attachProductionStandard(ctx context.Context, item *e
|
||||
return nil
|
||||
}
|
||||
|
||||
week := ((int(*item.Day) - 1) / 7) + 1
|
||||
category := strings.ToUpper(item.ProjectFlockKandang.ProjectFlock.Category)
|
||||
weekBase := 1
|
||||
if category == string(utils.ProjectFlockCategoryLaying) {
|
||||
weekBase = 18
|
||||
}
|
||||
week := ((int(*item.Day) - 1) / 7) + weekBase
|
||||
if week <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
category := strings.ToUpper(item.ProjectFlockKandang.ProjectFlock.Category)
|
||||
db := s.Repository.DB()
|
||||
standardDetailRepo := rProductionStandard.NewProductionStandardDetailRepository(db)
|
||||
growthDetailRepo := rProductionStandard.NewStandardGrowthDetailRepository(db)
|
||||
|
||||
@@ -21,6 +21,7 @@ type (
|
||||
|
||||
type Create struct {
|
||||
ProjectFlockKandangId uint `json:"project_flock_kandang_id" validate:"required,number,min=1"`
|
||||
RecordDate *string `json:"record_date,omitempty" validate:"omitempty,datetime=2006-01-02"`
|
||||
Stocks []Stock `json:"stocks" validate:"dive"`
|
||||
Depletions []Depletion `json:"depletions" validate:"dive"`
|
||||
Eggs []Egg `json:"eggs" validate:"omitempty,dive"`
|
||||
|
||||
Reference in New Issue
Block a user