material_manage_system/internal/repository/material_log.go
2026-10-09 10:38:02 +08:00

159 lines
4.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"database/sql"
"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) insertLog(execer sqlExecer, log *model.MaterialLog) error {
query := `INSERT INTO material_logs (operation_type, material_id, old_value, new_value, operator, description) VALUES (?, ?, ?, ?, ?, ?)`
result, err := execer.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) Create(log *model.MaterialLog) error {
return r.insertLog(database.DB, log)
}
// CreateTx 在调用方事务内写入日志,便于和物料主记录的修改一起提交或回滚。
func (r *MaterialLogRepo) CreateTx(tx *sql.Tx, log *model.MaterialLog) error {
return r.insertLog(tx, log)
}
// List 只返回当前公司物料的日志:material_logs 本身不带组织列,经 materials
// 关联过滤,避免 A 看到 B 的物料变更记录。
func (r *MaterialLogRepo) List(organizationID int64, operationType, materialId string, startDate, endDate string, limit, offset int) ([]model.MaterialLog, int64, error) {
countQuery := `SELECT COUNT(*) FROM material_logs ml JOIN materials m ON m.id = ml.material_id WHERE m.organization_id = ?`
countArgs := []interface{}{organizationID}
if operationType != "" {
countQuery += ` AND ml.operation_type = ?`
countArgs = append(countArgs, operationType)
}
if materialId != "" {
countQuery += ` AND ml.material_id = ?`
countArgs = append(countArgs, materialId)
}
if startDate != "" {
countQuery += ` AND ml.created_at >= ?`
countArgs = append(countArgs, startDate)
}
if endDate != "" {
countQuery += ` AND ml.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 ml.id, ml.operation_type, ml.material_id, ml.old_value, ml.new_value, ml.operator, ml.description, ml.created_at
FROM material_logs ml JOIN materials m ON m.id = ml.material_id WHERE m.organization_id = ?`
args := []interface{}{organizationID}
if operationType != "" {
query += ` AND ml.operation_type = ?`
args = append(args, operationType)
}
if materialId != "" {
query += ` AND ml.material_id = ?`
args = append(args, materialId)
}
if startDate != "" {
query += ` AND ml.created_at >= ?`
args = append(args, startDate)
}
if endDate != "" {
query += ` AND ml.created_at <= ?`
args = append(args, normalizeEndDate(endDate))
}
query += ` ORDER BY ml.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
}
// GetByMaterialID 只返回属于当前公司的该物料日志;物料不属于本公司时结果为空。
func (r *MaterialLogRepo) GetByMaterialID(organizationID, materialID int64) ([]model.MaterialLog, error) {
query := `SELECT ml.id, ml.operation_type, ml.material_id, ml.old_value, ml.new_value, ml.operator, ml.description, ml.created_at
FROM material_logs ml JOIN materials m ON m.id = ml.material_id
WHERE m.organization_id = ? AND ml.material_id = ? ORDER BY ml.id DESC`
rows, err := database.DB.Query(query, organizationID, 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
}