217 lines
4.9 KiB
Go
217 lines
4.9 KiB
Go
package storage
|
|
|
|
import (
|
|
"crm-go/models"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type TrialPeriodStorage interface {
|
|
GetAllTrialPeriods() ([]models.TrialPeriod, error)
|
|
GetTrialPeriodsByCustomerID(customerID string) ([]models.TrialPeriod, error)
|
|
GetTrialPeriodByID(id string) (*models.TrialPeriod, error)
|
|
CreateTrialPeriod(trialPeriod models.TrialPeriod) (*models.TrialPeriod, error)
|
|
UpdateTrialPeriod(id string, updates models.UpdateTrialPeriodRequest) error
|
|
DeleteTrialPeriod(id string) error
|
|
}
|
|
|
|
type trialPeriodStorage struct {
|
|
filePath string
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
func NewTrialPeriodStorage(filePath string) TrialPeriodStorage {
|
|
storage := &trialPeriodStorage{
|
|
filePath: filePath,
|
|
}
|
|
return storage
|
|
}
|
|
|
|
func (ts *trialPeriodStorage) GetAllTrialPeriods() ([]models.TrialPeriod, error) {
|
|
ts.mutex.RLock()
|
|
defer ts.mutex.RUnlock()
|
|
|
|
trialPeriods, err := ts.loadTrialPeriods()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Sort by CreatedAt in descending order (newest first)
|
|
for i := 0; i < len(trialPeriods)-1; i++ {
|
|
for j := i + 1; j < len(trialPeriods); j++ {
|
|
if trialPeriods[i].CreatedAt.Before(trialPeriods[j].CreatedAt) {
|
|
trialPeriods[i], trialPeriods[j] = trialPeriods[j], trialPeriods[i]
|
|
}
|
|
}
|
|
}
|
|
|
|
return trialPeriods, nil
|
|
}
|
|
|
|
func (ts *trialPeriodStorage) GetTrialPeriodsByCustomerID(customerID string) ([]models.TrialPeriod, error) {
|
|
ts.mutex.RLock()
|
|
defer ts.mutex.RUnlock()
|
|
|
|
allPeriods, err := ts.loadTrialPeriods()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var customerPeriods []models.TrialPeriod
|
|
for _, period := range allPeriods {
|
|
if period.CustomerID == customerID {
|
|
customerPeriods = append(customerPeriods, period)
|
|
}
|
|
}
|
|
|
|
// Sort by EndTime in descending order (latest first)
|
|
for i := 0; i < len(customerPeriods)-1; i++ {
|
|
for j := i + 1; j < len(customerPeriods); j++ {
|
|
if customerPeriods[i].EndTime.Before(customerPeriods[j].EndTime) {
|
|
customerPeriods[i], customerPeriods[j] = customerPeriods[j], customerPeriods[i]
|
|
}
|
|
}
|
|
}
|
|
|
|
return customerPeriods, nil
|
|
}
|
|
|
|
func (ts *trialPeriodStorage) GetTrialPeriodByID(id string) (*models.TrialPeriod, error) {
|
|
ts.mutex.RLock()
|
|
defer ts.mutex.RUnlock()
|
|
|
|
trialPeriods, err := ts.loadTrialPeriods()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, period := range trialPeriods {
|
|
if period.ID == id {
|
|
return &period, nil
|
|
}
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func (ts *trialPeriodStorage) CreateTrialPeriod(trialPeriod models.TrialPeriod) (*models.TrialPeriod, error) {
|
|
ts.mutex.Lock()
|
|
defer ts.mutex.Unlock()
|
|
|
|
if trialPeriod.ID == "" {
|
|
trialPeriod.ID = generateTrialPeriodUUID()
|
|
}
|
|
|
|
if trialPeriod.CreatedAt.IsZero() {
|
|
trialPeriod.CreatedAt = time.Now()
|
|
}
|
|
|
|
trialPeriods, err := ts.loadTrialPeriods()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
trialPeriods = append(trialPeriods, trialPeriod)
|
|
|
|
if err := ts.saveTrialPeriods(trialPeriods); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &trialPeriod, nil
|
|
}
|
|
|
|
func (ts *trialPeriodStorage) UpdateTrialPeriod(id string, updates models.UpdateTrialPeriodRequest) error {
|
|
ts.mutex.Lock()
|
|
defer ts.mutex.Unlock()
|
|
|
|
trialPeriods, err := ts.loadTrialPeriods()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i, period := range trialPeriods {
|
|
if period.ID == id {
|
|
if updates.StartTime != nil {
|
|
startTime, err := time.Parse(time.RFC3339, *updates.StartTime)
|
|
if err == nil {
|
|
trialPeriods[i].StartTime = startTime
|
|
}
|
|
}
|
|
if updates.EndTime != nil {
|
|
endTime, err := time.Parse(time.RFC3339, *updates.EndTime)
|
|
if err == nil {
|
|
trialPeriods[i].EndTime = endTime
|
|
}
|
|
}
|
|
|
|
return ts.saveTrialPeriods(trialPeriods)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ts *trialPeriodStorage) DeleteTrialPeriod(id string) error {
|
|
ts.mutex.Lock()
|
|
defer ts.mutex.Unlock()
|
|
|
|
trialPeriods, err := ts.loadTrialPeriods()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i, period := range trialPeriods {
|
|
if period.ID == id {
|
|
trialPeriods = append(trialPeriods[:i], trialPeriods[i+1:]...)
|
|
return ts.saveTrialPeriods(trialPeriods)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ts *trialPeriodStorage) saveTrialPeriods(trialPeriods []models.TrialPeriod) error {
|
|
dir := filepath.Dir(ts.filePath)
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
data, err := json.MarshalIndent(trialPeriods, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(ts.filePath, data, 0644)
|
|
}
|
|
|
|
func (ts *trialPeriodStorage) loadTrialPeriods() ([]models.TrialPeriod, error) {
|
|
if _, err := os.Stat(ts.filePath); os.IsNotExist(err) {
|
|
return []models.TrialPeriod{}, nil
|
|
}
|
|
|
|
data, err := os.ReadFile(ts.filePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var trialPeriods []models.TrialPeriod
|
|
if err := json.Unmarshal(data, &trialPeriods); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return trialPeriods, nil
|
|
}
|
|
|
|
func generateTrialPeriodUUID() string {
|
|
bytes := make([]byte, 16)
|
|
rand.Read(bytes)
|
|
bytes[6] = (bytes[6] & 0x0f) | 0x40
|
|
bytes[8] = (bytes[8] & 0x3f) | 0x80
|
|
return hex.EncodeToString(bytes)
|
|
}
|