13 KiB
13 KiB
AGENTS.md
This file provides guidance for agentic coding agents working on this repository.
Build/Lint/Test Commands
Building
make build # Build executable (trace-backend.exe)
make run # Run development server
go build -o bin/backend.exe . # Build to custom location
Testing
make test # Run all integration tests (./tests/...)
go test -v ./services/... # Run service layer unit tests
go test -v ./tests/... # Run integration tests
go test -v -run TestAuthService_ValidateUser_Success ./services/... # Single test
go test -v ./services/... -run TestEmployeeSerialsService # Run test prefix
make test-coverage # Generate coverage report
Code Quality
make lint # Run golangci-lint (configured in .golangci.yml)
make fmt # Format code with gofmt
make imports # Format imports with goimports
make quality # fmt + imports + lint (full check)
golangci-lint run ./... # Direct lint check
Swagger Documentation
make swagger # Generate swagger docs to docs/ directory
swag init -g main.go # Alternative command
Code Style Guidelines
Project Structure
backend-go/
├── config/ # Configuration management
│ └── config.go # Config loading (.env, config.yaml, env vars)
├── controllers/ # HTTP request handlers
│ ├── aftersales_controller.go # Aftersales orders: create, query, submit, confirm, qrcode
│ ├── auth_controller.go # Auth: login, profile, password change
│ ├── dashboard_controller.go # Dashboard work-order statistics
│ ├── employees_controller.go # Employee permission codes: generate, query, update, revoke, qrcode
│ ├── helper.go # Helper functions (GetCurrentUser, BindJSON, Response)
│ ├── product_traces_controller.go # Product traceability
│ ├── project_orders_controller.go # Project work orders
│ └── users_controller.go # Employee master data / backend account management
├── database/ # Database connection and migrations
│ └── database.go # GORM init, AutoMigrate
├── docs/ # Swagger documentation (auto-generated)
├── logger/ # Structured logging
│ └── logger.go # Zap logger wrapper
├── middleware/ # Middleware
│ └── auth.go # JWT auth, Admin / Technician permission checks
├── models/ # Data models and DTOs
│ └── models.go # User, Company, EmployeeSerial, ProductTrace, AftersalesOrder, ProjectOrder and DTOs
├── routes/ # Route configuration
│ └── routes.go # API route registration
├── services/ # Business logic layer
│ ├── aftersales_service.go # Aftersales orders: create, list, update, submit, customer confirm, qrcode
│ ├── auth_service.go # Auth: validate user, generate token, password management
│ ├── dashboard_service.go # Dashboard work-order statistics
│ ├── employees_service.go # Employee permission codes: generate, query, update, revoke, qrcode
│ ├── product_traces_service.go # Product traceability
│ ├── project_orders_service.go # Project work orders
│ ├── aftersales_service_test.go # Aftersales unit tests
│ ├── services_test.go # Auth / employee permission-code unit tests
│ ├── users_service.go # Employee CRUD, role management, password reset (admin)
│ └── users_service_test.go # Employee/user account unit tests
├── tests/ # Integration tests
│ └── main_test.go # End-to-end tests
├── data/ # SQLite data directory
├── main.go # Application entry point
├── go.mod # Go dependencies
├── Makefile # Build tasks
└── .env.example # Environment variable example
Layer Responsibilities
- controllers/: Receive HTTP requests, validate params, call services, return responses
- services/: Business logic, data processing, database interaction, return results or errors
- models/: Data structure definitions, GORM models, API request/response DTOs
- middleware/: Authentication and authorization
- routes/: Route registration, connect controllers to router
API Surface (Current)
- Auth:
POST /api/auth/login,POST /api/auth/logout,GET /api/auth/profile,PUT /api/auth/profile,POST /api/auth/change-password - Dashboard:
GET /api/dashboard/stats - Employee Permission Codes:
POST /api/employee-serials/generate,POST /api/employee-serials/:serialNumber/qrcode,GET /api/employee-serials/:serialNumber/query,GET /api/employee-serials,PATCH /api/employee-serials/:serialNumber,PUT /api/employee-serials/:serialNumber,POST /api/employee-serials/:serialNumber/revoke,DELETE /api/employee-serials/:serialNumber - Product Traces:
GET /api/product-traces/:serialNumber/query,POST /api/product-traces,GET /api/product-traces,GET /api/product-traces/:serialNumber,PATCH /api/product-traces/:serialNumber,POST /api/product-traces/:serialNumber/qrcode,POST /api/product-traces/:serialNumber/wechat-qrcode,POST /api/product-traces/:serialNumber/revoke,DELETE /api/product-traces/:serialNumber - Aftersales (公开):
GET /api/aftersales/:serialNumber/query,POST /api/aftersales/:serialNumber/confirm - Aftersales (工单角色+管理员):
GET /api/aftersales,GET /api/aftersales/:serialNumber,PATCH /api/aftersales/:serialNumber,POST /api/aftersales/:serialNumber/qrcode,POST /api/aftersales/:serialNumber/submit - Aftersales (仅管理员):
POST /api/aftersales,POST /api/aftersales/:serialNumber/reassign,POST /api/aftersales/:serialNumber/force-close,DELETE /api/aftersales/:serialNumber - Project Orders (公开):
GET /api/project-orders/:serialNumber/query,POST /api/project-orders/:serialNumber/site-images,POST /api/project-orders/:serialNumber/complete - Project Orders (工单角色+管理员):
GET /api/project-orders,GET /api/project-orders/:serialNumber,PATCH /api/project-orders/:serialNumber,POST /api/project-orders/:serialNumber/qrcode,POST /api/project-orders/:serialNumber/submit - Project Orders (仅管理员):
POST /api/project-orders,POST /api/project-orders/:serialNumber/reassign,POST /api/project-orders/:serialNumber/force-close,DELETE /api/project-orders/:serialNumber - Users (仅管理员):
GET /api/users/assignable - Employees (仅管理员):
POST /api/employees,GET /api/employees,PATCH /api/employees/:id,POST /api/employees/:id/reset-password,DELETE /api/employees/:id
Roles and permissions
adminis the system administrator role and has full backend access.- Permission management may create/edit only four equal work-order roles:
software_engineer,hardware_engineer,business_manager,project_manager. - The four work-order roles can log in only to process aftersales/project orders assigned to themselves.
- The four work-order roles must not access dashboard, permission management, product traces, assignable user lists, creation/deletion/reassign/force-close endpoints, or other admin-only resources.
technicianis legacy-compatible and may keep work-order access, but must not be offered as a new role.employeeis legacy/no backend login access and must not be offered as a new role.- Creating an employee through
/api/employeescreates employee master data and automatically generates one employee permission code bound byemployeeId. - Creating managed work-order roles requires an initial password; creating
adminoremployeethrough permission management is forbidden.
Business Boundaries
- Enterprise/company-code management was removed. Do not reintroduce
/api/companies,/api/serials,CompaniesService,SerialsService, or a company-management UI. - The
Companymodel remains only as internal compatibility for employee permission-code ownership; it is not an exposed management feature. - Aftersales/project order
companyNameis customer information stored on the order only; creating or updating a work order must not create a managed-company feature.
Import Organization
Standard imports followed by third-party imports, then project imports (sorted alphabetically):
import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
"git.beifan.cn/trace-system/backend-go/config"
"git.beifan.cn/trace-system/backend-go/models"
)
Naming Conventions
- Controllers:
AuthController,DashboardController,EmployeeSerialsController,ProductTracesController,ProjectOrdersController - Services:
AuthService,DashboardService,EmployeeSerialsService,ProductTracesService,ProjectOrdersService - Models:
User,Company,EmployeeSerial,ProductTrace,AftersalesOrder,ProjectOrder(use PascalCase for exported structs) - DTOs:
LoginDTO,ChangePasswordDTO,UpdateProfileDTO(DTO suffix) - Functions:
ValidateUser,Generate,Query(PascalCase for exported) - Variables: camelCase for local variables, PascalCase for exported
Struct Tags
- JSON tags: lowercase camelCase,
json:"username",json:"accessToken" - GORM tags: PascalCase,
gorm:"primaryKey",gorm:"uniqueIndex;size:255" - Validate tags:
validate:"required,min=6",validate:"omitempty,email" - Omit empty:
json:"omitempty"for optional fields - Ignore in JSON:
json:"-"for sensitive fields (Password, DeletedAt)
Error Handling
Services: Return errors, don't handle them directly:
func (s *AuthService) ValidateUser(username, password string) (models.User, error) {
var user models.User
err := database.DB.Where("username = ?", username).First(&user).Error
if err != nil {
return models.User{}, errors.New("用户名或密码不正确")
}
return user, nil
}
Controllers: Use helper functions for consistent responses:
func (c *AuthController) Login(ctx *gin.Context) {
var loginData models.LoginDTO
if !BindJSON(ctx, &loginData) {
return
}
user, err := c.authService.ValidateUser(loginData.Username, loginData.Password)
if err != nil {
ErrorResponse(ctx, http.StatusUnauthorized, err.Error())
return
}
SuccessResponse(ctx, "登录成功", gin.H{"user": user})
}
- Use
ErrorResponsefor API errors so messages are user-friendly and consistent. - Do not leak raw DB/stack errors to clients; log internal details and return safe messages.
Response Format
Success response:
{
"message": "操作成功",
"data": { ... }
}
Some endpoints also return Node-compatible top-level keys (e.g. serial, serials, pagination) to preserve frontend compatibility.
Error response:
{
"message": "错误描述",
"error": "详细错误信息"
}
Logging
Use structured logger from logger package:
logger.Info("用户登录", logger.String("username", user.Username))
logger.Error("数据库错误", logger.Err(err))
logger.Fatal("致命错误", logger.Err(err))
Database Operations
- Use
database.DBfor GORM operations - Always check for errors:
if err != nil { ... } - Use Unscoped for permanent deletion:
database.DB.Unscoped().Delete(...) - Test cleanup:
database.DB.Unscoped().Where("1 = 1").Delete(&models.User{}) - During
AutoMigrate(), default admin is seeded only when user table is empty
Testing
- Use
testify/assertfor assertions - Use
TestMainfor setup/cleanup (init DB, create test data, cleanup on exit) - Test naming:
Test{Service}_{Method}_{Scenario} - Clean up test data after tests: delete all records
- Use bcrypt for password hashing in tests
Swagger Annotations
Add Swagger comments to controller methods:
// @Summary Brief description
// @Description Detailed description
// @Tags Category
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param name body models.DTO true "Description"
// @Success 200 {object} models.ResponseDTO
// @Failure 400 {object} models.ErrorResponse
// @Router /path [method]
After modifying Swagger annotations, run make swagger.
Configuration
- Load with
config.LoadConfig() - Access with
config.GetAppConfig() - Environment variables must use
APP_prefix (e.g.APP_SERVER_PORT,APP_DATABASE_DRIVER,APP_DATABASE_SQLITE_PATH,APP_JWT_SECRET) - .env file for local development (not committed)
Middleware
- JWTAuthMiddleware: Validates JWT tokens, sets user in context
- AdminMiddleware: Checks if user has admin role
- TechnicianMiddleware: Allows admin, the four managed work-order roles, and legacy
technician(used for work-order processing endpoints) - Access current user:
user, ok := GetCurrentUser(ctx)
Git Hooks
Run make quality before committing to ensure code passes all checks.