crm/internal/storage/mysql_trial_period_storage.go

225 lines
5.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, COALESCE(source, '') as source, COALESCE(intended_product, '') as intended_product,
COALESCE(deal_status, '') as deal_status, 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.IntendedProduct, &tp.DealStatus,
&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, COALESCE(intended_product, '') as intended_product,
COALESCE(deal_status, '') as deal_status, 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.IntendedProduct, &tp.DealStatus,
&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, COALESCE(intended_product, '') as intended_product,
COALESCE(deal_status, '') as deal_status, 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.IntendedProduct, &tp.DealStatus,
&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, intended_product, deal_status, 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.IntendedProduct,
trialPeriod.DealStatus, 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.IntendedProduct != nil {
existing.IntendedProduct = *updates.IntendedProduct
}
if updates.DealStatus != nil {
existing.DealStatus = *updates.DealStatus
}
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 = ?, intended_product = ?, deal_status = ?, 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.IntendedProduct, existing.DealStatus,
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)
}