mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-24 07:15:43 +00:00
fixing report-counting-sapronak
This commit is contained in:
@@ -16,14 +16,14 @@ import (
|
||||
type ClosingRepository interface {
|
||||
repository.BaseRepository[entity.ProjectFlock]
|
||||
GetSapronak(ctx context.Context, params SapronakQueryParams) ([]SapronakRow, int64, error)
|
||||
ListProjectFlockKandangsForSapronak(ctx context.Context, params *validation.CountSapronakQuery) ([]entity.ProjectFlockKandang, error)
|
||||
MapSapronakStartDates(ctx context.Context, pfkIDs []uint) (map[uint]time.Time, error)
|
||||
FetchSapronakIncoming(ctx context.Context, kandangID uint, start, end *time.Time) ([]SapronakIncomingRow, error)
|
||||
FetchSapronakIncomingDetails(ctx context.Context, kandangID uint, start, end *time.Time) (map[uint][]SapronakDetailRow, error)
|
||||
FetchSapronakUsage(ctx context.Context, pfkID uint, start, end *time.Time) ([]SapronakUsageRow, error)
|
||||
FetchSapronakUsageDetails(ctx context.Context, pfkID uint, start, end *time.Time) (map[uint][]SapronakDetailRow, error)
|
||||
FetchSapronakAdjustments(ctx context.Context, kandangID uint, start, end *time.Time) (map[uint][]SapronakDetailRow, map[uint][]SapronakDetailRow, error)
|
||||
FetchSapronakTransfers(ctx context.Context, kandangID uint, start, end *time.Time) (map[uint][]SapronakDetailRow, map[uint][]SapronakDetailRow, error)
|
||||
FetchSapronakIncoming(ctx context.Context, kandangID uint) ([]SapronakIncomingRow, error)
|
||||
FetchSapronakIncomingDetails(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, error)
|
||||
FetchSapronakUsage(ctx context.Context, pfkID uint) ([]SapronakUsageRow, error)
|
||||
FetchSapronakUsageDetails(ctx context.Context, pfkID uint) (map[uint][]SapronakDetailRow, error)
|
||||
FetchSapronakChickinUsage(ctx context.Context, pfkID uint) ([]SapronakUsageRow, error)
|
||||
FetchSapronakChickinUsageDetails(ctx context.Context, pfkID uint) (map[uint][]SapronakDetailRow, error)
|
||||
FetchSapronakAdjustments(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, map[uint][]SapronakDetailRow, error)
|
||||
FetchSapronakTransfers(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, map[uint][]SapronakDetailRow, error)
|
||||
}
|
||||
|
||||
type ClosingRepositoryImpl struct {
|
||||
@@ -260,183 +260,159 @@ type SapronakDetailRow struct {
|
||||
Price float64
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) ListProjectFlockKandangsForSapronak(ctx context.Context, params *validation.CountSapronakQuery) ([]entity.ProjectFlockKandang, error) {
|
||||
db := r.DB().
|
||||
WithContext(ctx).
|
||||
Preload("ProjectFlock").
|
||||
Preload("Kandang")
|
||||
|
||||
if params != nil {
|
||||
if params.ProjectFlockID > 0 {
|
||||
db = db.Where("project_flock_kandangs.project_flock_id = ?", params.ProjectFlockID)
|
||||
}
|
||||
if params.KandangID > 0 {
|
||||
db = db.Where("project_flock_kandangs.kandang_id = ?", params.KandangID)
|
||||
}
|
||||
if params.ProjectFlockKandangID > 0 {
|
||||
db = db.Where("project_flock_kandangs.id = ?", params.ProjectFlockKandangID)
|
||||
func (r *ClosingRepositoryImpl) withCtx(ctx context.Context) *gorm.DB { return r.DB().WithContext(ctx) }
|
||||
|
||||
func applyJoins(db *gorm.DB, joins ...string) *gorm.DB {
|
||||
for _, j := range joins {
|
||||
if strings.TrimSpace(j) != "" {
|
||||
db = db.Joins(j)
|
||||
}
|
||||
}
|
||||
|
||||
var pfks []entity.ProjectFlockKandang
|
||||
if err := db.Find(&pfks).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pfks, nil
|
||||
return db
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) MapSapronakStartDates(ctx context.Context, pfkIDs []uint) (map[uint]time.Time, error) {
|
||||
result := make(map[uint]time.Time, len(pfkIDs))
|
||||
if len(pfkIDs) == 0 {
|
||||
return result, nil
|
||||
func sapronakFlags(flags ...utils.FlagType) []string {
|
||||
out := make([]string, len(flags))
|
||||
for i, f := range flags {
|
||||
out[i] = string(f)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var rows []struct {
|
||||
ProjectFlockKandangID uint `gorm:"column:project_flock_kandang_id"`
|
||||
StartDate *time.Time `gorm:"column:start_date"`
|
||||
}
|
||||
|
||||
if err := r.DB().
|
||||
WithContext(ctx).
|
||||
Table("project_chickins").
|
||||
Select("project_flock_kandang_id, MIN(chick_in_date) AS start_date").
|
||||
Where("project_flock_kandang_id IN ?", pfkIDs).
|
||||
Group("project_flock_kandang_id").
|
||||
Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var (
|
||||
sapronakFlagsAll = sapronakFlags(utils.FlagDOC, utils.FlagPakan, utils.FlagOVK, utils.FlagPullet)
|
||||
sapronakFlagsUsage = sapronakFlags(utils.FlagPakan, utils.FlagOVK)
|
||||
sapronakFlagsChickin = sapronakFlags(utils.FlagDOC, utils.FlagPullet)
|
||||
)
|
||||
|
||||
func groupSapronakDetails(rows []SapronakDetailRow) map[uint][]SapronakDetailRow {
|
||||
m := make(map[uint][]SapronakDetailRow)
|
||||
for _, row := range rows {
|
||||
if row.StartDate != nil {
|
||||
result[row.ProjectFlockKandangID] = row.StartDate.UTC()
|
||||
}
|
||||
m[row.ProductID] = append(m[row.ProductID], row)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return m
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakIncoming(ctx context.Context, kandangID uint, start, end *time.Time) ([]SapronakIncomingRow, error) {
|
||||
rows := make([]SapronakIncomingRow, 0)
|
||||
|
||||
db := r.DB().
|
||||
WithContext(ctx).
|
||||
Table("purchase_items AS pi").
|
||||
Select(`
|
||||
pi.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
COALESCE(SUM(pi.total_qty), 0) AS qty,
|
||||
COALESCE(SUM(pi.total_qty * pi.price), 0) AS value,
|
||||
COALESCE(p.product_price, 0) AS default_price
|
||||
`).
|
||||
Joins("JOIN purchases po ON po.id = pi.purchase_id AND po.deleted_at IS NULL").
|
||||
Joins("JOIN products p ON p.id = pi.product_id").
|
||||
Joins("JOIN flags f ON f.flagable_id = p.id AND f.flagable_type = ?", entity.FlagableTypeProduct).
|
||||
Joins("JOIN warehouses w ON w.id = pi.warehouse_id").
|
||||
Where("w.kandang_id = ?", kandangID).
|
||||
Where("f.name IN ?", []string{string(utils.FlagDOC), string(utils.FlagPakan), string(utils.FlagOVK)}).
|
||||
Where("pi.received_date IS NOT NULL")
|
||||
|
||||
if start != nil {
|
||||
db = db.Where("pi.received_date >= ?", *start)
|
||||
}
|
||||
if end != nil {
|
||||
db = db.Where("pi.received_date < ?", *end)
|
||||
}
|
||||
|
||||
if err := db.Group("pi.product_id, p.name, f.name, p.product_price").Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakUsage(ctx context.Context, pfkID uint, start, end *time.Time) ([]SapronakUsageRow, error) {
|
||||
rows := make([]SapronakUsageRow, 0)
|
||||
if pfkID == 0 {
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
db := r.DB().
|
||||
WithContext(ctx).
|
||||
Table("recording_stocks AS rs").
|
||||
Select(`
|
||||
pw.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
COALESCE(SUM(rs.usage_qty), 0) AS qty,
|
||||
COALESCE(p.product_price, 0) AS default_price
|
||||
`).
|
||||
Joins("JOIN recordings r ON r.id = rs.recording_id AND r.deleted_at IS NULL").
|
||||
Joins("JOIN product_warehouses pw ON pw.id = rs.product_warehouse_id").
|
||||
Joins("JOIN products p ON p.id = pw.product_id").
|
||||
Joins("JOIN flags f ON f.flagable_id = p.id AND f.flagable_type = ?", entity.FlagableTypeProduct).
|
||||
Where("r.project_flock_kandangs_id = ?", pfkID).
|
||||
Where("f.name IN ?", []string{string(utils.FlagDOC), string(utils.FlagPakan), string(utils.FlagOVK)})
|
||||
|
||||
if start != nil {
|
||||
db = db.Where("r.record_datetime >= ?", *start)
|
||||
}
|
||||
if end != nil {
|
||||
db = db.Where("r.record_datetime < ?", *end)
|
||||
}
|
||||
|
||||
if err := db.Group("pw.product_id, p.name, f.name, p.product_price").Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakIncomingDetails(ctx context.Context, kandangID uint, start, end *time.Time) (map[uint][]SapronakDetailRow, error) {
|
||||
func scanAndGroupDetails(db *gorm.DB) (map[uint][]SapronakDetailRow, error) {
|
||||
rows := make([]SapronakDetailRow, 0)
|
||||
|
||||
db := r.DB().
|
||||
WithContext(ctx).
|
||||
Table("purchase_items AS pi").
|
||||
Select(`
|
||||
pi.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
pi.received_date AS date,
|
||||
COALESCE(po.po_number, '') AS reference,
|
||||
COALESCE(pi.total_qty,0) AS qty_in,
|
||||
0 AS qty_out,
|
||||
COALESCE(pi.price,0) AS price
|
||||
`).
|
||||
Joins("JOIN purchases po ON po.id = pi.purchase_id AND po.deleted_at IS NULL").
|
||||
Joins("JOIN products p ON p.id = pi.product_id").
|
||||
Joins("JOIN flags f ON f.flagable_id = p.id AND f.flagable_type = ?", entity.FlagableTypeProduct).
|
||||
Joins("JOIN warehouses w ON w.id = pi.warehouse_id").
|
||||
Where("w.kandang_id = ?", kandangID).
|
||||
Where("f.name IN ?", []string{string(utils.FlagDOC), string(utils.FlagPakan), string(utils.FlagOVK)}).
|
||||
Where("pi.received_date IS NOT NULL")
|
||||
|
||||
if start != nil {
|
||||
db = db.Where("pi.received_date >= ?", *start)
|
||||
}
|
||||
if end != nil {
|
||||
db = db.Where("pi.received_date < ?", *end)
|
||||
}
|
||||
|
||||
if err := db.Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uint][]SapronakDetailRow)
|
||||
for _, row := range rows {
|
||||
result[row.ProductID] = append(result[row.ProductID], row)
|
||||
}
|
||||
return result, nil
|
||||
return groupSapronakDetails(rows), nil
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakUsageDetails(ctx context.Context, pfkID uint, start, end *time.Time) (map[uint][]SapronakDetailRow, error) {
|
||||
rows := make([]SapronakDetailRow, 0)
|
||||
// =========================
|
||||
// Usage (summary + details)
|
||||
// =========================
|
||||
|
||||
db := r.DB().
|
||||
WithContext(ctx).
|
||||
Table("recording_stocks AS rs").
|
||||
Select(`
|
||||
func (r *ClosingRepositoryImpl) usageQuery(
|
||||
ctx context.Context,
|
||||
table string,
|
||||
pwJoinCond string,
|
||||
joins []string,
|
||||
where string,
|
||||
args ...any,
|
||||
) *gorm.DB {
|
||||
db := r.withCtx(ctx).Table(table).Select(`
|
||||
pw.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
COALESCE(SUM(usage_qty), 0) AS qty,
|
||||
COALESCE(p.product_price, 0) AS default_price
|
||||
`)
|
||||
db = applyJoins(db, joins...)
|
||||
return db.
|
||||
Joins("JOIN product_warehouses pw ON " + pwJoinCond).
|
||||
Joins("JOIN products p ON p.id = pw.product_id").
|
||||
Joins("JOIN flags f ON f.flagable_id = p.id AND f.flagable_type = ?", entity.FlagableTypeProduct).
|
||||
Where(where, args...)
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) fetchSapronakUsage(
|
||||
ctx context.Context,
|
||||
table string,
|
||||
pwJoinCond string,
|
||||
joins []string,
|
||||
where string,
|
||||
args ...any,
|
||||
) ([]SapronakUsageRow, error) {
|
||||
rows := make([]SapronakUsageRow, 0)
|
||||
db := r.usageQuery(ctx, table, pwJoinCond, joins, where, args...)
|
||||
if err := db.Group("pw.product_id, p.name, f.name, p.product_price").Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) detailQuery(
|
||||
ctx context.Context,
|
||||
table string,
|
||||
pwJoinCond string,
|
||||
joins []string,
|
||||
selectSQL string,
|
||||
where string,
|
||||
args ...any,
|
||||
) *gorm.DB {
|
||||
db := r.withCtx(ctx).
|
||||
Table(table).
|
||||
Joins("JOIN product_warehouses pw ON " + pwJoinCond).
|
||||
Joins("JOIN products p ON p.id = pw.product_id").
|
||||
Joins("JOIN flags f ON f.flagable_id = p.id AND f.flagable_type = ?", entity.FlagableTypeProduct)
|
||||
|
||||
db = applyJoins(db, joins...)
|
||||
return db.Select(selectSQL).Where(where, args...)
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) fetchSapronakDetails(
|
||||
ctx context.Context,
|
||||
table string,
|
||||
pwJoinCond string,
|
||||
joins []string,
|
||||
selectSQL string,
|
||||
where string,
|
||||
args ...any,
|
||||
) (map[uint][]SapronakDetailRow, error) {
|
||||
return scanAndGroupDetails(r.detailQuery(ctx, table, pwJoinCond, joins, selectSQL, where, args...))
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakUsage(ctx context.Context, pfkID uint) ([]SapronakUsageRow, error) {
|
||||
if pfkID == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return r.fetchSapronakUsage(
|
||||
ctx,
|
||||
"recording_stocks rs",
|
||||
"pw.id = rs.product_warehouse_id",
|
||||
[]string{"JOIN recordings r ON r.id = rs.recording_id AND r.deleted_at IS NULL"},
|
||||
"r.project_flock_kandangs_id = ? AND f.name IN ?",
|
||||
pfkID,
|
||||
sapronakFlagsUsage,
|
||||
)
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakChickinUsage(ctx context.Context, pfkID uint) ([]SapronakUsageRow, error) {
|
||||
if pfkID == 0 {
|
||||
return []SapronakUsageRow{}, nil
|
||||
}
|
||||
return r.fetchSapronakUsage(
|
||||
ctx,
|
||||
"project_chickins pc",
|
||||
"pw.id = pc.product_warehouse_id",
|
||||
nil,
|
||||
"pc.project_flock_kandang_id = ? AND pc.usage_qty > 0 AND f.name IN ?",
|
||||
pfkID,
|
||||
sapronakFlagsChickin,
|
||||
)
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakUsageDetails(ctx context.Context, pfkID uint) (map[uint][]SapronakDetailRow, error) {
|
||||
return r.fetchSapronakDetails(
|
||||
ctx,
|
||||
"recording_stocks rs",
|
||||
"pw.id = rs.product_warehouse_id",
|
||||
[]string{"JOIN recordings r ON r.id = rs.recording_id AND r.deleted_at IS NULL"}, // penting: supaya alias r valid
|
||||
`
|
||||
pw.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
@@ -445,184 +421,180 @@ func (r *ClosingRepositoryImpl) FetchSapronakUsageDetails(ctx context.Context, p
|
||||
0 AS qty_in,
|
||||
COALESCE(rs.usage_qty,0) AS qty_out,
|
||||
COALESCE(p.product_price,0) AS price
|
||||
`,
|
||||
"r.project_flock_kandangs_id = ? AND f.name IN ?",
|
||||
pfkID,
|
||||
sapronakFlagsUsage,
|
||||
)
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakChickinUsageDetails(ctx context.Context, pfkID uint) (map[uint][]SapronakDetailRow, error) {
|
||||
return r.fetchSapronakDetails(
|
||||
ctx,
|
||||
"project_chickins pc",
|
||||
"pw.id = pc.product_warehouse_id",
|
||||
nil,
|
||||
`
|
||||
pw.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
pc.chick_in_date AS date,
|
||||
CAST(pc.id AS TEXT) AS reference,
|
||||
0 AS qty_in,
|
||||
COALESCE(pc.usage_qty,0) AS qty_out,
|
||||
COALESCE(p.product_price,0) AS price
|
||||
`,
|
||||
"pc.project_flock_kandang_id = ? AND pc.usage_qty > 0 AND f.name IN ?",
|
||||
pfkID,
|
||||
sapronakFlagsChickin,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
func (r *ClosingRepositoryImpl) incomingPurchaseBase(ctx context.Context, kandangID uint) *gorm.DB {
|
||||
return r.withCtx(ctx).
|
||||
Table("purchase_items AS pi").
|
||||
Joins("JOIN purchases po ON po.id = pi.purchase_id AND po.deleted_at IS NULL").
|
||||
Joins("JOIN products p ON p.id = pi.product_id").
|
||||
Joins("JOIN flags f ON f.flagable_id = p.id AND f.flagable_type = ?", entity.FlagableTypeProduct).
|
||||
Joins("JOIN warehouses w ON w.id = pi.warehouse_id").
|
||||
Where("w.kandang_id = ?", kandangID).
|
||||
Where("f.name IN ?", sapronakFlagsAll).
|
||||
Where("pi.received_date IS NOT NULL")
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakIncoming(ctx context.Context, kandangID uint) ([]SapronakIncomingRow, error) {
|
||||
rows := make([]SapronakIncomingRow, 0)
|
||||
db := r.incomingPurchaseBase(ctx, kandangID).Select(`
|
||||
pi.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
COALESCE(SUM(pi.total_qty), 0) AS qty,
|
||||
COALESCE(SUM(pi.total_qty * pi.price), 0) AS value,
|
||||
COALESCE(p.product_price, 0) AS default_price
|
||||
`)
|
||||
if err := db.Group("pi.product_id, p.name, f.name, p.product_price").Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakIncomingDetails(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, error) {
|
||||
return scanAndGroupDetails(
|
||||
r.incomingPurchaseBase(ctx, kandangID).Select(`
|
||||
pi.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
pi.received_date AS date,
|
||||
COALESCE(po.po_number, '') AS reference,
|
||||
COALESCE(pi.total_qty,0) AS qty_in,
|
||||
0 AS qty_out,
|
||||
COALESCE(pi.price,0) AS price
|
||||
`),
|
||||
)
|
||||
}
|
||||
|
||||
type stockLogSapronakRow struct {
|
||||
ID uint `gorm:"column:id"`
|
||||
ProductID uint `gorm:"column:product_id"`
|
||||
ProductName string `gorm:"column:product_name"`
|
||||
Flag string `gorm:"column:flag"`
|
||||
CreatedAt *time.Time `gorm:"column:created_at"`
|
||||
Increase float64 `gorm:"column:increase"`
|
||||
Decrease float64 `gorm:"column:decrease"`
|
||||
Price float64 `gorm:"column:price"`
|
||||
MovementNumber string `gorm:"column:movement_number"`
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) fetchStockLogs(ctx context.Context, kandangID uint, logType any, withMovement bool) ([]stockLogSapronakRow, error) {
|
||||
rows := make([]stockLogSapronakRow, 0)
|
||||
|
||||
movementSelect := "'' AS movement_number"
|
||||
joins := []string{}
|
||||
if withMovement {
|
||||
movementSelect = "COALESCE(st.movement_number,'') AS movement_number"
|
||||
joins = append(joins, "JOIN stock_transfers st ON st.id = sl.loggable_id")
|
||||
}
|
||||
|
||||
db := r.withCtx(ctx).
|
||||
Table("stock_logs sl").
|
||||
Select(`
|
||||
sl.id AS id,
|
||||
pw.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
sl.created_at AS created_at,
|
||||
COALESCE(sl.increase,0) AS increase,
|
||||
COALESCE(sl.decrease,0) AS decrease,
|
||||
COALESCE(p.product_price,0) AS price,
|
||||
` + movementSelect + `
|
||||
`).
|
||||
Joins("JOIN recordings r ON r.id = rs.recording_id AND r.deleted_at IS NULL").
|
||||
Joins("JOIN product_warehouses pw ON pw.id = rs.product_warehouse_id").
|
||||
Joins("JOIN product_warehouses pw ON pw.id = sl.product_warehouse_id").
|
||||
Joins("JOIN products p ON p.id = pw.product_id").
|
||||
Joins("JOIN flags f ON f.flagable_id = p.id AND f.flagable_type = ?", entity.FlagableTypeProduct).
|
||||
Where("r.project_flock_kandangs_id = ?", pfkID).
|
||||
Where("f.name IN ?", []string{string(utils.FlagDOC), string(utils.FlagPakan), string(utils.FlagOVK)})
|
||||
Joins("JOIN warehouses w ON w.id = pw.warehouse_id")
|
||||
|
||||
if start != nil {
|
||||
db = db.Where("r.record_datetime >= ?", *start)
|
||||
}
|
||||
if end != nil {
|
||||
db = db.Where("r.record_datetime < ?", *end)
|
||||
}
|
||||
db = applyJoins(db, joins...)
|
||||
|
||||
if err := db.Scan(&rows).Error; err != nil {
|
||||
if err := db.
|
||||
Where("sl.loggable_type = ?", logType).
|
||||
Where("w.kandang_id = ?", kandangID).
|
||||
Where("f.name IN ?", sapronakFlagsAll).
|
||||
Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uint][]SapronakDetailRow)
|
||||
for _, row := range rows {
|
||||
result[row.ProductID] = append(result[row.ProductID], row)
|
||||
}
|
||||
return result, nil
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakAdjustments(ctx context.Context, kandangID uint, start, end *time.Time) (map[uint][]SapronakDetailRow, map[uint][]SapronakDetailRow, error) {
|
||||
incoming := make(map[uint][]SapronakDetailRow)
|
||||
outgoing := make(map[uint][]SapronakDetailRow)
|
||||
|
||||
rows := make([]struct {
|
||||
ID uint
|
||||
ProductID uint
|
||||
ProductName string
|
||||
Flag string
|
||||
CreatedAt *time.Time
|
||||
Increase float64
|
||||
Decrease float64
|
||||
Price float64
|
||||
}, 0)
|
||||
|
||||
db := r.DB().
|
||||
WithContext(ctx).
|
||||
Table("stock_logs sl").
|
||||
Select(`
|
||||
sl.id AS id,
|
||||
pw.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
sl.created_at AS created_at,
|
||||
COALESCE(sl.increase,0) AS increase,
|
||||
COALESCE(sl.decrease,0) AS decrease,
|
||||
COALESCE(p.product_price,0) AS price
|
||||
`).
|
||||
Joins("JOIN product_warehouses pw ON pw.id = sl.product_warehouse_id").
|
||||
Joins("JOIN products p ON p.id = pw.product_id").
|
||||
Joins("JOIN flags f ON f.flagable_id = p.id AND f.flagable_type = ?", entity.FlagableTypeProduct).
|
||||
Joins("JOIN warehouses w ON w.id = pw.warehouse_id").
|
||||
Where("sl.loggable_type = ?", entity.LogTypeAdjustment).
|
||||
Where("w.kandang_id = ?", kandangID).
|
||||
Where("f.name IN ?", []string{string(utils.FlagDOC), string(utils.FlagPakan), string(utils.FlagOVK)})
|
||||
|
||||
if start != nil {
|
||||
db = db.Where("sl.created_at >= ?", *start)
|
||||
}
|
||||
if end != nil {
|
||||
db = db.Where("sl.created_at < ?", *end)
|
||||
}
|
||||
|
||||
if err := db.Scan(&rows).Error; err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
func splitStockLogs(rows []stockLogSapronakRow, refFn func(stockLogSapronakRow) string) (map[uint][]SapronakDetailRow, map[uint][]SapronakDetailRow) {
|
||||
in := make(map[uint][]SapronakDetailRow)
|
||||
out := make(map[uint][]SapronakDetailRow)
|
||||
|
||||
for _, row := range rows {
|
||||
ref := fmt.Sprintf("ADJ-%d", row.ID)
|
||||
base := SapronakDetailRow{
|
||||
ProductID: row.ProductID,
|
||||
ProductName: row.ProductName,
|
||||
Flag: row.Flag,
|
||||
Date: row.CreatedAt,
|
||||
Reference: refFn(row),
|
||||
Price: row.Price,
|
||||
}
|
||||
|
||||
if row.Increase > 0 {
|
||||
incoming[row.ProductID] = append(incoming[row.ProductID], SapronakDetailRow{
|
||||
ProductID: row.ProductID,
|
||||
ProductName: row.ProductName,
|
||||
Flag: row.Flag,
|
||||
Date: row.CreatedAt,
|
||||
Reference: ref,
|
||||
QtyIn: row.Increase,
|
||||
QtyOut: 0,
|
||||
Price: row.Price,
|
||||
})
|
||||
d := base
|
||||
d.QtyIn = row.Increase
|
||||
in[row.ProductID] = append(in[row.ProductID], d)
|
||||
}
|
||||
if row.Decrease > 0 {
|
||||
outgoing[row.ProductID] = append(outgoing[row.ProductID], SapronakDetailRow{
|
||||
ProductID: row.ProductID,
|
||||
ProductName: row.ProductName,
|
||||
Flag: row.Flag,
|
||||
Date: row.CreatedAt,
|
||||
Reference: ref,
|
||||
QtyIn: 0,
|
||||
QtyOut: row.Decrease,
|
||||
Price: row.Price,
|
||||
})
|
||||
d := base
|
||||
d.QtyOut = row.Decrease
|
||||
out[row.ProductID] = append(out[row.ProductID], d)
|
||||
}
|
||||
}
|
||||
|
||||
return incoming, outgoing, nil
|
||||
return in, out
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakTransfers(ctx context.Context, kandangID uint, start, end *time.Time) (map[uint][]SapronakDetailRow, map[uint][]SapronakDetailRow, error) {
|
||||
incoming := make(map[uint][]SapronakDetailRow)
|
||||
outgoing := make(map[uint][]SapronakDetailRow)
|
||||
|
||||
rows := make([]struct {
|
||||
ID uint
|
||||
ProductID uint
|
||||
ProductName string
|
||||
Flag string
|
||||
CreatedAt *time.Time
|
||||
Increase float64
|
||||
Decrease float64
|
||||
Price float64
|
||||
}, 0)
|
||||
|
||||
db := r.DB().
|
||||
WithContext(ctx).
|
||||
Table("stock_logs sl").
|
||||
Select(`
|
||||
sl.id AS id,
|
||||
pw.product_id AS product_id,
|
||||
p.name AS product_name,
|
||||
f.name AS flag,
|
||||
sl.created_at AS created_at,
|
||||
COALESCE(sl.increase,0) AS increase,
|
||||
COALESCE(sl.decrease,0) AS decrease,
|
||||
COALESCE(p.product_price,0) AS price
|
||||
`).
|
||||
Joins("JOIN product_warehouses pw ON pw.id = sl.product_warehouse_id").
|
||||
Joins("JOIN products p ON p.id = pw.product_id").
|
||||
Joins("JOIN flags f ON f.flagable_id = p.id AND f.flagable_type = ?", entity.FlagableTypeProduct).
|
||||
Joins("JOIN warehouses w ON w.id = pw.warehouse_id").
|
||||
Where("sl.loggable_type = ?", entity.LogTypeTransfer).
|
||||
Where("w.kandang_id = ?", kandangID).
|
||||
Where("f.name IN ?", []string{string(utils.FlagDOC), string(utils.FlagPakan), string(utils.FlagOVK)})
|
||||
|
||||
if start != nil {
|
||||
db = db.Where("sl.created_at >= ?", *start)
|
||||
}
|
||||
if end != nil {
|
||||
db = db.Where("sl.created_at < ?", *end)
|
||||
}
|
||||
|
||||
if err := db.Scan(&rows).Error; err != nil {
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakAdjustments(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, map[uint][]SapronakDetailRow, error) {
|
||||
rows, err := r.fetchStockLogs(ctx, kandangID, entity.LogTypeAdjustment, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, row := range rows {
|
||||
ref := fmt.Sprintf("TRF-%d", row.ID)
|
||||
if row.Increase > 0 {
|
||||
incoming[row.ProductID] = append(incoming[row.ProductID], SapronakDetailRow{
|
||||
ProductID: row.ProductID,
|
||||
ProductName: row.ProductName,
|
||||
Flag: row.Flag,
|
||||
Date: row.CreatedAt,
|
||||
Reference: ref,
|
||||
QtyIn: row.Increase,
|
||||
QtyOut: 0,
|
||||
Price: row.Price,
|
||||
})
|
||||
}
|
||||
if row.Decrease > 0 {
|
||||
outgoing[row.ProductID] = append(outgoing[row.ProductID], SapronakDetailRow{
|
||||
ProductID: row.ProductID,
|
||||
ProductName: row.ProductName,
|
||||
Flag: row.Flag,
|
||||
Date: row.CreatedAt,
|
||||
Reference: ref,
|
||||
QtyIn: 0,
|
||||
QtyOut: row.Decrease,
|
||||
Price: row.Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return incoming, outgoing, nil
|
||||
in, out := splitStockLogs(rows, func(row stockLogSapronakRow) string { return fmt.Sprintf("ADJ-%d", row.ID) })
|
||||
return in, out, nil
|
||||
}
|
||||
|
||||
func (r *ClosingRepositoryImpl) FetchSapronakTransfers(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, map[uint][]SapronakDetailRow, error) {
|
||||
rows, err := r.fetchStockLogs(ctx, kandangID, entity.LogTypeTransfer, true)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
in, out := splitStockLogs(rows, func(row stockLogSapronakRow) string {
|
||||
if ref := strings.TrimSpace(row.MovementNumber); ref != "" {
|
||||
return ref
|
||||
}
|
||||
return fmt.Sprintf("TRF-%d", row.ID)
|
||||
})
|
||||
return in, out, nil
|
||||
}
|
||||
Reference in New Issue
Block a user