Compare commits

...

2 Commits

Author SHA1 Message Date
Frudrax Cheng f80ab4a8ce fix: avoid company writes for employee serials 2026-06-06 14:07:17 +08:00
Frudrax Cheng a9aa4a1318 feat: update project order types 2026-06-06 13:58:57 +08:00
8 changed files with 46 additions and 35 deletions
+1 -1
View File
@@ -309,7 +309,7 @@ go run github.com/swaggo/swag/cmd/swag@v1.16.6 init -g main.go
| DELETE | `/api/project-orders/:serialNumber` | 删除项目工单 | 是 | 管理员 | | DELETE | `/api/project-orders/:serialNumber` | 删除项目工单 | 是 | 管理员 |
**项目工单特点**: **项目工单特点**:
- 用于现场勘查、现场实施等项目任务 - 用于项目勘察、工程实施、定期维保、商务合作等项目任务
- 工单号格式: `zjbf-xm-YYMMDDNN` - 工单号格式: `zjbf-xm-YYMMDDNN`
- 现场图片最多 18 张 - 现场图片最多 18 张
- 仅需要工程师签名,无客户签字环节 - 仅需要工程师签名,无客户签字环节
+2
View File
@@ -2352,6 +2352,7 @@ const docTemplate = `{
"survey", "survey",
"implementation", "implementation",
"maintenance", "maintenance",
"business",
"other" "other"
] ]
}, },
@@ -2743,6 +2744,7 @@ const docTemplate = `{
"survey", "survey",
"implementation", "implementation",
"maintenance", "maintenance",
"business",
"other" "other"
] ]
}, },
+2
View File
@@ -2346,6 +2346,7 @@
"survey", "survey",
"implementation", "implementation",
"maintenance", "maintenance",
"business",
"other" "other"
] ]
}, },
@@ -2737,6 +2738,7 @@
"survey", "survey",
"implementation", "implementation",
"maintenance", "maintenance",
"business",
"other" "other"
] ]
}, },
+2
View File
@@ -80,6 +80,7 @@ definitions:
- survey - survey
- implementation - implementation
- maintenance - maintenance
- business
- other - other
type: string type: string
siteDescription: siteDescription:
@@ -348,6 +349,7 @@ definitions:
- survey - survey
- implementation - implementation
- maintenance - maintenance
- business
- other - other
type: string type: string
siteDescription: siteDescription:
+2 -2
View File
@@ -401,7 +401,7 @@ type CreateProjectOrderDTO struct {
CompanyAddress string `json:"companyAddress" validate:"required"` CompanyAddress string `json:"companyAddress" validate:"required"`
ContactName string `json:"contactName" validate:"required"` ContactName string `json:"contactName" validate:"required"`
ContactPhone string `json:"contactPhone" validate:"required,len=11"` ContactPhone string `json:"contactPhone" validate:"required,len=11"`
ProjectType string `json:"projectType" validate:"required,oneof=survey implementation maintenance other"` ProjectType string `json:"projectType" validate:"required,oneof=survey implementation maintenance business other"`
SiteDescription string `json:"siteDescription" validate:"required"` SiteDescription string `json:"siteDescription" validate:"required"`
TechnicianID *uint `json:"technicianId,omitempty"` TechnicianID *uint `json:"technicianId,omitempty"`
} }
@@ -411,7 +411,7 @@ type UpdateProjectOrderDTO struct {
CompanyAddress string `json:"companyAddress,omitempty"` CompanyAddress string `json:"companyAddress,omitempty"`
ContactName string `json:"contactName,omitempty"` ContactName string `json:"contactName,omitempty"`
ContactPhone string `json:"contactPhone,omitempty" validate:"omitempty,len=11"` ContactPhone string `json:"contactPhone,omitempty" validate:"omitempty,len=11"`
ProjectType string `json:"projectType,omitempty" validate:"omitempty,oneof=survey implementation maintenance other"` ProjectType string `json:"projectType,omitempty" validate:"omitempty,oneof=survey implementation maintenance business other"`
SiteDescription string `json:"siteDescription,omitempty"` SiteDescription string `json:"siteDescription,omitempty"`
CompletionNote string `json:"completionNote,omitempty"` CompletionNote string `json:"completionNote,omitempty"`
TechnicianID *uint `json:"technicianId,omitempty"` TechnicianID *uint `json:"technicianId,omitempty"`
+1 -26
View File
@@ -79,20 +79,6 @@ func (s *EmployeeSerialsService) generateWithDB(
) ([]models.EmployeeSerial, error) { ) ([]models.EmployeeSerial, error) {
var serials []models.EmployeeSerial var serials []models.EmployeeSerial
// 检查公司是否存在,不存在则创建
var company models.Company
result := db.Where("company_name = ?", companyName).First(&company)
if result.Error != nil {
company = models.Company{
CompanyName: companyName,
IsActive: true,
}
result = db.Create(&company)
if result.Error != nil {
return nil, fmt.Errorf("创建公司失败: %w", result.Error)
}
}
// 生成序列号前缀 // 生成序列号前缀
if serialPrefix == "" { if serialPrefix == "" {
serialPrefix = fmt.Sprintf("EMP%d", time.Now().Year()%100) serialPrefix = fmt.Sprintf("EMP%d", time.Now().Year()%100)
@@ -136,7 +122,7 @@ func (s *EmployeeSerialsService) generateWithDB(
} }
// 保存到数据库 // 保存到数据库
result = db.Create(&serials) result := db.Create(&serials)
if result.Error != nil { if result.Error != nil {
return nil, fmt.Errorf("保存员工序列号失败: %w", result.Error) return nil, fmt.Errorf("保存员工序列号失败: %w", result.Error)
} }
@@ -197,17 +183,6 @@ func (s *EmployeeSerialsService) Update(serialNumber string, updateData models.U
} }
if updateData.CompanyName != "" { if updateData.CompanyName != "" {
// 检查公司是否存在
var company models.Company
companyResult := database.DB.Where("company_name = ?", updateData.CompanyName).First(&company)
if companyResult.Error != nil {
company = models.Company{
CompanyName: updateData.CompanyName,
IsActive: true,
}
database.DB.Create(&company)
}
serial.CompanyName = updateData.CompanyName serial.CompanyName = updateData.CompanyName
} }
+8 -6
View File
@@ -248,7 +248,7 @@ func TestEmployeeSerialsService_Generate_Success(t *testing.T) {
database.DB.Unscoped().Delete(&user) database.DB.Unscoped().Delete(&user)
} }
func TestEmployeeSerialsService_Generate_CreateNewCompany(t *testing.T) { func TestEmployeeSerialsService_Generate_DoesNotCreateManagedCompany(t *testing.T) {
var user models.User var user models.User
password, _ := bcrypt.GenerateFromPassword([]byte("password123"), bcrypt.DefaultCost) password, _ := bcrypt.GenerateFromPassword([]byte("password123"), bcrypt.DefaultCost)
user = models.User{ user = models.User{
@@ -266,11 +266,9 @@ func TestEmployeeSerialsService_Generate_CreateNewCompany(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, serials, 3) assert.Len(t, serials, 3)
var company models.Company var count int64
result := database.DB.Where("company_name = ?", "NewEmpCompany").First(&company) database.DB.Model(&models.Company{}).Where("company_name = ?", "NewEmpCompany").Count(&count)
assert.NoError(t, result.Error) assert.Equal(t, int64(0), count)
assert.Equal(t, "NewEmpCompany", company.CompanyName)
assert.True(t, company.IsActive)
for _, serial := range serials { for _, serial := range serials {
database.DB.Unscoped().Delete(&serial) database.DB.Unscoped().Delete(&serial)
@@ -419,6 +417,10 @@ func TestEmployeeSerialsService_Update_Success(t *testing.T) {
assert.Equal(t, "新名字", result.EmployeeName) assert.Equal(t, "新名字", result.EmployeeName)
assert.False(t, result.IsActive) assert.False(t, result.IsActive)
var count int64
database.DB.Model(&models.Company{}).Where("company_name = ?", "UpdatedEmpCompany").Count(&count)
assert.Equal(t, int64(0), count)
for _, serial := range serials { for _, serial := range serials {
database.DB.Unscoped().Delete(&serial) database.DB.Unscoped().Delete(&serial)
} }
+28
View File
@@ -33,6 +33,34 @@ func TestUsersService_Create_Success(t *testing.T) {
database.DB.Unscoped().Where("employee_name = ?", "新技术员").Delete(&models.EmployeeSerial{}) database.DB.Unscoped().Where("employee_name = ?", "新技术员").Delete(&models.EmployeeSerial{})
} }
func TestUsersService_Create_DoesNotTouchCompanyTable(t *testing.T) {
database.DB.Unscoped().Where("company_name = ?", "内部员工").Delete(&models.Company{})
company := models.Company{CompanyName: "内部员工", IsActive: true}
assert.NoError(t, database.DB.Create(&company).Error)
assert.NoError(t, database.DB.Delete(&company).Error)
svc := UsersService{}
dto, err := svc.Create(models.CreateUserDTO{
Password: "password123",
Name: "软删公司员工",
Phone: "13800000008",
EmployeeNo: "users_create_restore_company",
Position: "硬件工程师",
Role: "hardware_engineer",
})
assert.NoError(t, err)
assert.NotNil(t, dto)
assert.Len(t, dto.EmployeeSerials, 1)
var count int64
database.DB.Model(&models.Company{}).Where("company_name = ?", "内部员工").Count(&count)
assert.Equal(t, int64(0), count)
database.DB.Unscoped().Where("username = ?", "users_create_restore_company").Delete(&models.User{})
database.DB.Unscoped().Where("employee_name = ?", "软删公司员工").Delete(&models.EmployeeSerial{})
database.DB.Unscoped().Where("company_name = ?", "内部员工").Delete(&models.Company{})
}
func TestUsersService_Create_BlocksEmployeeRole(t *testing.T) { func TestUsersService_Create_BlocksEmployeeRole(t *testing.T) {
svc := UsersService{} svc := UsersService{}
_, err := svc.Create(models.CreateUserDTO{ _, err := svc.Create(models.CreateUserDTO{