213 lines
4.6 KiB
Go
213 lines
4.6 KiB
Go
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, 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.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, 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.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, 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.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, 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.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.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 = ?, start_time = ?, end_time = ?, is_trial = ?
|
|
WHERE id = ?
|
|
`
|
|
|
|
isTrial := 0
|
|
if existing.IsTrial {
|
|
isTrial = 1
|
|
}
|
|
|
|
_, err = ts.db.Exec(query,
|
|
existing.CustomerName, 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)
|
|
}
|