package storage import ( "crm-go/models" "crypto/rand" "database/sql" "encoding/hex" "fmt" "strings" "time" ) type mysqlTrialPeriodStorage struct { db *sql.DB } // NewMySQLTrialPeriodStorage 创建MySQL试用期存储 func NewMySQLTrialPeriodStorage() TrialPeriodStorage { return &mysqlTrialPeriodStorage{ db: GetDB(), } } func (ts *mysqlTrialPeriodStorage) GetAllTrialPeriods() ([]models.TrialPeriod, error) { query := ` SELECT id, customer_name, COALESCE(source, '') as source, start_time, end_time, is_trial, created_at FROM trial_periods ORDER BY created_at DESC ` rows, err := ts.db.Query(query) if err != nil { return nil, err } defer rows.Close() var trialPeriods []models.TrialPeriod for rows.Next() { var tp models.TrialPeriod var isTrial int err := rows.Scan( &tp.ID, &tp.CustomerName, &tp.Source, &tp.StartTime, &tp.EndTime, &isTrial, &tp.CreatedAt, ) if err != nil { return nil, err } tp.IsTrial = isTrial == 1 trialPeriods = append(trialPeriods, tp) } return trialPeriods, rows.Err() } func (ts *mysqlTrialPeriodStorage) GetTrialPeriodsByCustomerID(customerID string) ([]models.TrialPeriod, error) { query := ` SELECT id, customer_name, COALESCE(source, '') as source, start_time, end_time, is_trial, created_at FROM trial_periods WHERE customer_name = ? ORDER BY end_time DESC ` rows, err := ts.db.Query(query, customerID) if err != nil { return nil, err } defer rows.Close() var trialPeriods []models.TrialPeriod for rows.Next() { var tp models.TrialPeriod var isTrial int err := rows.Scan( &tp.ID, &tp.CustomerName, &tp.Source, &tp.StartTime, &tp.EndTime, &isTrial, &tp.CreatedAt, ) if err != nil { return nil, err } tp.IsTrial = isTrial == 1 trialPeriods = append(trialPeriods, tp) } return trialPeriods, rows.Err() } func (ts *mysqlTrialPeriodStorage) GetTrialPeriodByID(id string) (*models.TrialPeriod, error) { query := ` SELECT id, customer_name, COALESCE(source, '') as source, start_time, end_time, is_trial, created_at FROM trial_periods WHERE id = ? ` var tp models.TrialPeriod var isTrial int err := ts.db.QueryRow(query, id).Scan( &tp.ID, &tp.CustomerName, &tp.Source, &tp.StartTime, &tp.EndTime, &isTrial, &tp.CreatedAt, ) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, err } tp.IsTrial = isTrial == 1 return &tp, nil } func (ts *mysqlTrialPeriodStorage) CreateTrialPeriod(trialPeriod models.TrialPeriod) (*models.TrialPeriod, error) { if trialPeriod.ID == "" { trialPeriod.ID = generateTrialPeriodMySQLUUID() } if trialPeriod.CreatedAt.IsZero() { trialPeriod.CreatedAt = time.Now() } query := ` INSERT INTO trial_periods (id, customer_name, source, start_time, end_time, is_trial, created_at) VALUES (?, ?, ?, ?, ?, ?, ?) ` isTrial := 0 if trialPeriod.IsTrial { isTrial = 1 } _, err := ts.db.Exec(query, trialPeriod.ID, trialPeriod.CustomerName, trialPeriod.Source, trialPeriod.StartTime, trialPeriod.EndTime, isTrial, trialPeriod.CreatedAt, ) if err != nil { return nil, err } return &trialPeriod, nil } func (ts *mysqlTrialPeriodStorage) UpdateTrialPeriod(id string, updates models.UpdateTrialPeriodRequest) error { // 首先获取现有记录 existing, err := ts.GetTrialPeriodByID(id) if err != nil || existing == nil { return err } // 应用更新 if updates.CustomerName != nil { existing.CustomerName = *updates.CustomerName } if updates.Source != nil { existing.Source = *updates.Source } if updates.StartTime != nil { startTime, err := time.Parse(time.RFC3339, *updates.StartTime) if err == nil { existing.StartTime = startTime } } if updates.EndTime != nil { endTime, err := time.Parse(time.RFC3339, *updates.EndTime) if err == nil { existing.EndTime = endTime } } if updates.IsTrial != nil { existing.IsTrial = *updates.IsTrial } query := ` UPDATE trial_periods SET customer_name = ?, source = ?, start_time = ?, end_time = ?, is_trial = ? WHERE id = ? ` isTrial := 0 if existing.IsTrial { isTrial = 1 } _, err = ts.db.Exec(query, existing.CustomerName, existing.Source, existing.StartTime, existing.EndTime, isTrial, id, ) return err } func (ts *mysqlTrialPeriodStorage) DeleteTrialPeriod(id string) error { query := `DELETE FROM trial_periods WHERE id = ?` _, err := ts.db.Exec(query, id) if err != nil { // 检查是否是权限不足错误 if strings.Contains(err.Error(), "command denied") || strings.Contains(err.Error(), "DELETE command denied") { return fmt.Errorf("数据库权限不足:无法执行删除操作,请联系管理员") } return err } return nil } func generateTrialPeriodMySQLUUID() string { bytes := make([]byte, 16) rand.Read(bytes) bytes[6] = (bytes[6] & 0x0f) | 0x40 // Version 4 bytes[8] = (bytes[8] & 0x3f) | 0x80 // Variant return hex.EncodeToString(bytes) }