Re-migrate code

This commit is contained in:
2026-03-02 10:24:11 +08:00
parent 51025195a5
commit f80f2b43ce
6 changed files with 479 additions and 103 deletions

View File

@@ -2,6 +2,10 @@ package services
import (
"errors"
"fmt"
"time"
"gorm.io/gorm"
"git.beifan.cn/trace-system/backend-go/database"
"git.beifan.cn/trace-system/backend-go/models"
@@ -15,31 +19,152 @@ func (s *CompaniesService) FindAll(page int, limit int, search string) ([]models
var companies []models.Company
var total int64
offset := (page - 1) * limit
db := database.DB
if page < 1 {
page = 1
}
if limit < 1 {
limit = 20
}
offset := (page - 1) * limit
db := database.DB.Model(&models.Company{})
// 搜索条件
if search != "" {
db = db.Where("company_name LIKE ?", "%"+search+"%")
}
// 获取总数
db.Count(&total)
if err := db.Count(&total).Error; err != nil {
return nil, 0, 0, errors.New("查询企业总数失败")
}
// 分页查询
result := db.Order("created_at DESC").Offset(offset).Limit(limit).Find(&companies)
result := db.Order("updated_at DESC").Offset(offset).Limit(limit).Find(&companies)
if result.Error != nil {
return nil, 0, 0, errors.New("查询企业列表失败")
}
totalPages := (int(total) + limit - 1) / limit
totalPages := 0
if total > 0 {
totalPages = (int(total) + limit - 1) / limit
}
return companies, int(total), totalPages, nil
}
// FindOne 获取单个企业详情(含分页序列号)
func (s *CompaniesService) FindOne(companyName string, page int, limit int) (map[string]any, error) {
if page < 1 {
page = 1
}
if limit < 1 {
limit = 20
}
var company models.Company
if err := database.DB.Where("company_name = ?", companyName).First(&company).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("企业不存在")
}
return nil, errors.New("查询企业失败")
}
var allSerials []models.Serial
if err := database.DB.Preload("User").Where("company_name = ?", companyName).Order("created_at DESC").Find(&allSerials).Error; err != nil {
return nil, errors.New("查询企业序列号失败")
}
now := time.Now()
serialCount := len(allSerials)
activeCount := 0
disabledCount := 0
expiredCount := 0
for _, serial := range allSerials {
if !serial.IsActive {
disabledCount++
continue
}
if serial.ValidUntil != nil && serial.ValidUntil.Before(now) {
expiredCount++
continue
}
activeCount++
}
offset := (page - 1) * limit
end := offset + limit
if offset > len(allSerials) {
offset = len(allSerials)
}
if end > len(allSerials) {
end = len(allSerials)
}
paginatedSerials := allSerials[offset:end]
serialItems := make([]map[string]any, 0, len(paginatedSerials))
for _, serial := range paginatedSerials {
createdBy := ""
if serial.User != nil {
createdBy = serial.User.Name
}
serialItems = append(serialItems, map[string]any{
"serialNumber": serial.SerialNumber,
"validUntil": serial.ValidUntil,
"isActive": serial.IsActive,
"createdAt": serial.CreatedAt,
"createdBy": createdBy,
})
}
monthlyStatsMap := map[string]int{}
for i := 11; i >= 0; i-- {
date := time.Date(now.Year(), now.Month()-time.Month(i), 1, 0, 0, 0, 0, time.Local)
monthKey := date.Format("2006-01")
monthlyStatsMap[monthKey] = 0
}
for _, serial := range allSerials {
monthKey := serial.CreatedAt.Format("2006-01")
if _, ok := monthlyStatsMap[monthKey]; ok {
monthlyStatsMap[monthKey]++
}
}
monthlyStats := make([]map[string]any, 0)
for i := 11; i >= 0; i-- {
date := time.Date(now.Year(), now.Month()-time.Month(i), 1, 0, 0, 0, 0, time.Local)
monthKey := date.Format("2006-01")
count := monthlyStatsMap[monthKey]
if count > 0 {
monthlyStats = append(monthlyStats, map[string]any{"month": monthKey, "count": count})
}
}
return map[string]any{
"companyName": company.CompanyName,
"serialCount": serialCount,
"activeCount": activeCount,
"disabledCount": disabledCount,
"expiredCount": expiredCount,
"firstCreated": company.CreatedAt,
"lastCreated": company.UpdatedAt,
"status": map[bool]string{true: "active", false: "disabled"}[company.IsActive],
"serials": serialItems,
"monthlyStats": monthlyStats,
"pagination": map[string]any{
"page": page,
"limit": limit,
"total": serialCount,
"totalPages": func() int {
if serialCount == 0 {
return 0
}
return (serialCount + limit - 1) / limit
}(),
},
}, nil
}
// Create 创建企业
func (s *CompaniesService) Create(companyName string) (*models.Company, error) {
// 检查企业是否已存在
var existingCompany models.Company
result := database.DB.Where("company_name = ?", companyName).First(&existingCompany)
if result.Error == nil {
@@ -60,57 +185,201 @@ func (s *CompaniesService) Create(companyName string) (*models.Company, error) {
}
// Update 更新企业信息
func (s *CompaniesService) Update(companyName string, newCompanyName string, isActive bool) (*models.Company, error) {
func (s *CompaniesService) Update(companyName string, newCompanyName string, isActive *bool) (*models.Company, error) {
var company models.Company
result := database.DB.Where("company_name = ?", companyName).First(&company)
if result.Error != nil {
return nil, errors.New("企业不存在")
}
// 如果企业名称已变更,检查新名称是否已存在
if newCompanyName == "" {
newCompanyName = companyName
}
if newCompanyName != companyName {
var existingCompany models.Company
checkResult := database.DB.Where("company_name = ?", newCompanyName).First(&existingCompany)
if checkResult.Error == nil {
return nil, errors.New("企业名称已存在")
}
company.CompanyName = newCompanyName
}
company.IsActive = isActive
err := database.DB.Transaction(func(tx *gorm.DB) error {
if newCompanyName != companyName {
if err := tx.Model(&models.Serial{}).Where("company_name = ?", companyName).Update("company_name", newCompanyName).Error; err != nil {
return fmt.Errorf("更新企业赋码企业名称失败: %w", err)
}
if err := tx.Model(&models.EmployeeSerial{}).Where("company_name = ?", companyName).Update("company_name", newCompanyName).Error; err != nil {
return fmt.Errorf("更新员工赋码企业名称失败: %w", err)
}
company.CompanyName = newCompanyName
}
result = database.DB.Save(&company)
if result.Error != nil {
return nil, errors.New("更新企业信息失败")
if isActive != nil {
company.IsActive = *isActive
}
if err := tx.Save(&company).Error; err != nil {
return fmt.Errorf("更新企业信息失败: %w", err)
}
return nil
})
if err != nil {
return nil, errors.New(err.Error())
}
return &company, nil
}
// Delete 删除企业
// Delete 删除企业(同时删除关联序列号)
func (s *CompaniesService) Delete(companyName string) error {
var company models.Company
result := database.DB.Where("company_name = ?", companyName).First(&company)
if result.Error != nil {
if err := database.DB.Where("company_name = ?", companyName).First(&company).Error; err != nil {
return errors.New("企业不存在")
}
// 检查企业是否有关联的序列号
var serialCount int64
database.DB.Model(&models.Serial{}).Where("company_name = ?", companyName).Count(&serialCount)
if serialCount > 0 {
return errors.New("企业下还有序列号,无法删除")
}
result = database.DB.Delete(&company)
if result.Error != nil {
if err := database.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("company_name = ?", companyName).Delete(&models.Serial{}).Error; err != nil {
return err
}
if err := tx.Where("company_name = ?", companyName).Delete(&models.EmployeeSerial{}).Error; err != nil {
return err
}
if err := tx.Delete(&company).Error; err != nil {
return err
}
return nil
}); err != nil {
return errors.New("删除企业失败")
}
return nil
}
// DeleteSerial 删除企业下指定企业赋码序列号
func (s *CompaniesService) DeleteSerial(companyName string, serialNumber string) error {
var serial models.Serial
err := database.DB.Where("serial_number = ? AND company_name = ?", serialNumber, companyName).First(&serial).Error
if err != nil {
return errors.New("序列号不存在或不属于该企业")
}
if err := database.DB.Delete(&serial).Error; err != nil {
return errors.New("删除序列号失败")
}
return nil
}
// Revoke 吊销企业(吊销所有企业赋码与员工赋码)
func (s *CompaniesService) Revoke(companyName string) error {
var company models.Company
if err := database.DB.Where("company_name = ?", companyName).First(&company).Error; err != nil {
return errors.New("企业不存在")
}
if err := database.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Model(&models.Serial{}).Where("company_name = ?", companyName).Update("is_active", false).Error; err != nil {
return err
}
if err := tx.Model(&models.EmployeeSerial{}).Where("company_name = ?", companyName).Update("is_active", false).Error; err != nil {
return err
}
if err := tx.Model(&company).Update("is_active", false).Error; err != nil {
return err
}
return nil
}); err != nil {
return errors.New("吊销企业失败")
}
return nil
}
// GetStats 获取企业统计(兼容 Node 返回结构)
func (s *CompaniesService) GetStats() (map[string]any, error) {
now := time.Now()
var companies []models.Company
if err := database.DB.Order("updated_at DESC").Find(&companies).Error; err != nil {
return nil, errors.New("查询企业统计失败")
}
var serials []models.Serial
if err := database.DB.Order("created_at DESC").Find(&serials).Error; err != nil {
return nil, errors.New("查询序列号统计失败")
}
companyCount := len(companies)
serialCount := len(serials)
activeCount := 0
for _, serial := range serials {
if serial.IsActive && (serial.ValidUntil == nil || serial.ValidUntil.After(now)) {
activeCount++
}
}
inactiveCount := serialCount - activeCount
monthlyItems := make([]map[string]any, 0)
for i := 11; i >= 0; i-- {
date := time.Date(now.Year(), now.Month()-time.Month(i), 1, 0, 0, 0, 0, time.Local)
monthStr := date.Format("2006-01")
monthSerialCount := 0
companySet := map[string]bool{}
for _, serial := range serials {
if serial.CreatedAt.Year() == date.Year() && serial.CreatedAt.Month() == date.Month() {
monthSerialCount++
companySet[serial.CompanyName] = true
}
}
if monthSerialCount > 0 {
monthlyItems = append(monthlyItems, map[string]any{
"month": monthStr,
"company_count": len(companySet),
"serial_count": monthSerialCount,
})
}
}
recentCompanies := make([]map[string]any, 0)
for i, company := range companies {
if i >= 10 {
break
}
recentCompanies = append(recentCompanies, map[string]any{
"companyName": company.CompanyName,
"lastCreated": company.UpdatedAt,
"status": map[bool]string{true: "active", false: "disabled"}[company.IsActive],
})
}
recentSerials := make([]map[string]any, 0)
for i, serial := range serials {
if i >= 10 {
break
}
recentSerials = append(recentSerials, map[string]any{
"serialNumber": serial.SerialNumber,
"companyName": serial.CompanyName,
"isActive": serial.IsActive,
"createdAt": serial.CreatedAt,
})
}
return map[string]any{
"overview": map[string]any{
"totalCompanies": companyCount,
"totalSerials": serialCount,
"activeSerials": activeCount,
"inactiveSerials": inactiveCount,
},
"monthlyStats": monthlyItems,
"recentCompanies": recentCompanies,
"recentSerials": recentSerials,
}, nil
}
// GetStatsOverview 获取企业统计概览
func (s *CompaniesService) GetStatsOverview() (*models.CompanyStatsOverviewDTO, error) {
stats := &models.CompanyStatsOverviewDTO{}