package repository import ( "strings" "github.com/wmms/wmms/internal/model" "github.com/wmms/wmms/pkg/database" ) type MaterialLogRepo struct{} func NewMaterialLogRepo() *MaterialLogRepo { return &MaterialLogRepo{} } // normalizeEndDate ensures endDate has a time component for proper date range filtering func normalizeEndDate(endDate string) string { if endDate == "" { return "" } // If already contains a time component (has : in time part like 23:59:59), return as-is if strings.Contains(endDate, " ") && strings.Contains(strings.Split(endDate, " ")[1], ":") { return endDate } // Append end of day time return endDate + " 23:59:59" } func (r *MaterialLogRepo) Create(log *model.MaterialLog) error { query := `INSERT INTO material_logs (operation_type, material_id, old_value, new_value, operator, description) VALUES (?, ?, ?, ?, ?, ?)` result, err := database.DB.Exec(query, log.OperationType, log.MaterialID, log.OldValue, log.NewValue, log.Operator, log.Description) if err != nil { return err } id, err := result.LastInsertId() if err != nil { return err } log.ID = id return nil } func (r *MaterialLogRepo) List(operationType, materialId string, startDate, endDate string, limit, offset int) ([]model.MaterialLog, int64, error) { countQuery := `SELECT COUNT(*) FROM material_logs WHERE 1=1` var countArgs []interface{} if operationType != "" { countQuery += ` AND operation_type = ?` countArgs = append(countArgs, operationType) } if materialId != "" { countQuery += ` AND material_id = ?` countArgs = append(countArgs, materialId) } if startDate != "" { countQuery += ` AND created_at >= ?` countArgs = append(countArgs, startDate) } if endDate != "" { countQuery += ` AND created_at <= ?` countArgs = append(countArgs, normalizeEndDate(endDate)) } var total int64 err := database.DB.QueryRow(countQuery, countArgs...).Scan(&total) if err != nil { return nil, 0, err } query := `SELECT id, operation_type, material_id, old_value, new_value, operator, description, created_at FROM material_logs WHERE 1=1` var args []interface{} if operationType != "" { query += ` AND operation_type = ?` args = append(args, operationType) } if materialId != "" { query += ` AND material_id = ?` args = append(args, materialId) } if startDate != "" { query += ` AND created_at >= ?` args = append(args, startDate) } if endDate != "" { query += ` AND created_at <= ?` args = append(args, normalizeEndDate(endDate)) } query += ` ORDER BY id DESC LIMIT ? OFFSET ?` args = append(args, limit, offset) rows, err := database.DB.Query(query, args...) if err != nil { return nil, 0, err } defer rows.Close() var logs []model.MaterialLog for rows.Next() { var log model.MaterialLog var oldValue, newValue []byte err := rows.Scan(&log.ID, &log.OperationType, &log.MaterialID, &oldValue, &newValue, &log.Operator, &log.Description, &log.CreatedAt) if err != nil { return nil, 0, err } if oldValue != nil { log.OldValue = string(oldValue) } if newValue != nil { log.NewValue = string(newValue) } logs = append(logs, log) } return logs, total, nil } func (r *MaterialLogRepo) GetByMaterialID(materialID int64) ([]model.MaterialLog, error) { query := `SELECT id, operation_type, material_id, old_value, new_value, operator, description, created_at FROM material_logs WHERE material_id = ? ORDER BY id DESC` rows, err := database.DB.Query(query, materialID) if err != nil { return nil, err } defer rows.Close() var logs []model.MaterialLog for rows.Next() { var log model.MaterialLog var oldValue, newValue []byte err := rows.Scan(&log.ID, &log.OperationType, &log.MaterialID, &oldValue, &newValue, &log.Operator, &log.Description, &log.CreatedAt) if err != nil { return nil, err } if oldValue != nil { log.OldValue = string(oldValue) } if newValue != nil { log.NewValue = string(newValue) } logs = append(logs, log) } return logs, nil }