214 lines
4.7 KiB
Go
214 lines
4.7 KiB
Go
package storage
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"os"
|
|
"sync"
|
|
"path/filepath"
|
|
"time"
|
|
"crm-go/models"
|
|
)
|
|
|
|
type CustomerStorage interface {
|
|
GetAllCustomers() ([]models.Customer, error)
|
|
GetCustomerByID(id string) (*models.Customer, error)
|
|
CreateCustomer(customer models.Customer) error
|
|
UpdateCustomer(id string, updates models.UpdateCustomerRequest) error
|
|
DeleteCustomer(id string) error
|
|
SaveCustomers(customers []models.Customer) error
|
|
LoadCustomers() ([]models.Customer, error)
|
|
CustomerExists(customer models.Customer) (bool, error)
|
|
}
|
|
|
|
type customerStorage struct {
|
|
filePath string
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
func NewCustomerStorage(filePath string) CustomerStorage {
|
|
storage := &customerStorage{
|
|
filePath: filePath,
|
|
}
|
|
|
|
// Ensure the directory exists
|
|
dir := os.DirFS(filePath[:len(filePath)-len("/customers.json")])
|
|
_ = dir // Use the directory to ensure it exists
|
|
|
|
return storage
|
|
}
|
|
|
|
func (cs *customerStorage) GetAllCustomers() ([]models.Customer, error) {
|
|
cs.mutex.RLock()
|
|
defer cs.mutex.RUnlock()
|
|
|
|
return cs.LoadCustomers()
|
|
}
|
|
|
|
func (cs *customerStorage) GetCustomerByID(id string) (*models.Customer, error) {
|
|
cs.mutex.RLock()
|
|
defer cs.mutex.RUnlock()
|
|
|
|
customers, err := cs.LoadCustomers()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, customer := range customers {
|
|
if customer.ID == id {
|
|
return &customer, nil
|
|
}
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func (cs *customerStorage) CreateCustomer(customer models.Customer) error {
|
|
cs.mutex.Lock()
|
|
defer cs.mutex.Unlock()
|
|
|
|
if customer.ID == "" {
|
|
customer.ID = generateUUID()
|
|
}
|
|
|
|
if customer.CreatedAt.IsZero() {
|
|
customer.CreatedAt = time.Now()
|
|
}
|
|
|
|
customers, err := cs.LoadCustomers()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
customers = append(customers, customer)
|
|
|
|
return cs.SaveCustomers(customers)
|
|
}
|
|
|
|
func generateUUID() 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)
|
|
}
|
|
|
|
func (cs *customerStorage) UpdateCustomer(id string, updates models.UpdateCustomerRequest) error {
|
|
cs.mutex.Lock()
|
|
defer cs.mutex.Unlock()
|
|
|
|
customers, err := cs.LoadCustomers()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i, customer := range customers {
|
|
if customer.ID == id {
|
|
if updates.CustomerName != nil {
|
|
customers[i].CustomerName = *updates.CustomerName
|
|
}
|
|
if updates.IntendedProduct != nil {
|
|
customers[i].IntendedProduct = *updates.IntendedProduct
|
|
}
|
|
if updates.Version != nil {
|
|
customers[i].Version = *updates.Version
|
|
}
|
|
if updates.Description != nil {
|
|
customers[i].Description = *updates.Description
|
|
}
|
|
if updates.Solution != nil {
|
|
customers[i].Solution = *updates.Solution
|
|
}
|
|
if updates.Type != nil {
|
|
customers[i].Type = *updates.Type
|
|
}
|
|
if updates.Module != nil {
|
|
customers[i].Module = *updates.Module
|
|
}
|
|
if updates.StatusProgress != nil {
|
|
customers[i].StatusProgress = *updates.StatusProgress
|
|
}
|
|
if updates.Reporter != nil {
|
|
customers[i].Reporter = *updates.Reporter
|
|
}
|
|
|
|
return cs.SaveCustomers(customers)
|
|
}
|
|
}
|
|
|
|
return nil // Customer not found, but not an error
|
|
}
|
|
|
|
func (cs *customerStorage) DeleteCustomer(id string) error {
|
|
cs.mutex.Lock()
|
|
defer cs.mutex.Unlock()
|
|
|
|
customers, err := cs.LoadCustomers()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i, customer := range customers {
|
|
if customer.ID == id {
|
|
customers = append(customers[:i], customers[i+1:]...)
|
|
return cs.SaveCustomers(customers)
|
|
}
|
|
}
|
|
|
|
return nil // Customer not found, but not an error
|
|
}
|
|
|
|
func (cs *customerStorage) SaveCustomers(customers []models.Customer) error {
|
|
// Ensure the directory exists
|
|
dir := filepath.Dir(cs.filePath)
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
data, err := json.MarshalIndent(customers, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(cs.filePath, data, 0644)
|
|
}
|
|
|
|
func (cs *customerStorage) LoadCustomers() ([]models.Customer, error) {
|
|
// Check if file exists
|
|
if _, err := os.Stat(cs.filePath); os.IsNotExist(err) {
|
|
// Return empty slice if file doesn't exist
|
|
return []models.Customer{}, nil
|
|
}
|
|
|
|
data, err := os.ReadFile(cs.filePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var customers []models.Customer
|
|
if err := json.Unmarshal(data, &customers); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return customers, nil
|
|
}
|
|
|
|
func (cs *customerStorage) CustomerExists(customer models.Customer) (bool, error) {
|
|
cs.mutex.RLock()
|
|
defer cs.mutex.RUnlock()
|
|
|
|
customers, err := cs.LoadCustomers()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
for _, existingCustomer := range customers {
|
|
if existingCustomer.Description == customer.Description {
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
} |