Files
license-manager/backend/internal/repository/customer_repository.go
T

239 lines
6.7 KiB
Go

package repository
import (
"context"
"fmt"
"strings"
"time"
"gorm.io/gorm"
"license-manager/internal/models"
)
type customerRepository struct {
db *gorm.DB
}
// NewCustomerRepository 创建客户数据访问实例
func NewCustomerRepository(db *gorm.DB) CustomerRepository {
return &customerRepository{
db: db,
}
}
// GetCustomerList 查询客户列表
func (r *customerRepository) GetCustomerList(ctx context.Context, req *models.CustomerListRequest) (*models.CustomerListResponse, error) {
// 设置默认值
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 20
}
if req.PageSize > 100 {
req.PageSize = 100
}
if req.Sort == "" {
req.Sort = "created_at"
}
if req.Order == "" {
req.Order = "desc"
}
// 构建查询
query := r.db.Model(&models.Customer{})
// 搜索关键词筛选
if req.Search != "" {
searchTerm := "%" + strings.TrimSpace(req.Search) + "%"
query = query.Where(
"customer_code LIKE ? OR customer_name LIKE ? OR contact_person LIKE ? OR email LIKE ?",
searchTerm, searchTerm, searchTerm, searchTerm,
)
}
// 客户类型筛选
if req.CustomerType != "" {
query = query.Where("customer_type = ?", req.CustomerType)
}
// 客户等级筛选
if req.CustomerLevel != "" {
query = query.Where("customer_level = ?", req.CustomerLevel)
}
// 状态筛选
if req.Status != "" {
query = query.Where("status = ?", req.Status)
}
// 计算总数
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, fmt.Errorf("failed to count customers: %w", err)
}
// 排序和分页
offset := (req.Page - 1) * req.PageSize
orderClause := fmt.Sprintf("%s %s", req.Sort, strings.ToUpper(req.Order))
query = query.Order(orderClause).Offset(offset).Limit(req.PageSize)
// 查询数据
var customers []models.Customer
if err := query.Find(&customers).Error; err != nil {
return nil, fmt.Errorf("failed to query customers: %w", err)
}
// 转换为响应格式
customerList := make([]models.CustomerListItem, 0, len(customers))
for _, customer := range customers {
customerList = append(customerList, models.CustomerListItem{
ID: customer.ID,
CustomerCode: customer.CustomerCode,
CustomerName: customer.CustomerName,
CustomerType: customer.CustomerType,
ContactPerson: customer.ContactPerson,
Email: customer.Email,
CustomerLevel: customer.CustomerLevel,
Status: customer.Status,
CreatedAt: customer.CreatedAt.Format(time.RFC3339),
})
}
// 计算总页数
totalPages := int(total) / req.PageSize
if int(total)%req.PageSize > 0 {
totalPages++
}
return &models.CustomerListResponse{
List: customerList,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
TotalPages: totalPages,
}, nil
}
// GetCustomerByID 根据ID获取客户信息
func (r *customerRepository) GetCustomerByID(ctx context.Context, id string) (*models.Customer, error) {
var customer models.Customer
if err := r.db.Where("id = ?", id).First(&customer).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrCustomerNotFound
}
return nil, fmt.Errorf("failed to get customer by id: %w", err)
}
return &customer, nil
}
// CreateCustomer 创建客户
func (r *customerRepository) CreateCustomer(ctx context.Context, customer *models.Customer) error {
// 使用事务确保数据一致性
return r.db.Transaction(func(tx *gorm.DB) error {
// 生成客户编码
customerCode, err := r.generateCustomerCode(tx)
if err != nil {
return fmt.Errorf("failed to generate customer code: %w", err)
}
customer.CustomerCode = customerCode
// 创建客户
if err := tx.Create(customer).Error; err != nil {
return fmt.Errorf("failed to create customer: %w", err)
}
return nil
})
}
// generateCustomerCode 生成客户编码
func (r *customerRepository) generateCustomerCode(tx *gorm.DB) (string, error) {
currentYear := time.Now().Year()
// 查询或创建当年的序列号记录
var sequence models.CustomerCodeSequence
err := tx.Where("year = ?", currentYear).First(&sequence).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
// 创建新年份的序列号记录
sequence = models.CustomerCodeSequence{
Year: currentYear,
SequenceNumber: 1,
}
if err := tx.Create(&sequence).Error; err != nil {
return "", fmt.Errorf("failed to create sequence: %w", err)
}
} else {
return "", fmt.Errorf("failed to query sequence: %w", err)
}
} else {
// 更新序列号
sequence.SequenceNumber++
if err := tx.Save(&sequence).Error; err != nil {
return "", fmt.Errorf("failed to update sequence: %w", err)
}
}
// 生成客户编码:CUS-YYYY-NNNN
customerCode := fmt.Sprintf("CUS-%d-%04d", currentYear, sequence.SequenceNumber)
return customerCode, nil
}
// UpdateCustomer 更新客户信息
func (r *customerRepository) UpdateCustomer(ctx context.Context, customer *models.Customer) error {
if err := r.db.Save(customer).Error; err != nil {
return fmt.Errorf("failed to update customer: %w", err)
}
return nil
}
// DeleteCustomer 删除客户(物理删除)
func (r *customerRepository) DeleteCustomer(ctx context.Context, id string) error {
result := r.db.Unscoped().Where("id = ?", id).Delete(&models.Customer{})
if result.Error != nil {
return fmt.Errorf("failed to delete customer: %w", result.Error)
}
if result.RowsAffected == 0 {
return ErrCustomerNotFound
}
return nil
}
// CheckCustomerHasAuthorizationCodes 检查客户是否有关联的授权码
func (r *customerRepository) CheckCustomerHasAuthorizationCodes(ctx context.Context, customerID string) (bool, error) {
var count int64
err := r.db.Model(&models.AuthorizationCode{}).Where("customer_id = ?", customerID).Count(&count).Error
if err != nil {
return false, fmt.Errorf("failed to check authorization codes: %w", err)
}
return count > 0, nil
}
// CheckCustomerHasLicenses 检查客户是否有关联的许可证
func (r *customerRepository) CheckCustomerHasLicenses(ctx context.Context, customerID string) (bool, error) {
var count int64
err := r.db.Model(&models.License{}).Where("customer_id = ?", customerID).Count(&count).Error
if err != nil {
return false, fmt.Errorf("failed to check licenses: %w", err)
}
return count > 0, nil
}
// GetCustomerCount 获取客户总数(用于统计)
func (r *customerRepository) GetCustomerCount(ctx context.Context, filters map[string]interface{}) (int64, error) {
var count int64
query := r.db.Model(&models.Customer{})
// 应用筛选条件
for key, value := range filters {
query = query.Where(fmt.Sprintf("%s = ?", key), value)
}
if err := query.Count(&count).Error; err != nil {
return 0, fmt.Errorf("failed to count customers: %w", err)
}
return count, nil
}