Java全栈项目 - 汽车维修服务管理平台

打印 上一主题 下一主题

主题 774|帖子 774|积分 2322

项目介绍

汽车维修服务管理平台是一个面向汽修店的综合业务管理系统。该平台帮助汽修店实现维修预约、工单管理、库存管理、客户管理等核心业务流程的数字化,提拔运营服从。
技术架构

后端技术栈



  • Spring Boot 2.x:应用开辟框架
  • Spring Security:认证和权限控制
  • MyBatis Plus:ORM框架
  • MySQL:关系型数据库
  • Redis:缓存数据库
  • JWT:用户会话管理
  • Maven:项目构建工具
前端技术栈



  • Vue.js:前端框架
  • Element UI:组件库
  • Axios:HTTP 请求
  • Vuex:状态管理
  • Vue Router:路由管理
核心功能模块

1. 维修预约管理



  • 在线预约
  • 预约时间段管理
  • 预约状态跟踪
  • 短信关照提示
2. 工单管理



  • 维修工单创建
  • 维修进度跟踪
  • 维修项目管理
  • 维修费用盘算
  • 工单状态变动
3. 库存管理



  • 配件入库登记
  • 库存预警提示
  • 配件使用记录
  • 库存盘货统计
4. 客户管理



  • 客户信息管理
  • 车辆信息管理
  • 维修记录查询
  • 会员积分管理
5. 员工管理



  • 员工信息管理
  • 工种分类管理
  • 工作量统计
  • 绩效考核
6. 财务管理



  • 收支明细记录
  • 营收报表统计
  • 成本分析
  • 利润核算
系统特点


  • 全流程数字化


  • 从预约到结算的完整业务闭环
  • 减少人工操作环节
  • 提高工作服从

  • 数据可视化


  • 直观的数据展示
  • 多维度统计分析
  • 辅助谋划决议

  • 用户体验


  • 简洁清楚的界面设计
  • 便捷的操作流程
  • 完满的提示信息

  • 安全可靠


  • 严酷的权限控制
  • 敏感数据加密
  • 操作日志记录
项目亮点


  • 微服务架构


  • 模块解耦,独立部署
  • 服务高可用
  • 便于扩展维护

  • 性能优化


  • Redis缓存机制
  • SQL语句优化
  • 前端资源压缩

  • 工单智能派单


  • 考虑技师专长
  • 工作量均衡分配
  • 提高维修服从

  • 数据分析功能


  • 客户消费分析
  • 配件使用分析
  • 维修项目分析
  • 营收趋势分析
项目收获


  • 掌握了完整的Java全栈开辟技术栈
  • 深入理解了微服务架构设计思想
  • 提拔了项目开辟和管理能力
  • 积聚了丰富的业务领域经验
项目展望


  • 引入人工智能技术,实现故障智能诊断
  • 开辟移动端应用,提供更便捷的服务
  • 对接物联网设备,实现智能化管理
  • 扩展更多增值服务功能
总结

本项目采取主流的Java全栈技术,实现了汽修行业核心业务的信息化管理。通过该项目的开辟,不仅提拔了技术能力,也深入理解了业务需求分析和系统架构设计的重要性。项目具有较强的实用价值,为汽修企业提供了完满的管理解决方案。
维修预约管理模块的核心代码实现

1. 数据库设计

  1. -- 预约表
  2. CREATE TABLE appointment (
  3.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  4.     customer_id BIGINT NOT NULL COMMENT '客户ID',
  5.     vehicle_id BIGINT NOT NULL COMMENT '车辆ID',
  6.     service_type VARCHAR(50) NOT NULL COMMENT '服务类型',
  7.     appointment_time DATETIME NOT NULL COMMENT '预约时间',
  8.     time_slot VARCHAR(20) NOT NULL COMMENT '预约时段',
  9.     status VARCHAR(20) NOT NULL COMMENT '预约状态',
  10.     description TEXT COMMENT '维修描述',
  11.     contact_name VARCHAR(50) NOT NULL COMMENT '联系人',
  12.     contact_phone VARCHAR(20) NOT NULL COMMENT '联系电话',
  13.     photos TEXT COMMENT '车辆照片URLs',
  14.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  15.     updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  16.     FOREIGN KEY (customer_id) REFERENCES customer(id),
  17.     FOREIGN KEY (vehicle_id) REFERENCES vehicle(id)
  18. );
  19. -- 预约时段配置表
  20. CREATE TABLE time_slot_config (
  21.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  22.     slot_time VARCHAR(20) NOT NULL COMMENT '时间段',
  23.     max_capacity INT NOT NULL COMMENT '最大预约数',
  24.     current_capacity INT NOT NULL DEFAULT 0 COMMENT '当前预约数',
  25.     is_available BOOLEAN NOT NULL DEFAULT true COMMENT '是否可用',
  26.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  27.     updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  28. );
  29. -- 预约状态变更记录表
  30. CREATE TABLE appointment_status_log (
  31.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  32.     appointment_id BIGINT NOT NULL,
  33.     old_status VARCHAR(20) COMMENT '原状态',
  34.     new_status VARCHAR(20) NOT NULL COMMENT '新状态',
  35.     operator_id BIGINT NOT NULL COMMENT '操作人',
  36.     remark TEXT COMMENT '备注',
  37.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  38.     FOREIGN KEY (appointment_id) REFERENCES appointment(id)
  39. );
复制代码
2. 实体类设计

  1. @Data
  2. @Entity
  3. @Table(name = "appointment")
  4. public class Appointment {
  5.     @Id
  6.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  7.     private Long id;
  8.    
  9.     private Long customerId;
  10.     private Long vehicleId;
  11.     private String serviceType;
  12.     private LocalDateTime appointmentTime;
  13.     private String timeSlot;
  14.    
  15.     @Enumerated(EnumType.STRING)
  16.     private AppointmentStatus status;
  17.    
  18.     private String description;
  19.     private String contactName;
  20.     private String contactPhone;
  21.     private String photos;
  22.     private LocalDateTime createdTime;
  23.     private LocalDateTime updatedTime;
  24. }
  25. @Data
  26. @Entity
  27. @Table(name = "time_slot_config")
  28. public class TimeSlotConfig {
  29.     @Id
  30.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  31.     private Long id;
  32.    
  33.     private String slotTime;
  34.     private Integer maxCapacity;
  35.     private Integer currentCapacity;
  36.     private Boolean isAvailable;
  37.     private LocalDateTime createdTime;
  38.     private LocalDateTime updatedTime;
  39. }
复制代码
3. 枚举定义

  1. public enum AppointmentStatus {
  2.     PENDING("待确认"),
  3.     CONFIRMED("已确认"),
  4.     WAITING("待到店"),
  5.     ARRIVED("已到店"),
  6.     COMPLETED("已完成"),
  7.     CANCELLED("已取消");
  8.    
  9.     private String description;
  10.    
  11.     AppointmentStatus(String description) {
  12.         this.description = description;
  13.     }
  14. }
  15. public enum ServiceType {
  16.     REGULAR_MAINTENANCE("常规保养"),
  17.     REPAIR("故障维修"),
  18.     INSPECTION("年检服务"),
  19.     CUSTOM("其他服务");
  20.    
  21.     private String description;
  22.    
  23.     ServiceType(String description) {
  24.         this.description = description;
  25.     }
  26. }
复制代码
4. DTO对象

  1. @Data
  2. public class AppointmentDTO {
  3.     private Long customerId;
  4.     private Long vehicleId;
  5.     private String serviceType;
  6.     private String appointmentDate;
  7.     private String timeSlot;
  8.     private String description;
  9.     private String contactName;
  10.     private String contactPhone;
  11.     private List<String> photos;
  12. }
  13. @Data
  14. public class TimeSlotDTO {
  15.     private String date;
  16.     private List<TimeSlotInfo> availableSlots;
  17.    
  18.     @Data
  19.     public static class TimeSlotInfo {
  20.         private String slotTime;
  21.         private Integer availableCapacity;
  22.         private Boolean isAvailable;
  23.     }
  24. }
复制代码
5. Service层实现

  1. @Service
  2. @Transactional
  3. public class AppointmentService {
  4.    
  5.     @Autowired
  6.     private AppointmentRepository appointmentRepository;
  7.    
  8.     @Autowired
  9.     private TimeSlotConfigRepository timeSlotConfigRepository;
  10.    
  11.     @Autowired
  12.     private NotificationService notificationService;
  13.    
  14.     @Autowired
  15.     private RedisTemplate<String, Object> redisTemplate;
  16.    
  17.     public AppointmentResponse createAppointment(AppointmentDTO dto) {
  18.         // 1. 验证时间段是否可预约
  19.         validateTimeSlot(dto.getAppointmentDate(), dto.getTimeSlot());
  20.         
  21.         // 2. 创建预约记录
  22.         Appointment appointment = new Appointment();
  23.         BeanUtils.copyProperties(dto, appointment);
  24.         appointment.setStatus(AppointmentStatus.PENDING);
  25.         
  26.         // 3. 更新时间段容量
  27.         updateTimeSlotCapacity(dto.getAppointmentDate(), dto.getTimeSlot());
  28.         
  29.         // 4. 保存预约信息
  30.         appointment = appointmentRepository.save(appointment);
  31.         
  32.         // 5. 发送通知
  33.         notificationService.sendAppointmentNotification(appointment);
  34.         
  35.         return buildResponse(appointment);
  36.     }
  37.    
  38.     @Cacheable(value = "timeSlots", key = "#date")
  39.     public List<TimeSlotDTO> getAvailableTimeSlots(String date) {
  40.         List<TimeSlotConfig> configs = timeSlotConfigRepository.findByDateAndIsAvailable(date, true);
  41.         return convertToDTO(configs);
  42.     }
  43.    
  44.     public void updateAppointmentStatus(Long appointmentId, AppointmentStatus newStatus) {
  45.         Appointment appointment = appointmentRepository.findById(appointmentId)
  46.             .orElseThrow(() -> new BusinessException("预约不存在"));
  47.             
  48.         // 记录状态变更
  49.         logStatusChange(appointment, newStatus);
  50.         
  51.         // 更新状态
  52.         appointment.setStatus(newStatus);
  53.         appointmentRepository.save(appointment);
  54.         
  55.         // 发送状态变更通知
  56.         notificationService.sendStatusChangeNotification(appointment);
  57.     }
  58.    
  59.     private void validateTimeSlot(String date, String timeSlot) {
  60.         String cacheKey = "timeSlot:" + date + ":" + timeSlot;
  61.         TimeSlotConfig config = (TimeSlotConfig) redisTemplate.opsForValue().get(cacheKey);
  62.         
  63.         if (config == null) {
  64.             config = timeSlotConfigRepository.findByDateAndSlotTime(date, timeSlot)
  65.                 .orElseThrow(() -> new BusinessException("无效的时间段"));
  66.         }
  67.         
  68.         if (!config.getIsAvailable() || config.getCurrentCapacity() >= config.getMaxCapacity()) {
  69.             throw new BusinessException("该时间段已约满");
  70.         }
  71.     }
  72.    
  73.     private void updateTimeSlotCapacity(String date, String timeSlot) {
  74.         timeSlotConfigRepository.incrementCurrentCapacity(date, timeSlot);
  75.         // 更新缓存
  76.         String cacheKey = "timeSlot:" + date + ":" + timeSlot;
  77.         redisTemplate.delete(cacheKey);
  78.     }
  79. }
复制代码
6. Controller层实现

  1. @RestController
  2. @RequestMapping("/api/appointments")
  3. public class AppointmentController {
  4.    
  5.     @Autowired
  6.     private AppointmentService appointmentService;
  7.    
  8.     @PostMapping
  9.     public Result<AppointmentResponse> createAppointment(@RequestBody @Valid AppointmentDTO dto) {
  10.         try {
  11.             AppointmentResponse response = appointmentService.createAppointment(dto);
  12.             return Result.success(response);
  13.         } catch (BusinessException e) {
  14.             return Result.failure(e.getMessage());
  15.         }
  16.     }
  17.    
  18.     @GetMapping("/time-slots")
  19.     public Result<List<TimeSlotDTO>> getAvailableTimeSlots(
  20.             @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") String date) {
  21.         List<TimeSlotDTO> slots = appointmentService.getAvailableTimeSlots(date);
  22.         return Result.success(slots);
  23.     }
  24.    
  25.     @PutMapping("/{id}/status")
  26.     public Result<Void> updateStatus(
  27.             @PathVariable Long id,
  28.             @RequestParam AppointmentStatus status) {
  29.         appointmentService.updateAppointmentStatus(id, status);
  30.         return Result.success();
  31.     }
  32.    
  33.     @GetMapping("/{id}")
  34.     public Result<AppointmentResponse> getAppointment(@PathVariable Long id) {
  35.         AppointmentResponse appointment = appointmentService.getAppointmentById(id);
  36.         return Result.success(appointment);
  37.     }
  38. }
复制代码
7. 关照服务实现

  1. @Service
  2. public class NotificationService {
  3.    
  4.     @Autowired
  5.     private SMSProvider smsProvider;
  6.    
  7.     @Autowired
  8.     private NotificationTemplateService templateService;
  9.    
  10.     @Async
  11.     public void sendAppointmentNotification(Appointment appointment) {
  12.         try {
  13.             String template = templateService.getTemplate("APPOINTMENT_CREATED");
  14.             String content = buildNotificationContent(template, appointment);
  15.             
  16.             SMSRequest request = SMSRequest.builder()
  17.                 .mobile(appointment.getContactPhone())
  18.                 .content(content)
  19.                 .build();
  20.                
  21.             smsProvider.send(request);
  22.         } catch (Exception e) {
  23.             log.error("发送预约通知失败", e);
  24.             // 添加重试机制
  25.             retryNotification(appointment);
  26.         }
  27.     }
  28.    
  29.     @Async
  30.     public void sendStatusChangeNotification(Appointment appointment) {
  31.         String template = templateService.getTemplate("STATUS_CHANGED");
  32.         String content = buildNotificationContent(template, appointment);
  33.         
  34.         SMSRequest request = SMSRequest.builder()
  35.             .mobile(appointment.getContactPhone())
  36.             .content(content)
  37.             .build();
  38.             
  39.         smsProvider.send(request);
  40.     }
  41.    
  42.     private void retryNotification(Appointment appointment) {
  43.         // 使用重试策略(如:exponential backoff)
  44.     }
  45. }
复制代码
8. 缓存配置

  1. @Configuration
  2. @EnableCaching
  3. public class CacheConfig {
  4.    
  5.     @Bean
  6.     public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
  7.         RedisTemplate<String, Object> template = new RedisTemplate<>();
  8.         template.setConnectionFactory(factory);
  9.         
  10.         // 设置key的序列化方式
  11.         template.setKeySerializer(new StringRedisSerializer());
  12.         
  13.         // 设置value的序列化方式
  14.         Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
  15.         template.setValueSerializer(serializer);
  16.         
  17.         return template;
  18.     }
  19.    
  20.     @Bean
  21.     public CacheManager cacheManager(RedisConnectionFactory factory) {
  22.         RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
  23.             .entryTtl(Duration.ofHours(1))
  24.             .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
  25.             .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
  26.             
  27.         return RedisCacheManager.builder(factory)
  28.             .cacheDefaults(config)
  29.             .build();
  30.     }
  31. }
复制代码
9. 非常处理

  1. @RestControllerAdvice
  2. public class GlobalExceptionHandler {
  3.    
  4.     @ExceptionHandler(BusinessException.class)
  5.     public Result<Void> handleBusinessException(BusinessException e) {
  6.         return Result.failure(e.getMessage());
  7.     }
  8.    
  9.     @ExceptionHandler(MethodArgumentNotValidException.class)
  10.     public Result<Void> handleValidationException(MethodArgumentNotValidException e) {
  11.         String message = e.getBindingResult().getFieldErrors().stream()
  12.             .map(FieldError::getDefaultMessage)
  13.             .collect(Collectors.joining(", "));
  14.         return Result.failure(message);
  15.     }
  16.    
  17.     @ExceptionHandler(Exception.class)
  18.     public Result<Void> handleException(Exception e) {
  19.         log.error("系统异常", e);
  20.         return Result.failure("系统繁忙,请稍后重试");
  21.     }
  22. }
复制代码
这些代码实现了预约管理的核心功能,包罗:

  • 预约创建和管理
  • 时间段容量控制
  • 状态跟踪和变动
  • 短信关照
  • 缓存优化
  • 非常处理
关键特点:


  • 使用Redis缓存热点数据(时间段信息)
  • 异步处理关照发送
  • 完满的非常处理机制
  • 状态变动日志记录
  • 预约容量控制
工单管理模块的核心代码实现

1. 数据库设计

  1. -- 工单主表
  2. CREATE TABLE work_order (
  3.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  4.     order_no VARCHAR(32) UNIQUE NOT NULL COMMENT '工单编号',
  5.     appointment_id BIGINT COMMENT '关联预约ID',
  6.     customer_id BIGINT NOT NULL COMMENT '客户ID',
  7.     vehicle_id BIGINT NOT NULL COMMENT '车辆ID',
  8.     technician_id BIGINT COMMENT '主责技师ID',
  9.     status VARCHAR(20) NOT NULL COMMENT '工单状态',
  10.     estimated_completion_time DATETIME COMMENT '预计完工时间',
  11.     actual_completion_time DATETIME COMMENT '实际完工时间',
  12.     total_amount DECIMAL(10,2) DEFAULT 0 COMMENT '总金额',
  13.     labor_cost DECIMAL(10,2) DEFAULT 0 COMMENT '工时费',
  14.     parts_cost DECIMAL(10,2) DEFAULT 0 COMMENT '配件费',
  15.     description TEXT COMMENT '维修描述',
  16.     diagnosis_result TEXT COMMENT '检查结果',
  17.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  18.     updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  19. );
  20. -- 工单项目明细表
  21. CREATE TABLE work_order_item (
  22.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  23.     work_order_id BIGINT NOT NULL COMMENT '工单ID',
  24.     service_item_id BIGINT NOT NULL COMMENT '服务项目ID',
  25.     technician_id BIGINT COMMENT '技师ID',
  26.     status VARCHAR(20) NOT NULL COMMENT '项目状态',
  27.     estimated_hours DECIMAL(4,1) COMMENT '预计工时',
  28.     actual_hours DECIMAL(4,1) COMMENT '实际工时',
  29.     amount DECIMAL(10,2) COMMENT '项目金额',
  30.     remark TEXT COMMENT '备注',
  31.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  32.     FOREIGN KEY (work_order_id) REFERENCES work_order(id)
  33. );
  34. -- 工单配件使用记录表
  35. CREATE TABLE work_order_part (
  36.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  37.     work_order_id BIGINT NOT NULL COMMENT '工单ID',
  38.     part_id BIGINT NOT NULL COMMENT '配件ID',
  39.     quantity INT NOT NULL COMMENT '使用数量',
  40.     unit_price DECIMAL(10,2) NOT NULL COMMENT '单价',
  41.     amount DECIMAL(10,2) NOT NULL COMMENT '金额',
  42.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  43.     FOREIGN KEY (work_order_id) REFERENCES work_order(id)
  44. );
  45. -- 工单进度记录表
  46. CREATE TABLE work_order_progress (
  47.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  48.     work_order_id BIGINT NOT NULL COMMENT '工单ID',
  49.     status VARCHAR(20) NOT NULL COMMENT '状态',
  50.     operator_id BIGINT NOT NULL COMMENT '操作人',
  51.     remark TEXT COMMENT '备注',
  52.     photos TEXT COMMENT '照片URLs',
  53.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  54.     FOREIGN KEY (work_order_id) REFERENCES work_order(id)
  55. );
复制代码
2. 实体类设计

  1. @Data
  2. @Entity
  3. @Table(name = "work_order")
  4. public class WorkOrder {
  5.     @Id
  6.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  7.     private Long id;
  8.    
  9.     private String orderNo;
  10.     private Long appointmentId;
  11.     private Long customerId;
  12.     private Long vehicleId;
  13.     private Long technicianId;
  14.    
  15.     @Enumerated(EnumType.STRING)
  16.     private WorkOrderStatus status;
  17.    
  18.     private LocalDateTime estimatedCompletionTime;
  19.     private LocalDateTime actualCompletionTime;
  20.     private BigDecimal totalAmount;
  21.     private BigDecimal laborCost;
  22.     private BigDecimal partsCost;
  23.     private String description;
  24.     private String diagnosisResult;
  25.    
  26.     @OneToMany(mappedBy = "workOrder", cascade = CascadeType.ALL)
  27.     private List<WorkOrderItem> items;
  28.    
  29.     @OneToMany(mappedBy = "workOrder", cascade = CascadeType.ALL)
  30.     private List<WorkOrderPart> parts;
  31. }
  32. @Data
  33. @Entity
  34. @Table(name = "work_order_item")
  35. public class WorkOrderItem {
  36.     @Id
  37.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  38.     private Long id;
  39.    
  40.     @ManyToOne
  41.     @JoinColumn(name = "work_order_id")
  42.     private WorkOrder workOrder;
  43.    
  44.     private Long serviceItemId;
  45.     private Long technicianId;
  46.    
  47.     @Enumerated(EnumType.STRING)
  48.     private ItemStatus status;
  49.    
  50.     private BigDecimal estimatedHours;
  51.     private BigDecimal actualHours;
  52.     private BigDecimal amount;
  53.     private String remark;
  54. }
复制代码
3. 枚举定义

  1. public enum WorkOrderStatus {
  2.     CREATED("已创建"),
  3.     INSPECTING("检查中"),
  4.     REPAIRING("维修中"),
  5.     QUALITY_CHECK("质检中"),
  6.     COMPLETED("已完成"),
  7.     CANCELLED("已取消");
  8.    
  9.     private String description;
  10.    
  11.     WorkOrderStatus(String description) {
  12.         this.description = description;
  13.     }
  14. }
  15. public enum ItemStatus {
  16.     PENDING("待处理"),
  17.     IN_PROGRESS("进行中"),
  18.     COMPLETED("已完成"),
  19.     CANCELLED("已取消");
  20.    
  21.     private String description;
  22. }
复制代码
4. Service层实现

  1. @Service
  2. @Transactional
  3. public class WorkOrderService {
  4.    
  5.     @Autowired
  6.     private WorkOrderRepository workOrderRepository;
  7.    
  8.     @Autowired
  9.     private WorkOrderItemRepository itemRepository;
  10.    
  11.     @Autowired
  12.     private PartInventoryService partInventoryService;
  13.    
  14.     @Autowired
  15.     private NotificationService notificationService;
  16.    
  17.     public WorkOrderResponse createWorkOrder(WorkOrderDTO dto) {
  18.         // 1. 生成工单编号
  19.         String orderNo = generateOrderNo();
  20.         
  21.         // 2. 创建工单
  22.         WorkOrder workOrder = new WorkOrder();
  23.         BeanUtils.copyProperties(dto, workOrder);
  24.         workOrder.setOrderNo(orderNo);
  25.         workOrder.setStatus(WorkOrderStatus.CREATED);
  26.         
  27.         // 3. 创建工单项目
  28.         List<WorkOrderItem> items = createWorkOrderItems(dto.getItems(), workOrder);
  29.         workOrder.setItems(items);
  30.         
  31.         // 4. 计算预估金额
  32.         calculateEstimatedAmount(workOrder);
  33.         
  34.         // 5. 保存工单
  35.         workOrder = workOrderRepository.save(workOrder);
  36.         
  37.         // 6. 发送通知
  38.         notificationService.sendWorkOrderCreatedNotification(workOrder);
  39.         
  40.         return buildResponse(workOrder);
  41.     }
  42.    
  43.     public void updateWorkOrderStatus(Long id, WorkOrderStatus newStatus, String remark) {
  44.         WorkOrder workOrder = workOrderRepository.findById(id)
  45.             .orElseThrow(() -> new BusinessException("工单不存在"));
  46.             
  47.         // 1. 验证状态变更是否合法
  48.         validateStatusTransition(workOrder.getStatus(), newStatus);
  49.         
  50.         // 2. 更新状态
  51.         workOrder.setStatus(newStatus);
  52.         
  53.         // 3. 记录进度
  54.         saveProgress(workOrder, newStatus, remark);
  55.         
  56.         // 4. 特殊状态处理
  57.         handleSpecialStatus(workOrder, newStatus);
  58.         
  59.         // 5. 保存更新
  60.         workOrderRepository.save(workOrder);
  61.         
  62.         // 6. 发送通知
  63.         notificationService.sendStatusChangeNotification(workOrder);
  64.     }
  65.    
  66.     public void addWorkOrderPart(Long workOrderId, WorkOrderPartDTO dto) {
  67.         WorkOrder workOrder = workOrderRepository.findById(workOrderId)
  68.             .orElseThrow(() -> new BusinessException("工单不存在"));
  69.             
  70.         // 1. 检查库存
  71.         partInventoryService.checkInventory(dto.getPartId(), dto.getQuantity());
  72.         
  73.         // 2. 创建配件使用记录
  74.         WorkOrderPart part = new WorkOrderPart();
  75.         BeanUtils.copyProperties(dto, part);
  76.         part.setWorkOrder(workOrder);
  77.         
  78.         // 3. 计算金额
  79.         calculatePartAmount(part);
  80.         
  81.         // 4. 更新工单金额
  82.         updateWorkOrderAmount(workOrder, part.getAmount());
  83.         
  84.         // 5. 扣减库存
  85.         partInventoryService.deductInventory(dto.getPartId(), dto.getQuantity());
  86.         
  87.         // 6. 保存记录
  88.         workOrderPartRepository.save(part);
  89.     }
  90.    
  91.     public void updateWorkOrderProgress(Long id, ProgressUpdateDTO dto) {
  92.         WorkOrder workOrder = workOrderRepository.findById(id)
  93.             .orElseThrow(() -> new BusinessException("工单不存在"));
  94.             
  95.         // 1. 更新项目进度
  96.         updateItemsProgress(workOrder, dto.getItemProgresses());
  97.         
  98.         // 2. 更新工时
  99.         updateLaborHours(workOrder, dto.getItemProgresses());
  100.         
  101.         // 3. 重新计算费用
  102.         recalculateAmount(workOrder);
  103.         
  104.         // 4. 保存更新
  105.         workOrderRepository.save(workOrder);
  106.         
  107.         // 5. 记录进度
  108.         saveProgress(workOrder, dto.getRemark(), dto.getPhotos());
  109.     }
  110.    
  111.     private void calculateEstimatedAmount(WorkOrder workOrder) {
  112.         BigDecimal laborCost = calculateLaborCost(workOrder.getItems());
  113.         BigDecimal partsCost = calculatePartsCost(workOrder.getParts());
  114.         workOrder.setLaborCost(laborCost);
  115.         workOrder.setPartsCost(partsCost);
  116.         workOrder.setTotalAmount(laborCost.add(partsCost));
  117.     }
  118.    
  119.     private void handleSpecialStatus(WorkOrder workOrder, WorkOrderStatus status) {
  120.         switch (status) {
  121.             case COMPLETED:
  122.                 workOrder.setActualCompletionTime(LocalDateTime.now());
  123.                 break;
  124.             case QUALITY_CHECK:
  125.                 validateAllItemsCompleted(workOrder);
  126.                 break;
  127.         }
  128.     }
  129. }
复制代码
5. Controller层实现

  1. @RestController
  2. @RequestMapping("/api/work-orders")
  3. public class WorkOrderController {
  4.    
  5.     @Autowired
  6.     private WorkOrderService workOrderService;
  7.    
  8.     @PostMapping
  9.     public Result<WorkOrderResponse> createWorkOrder(@RequestBody @Valid WorkOrderDTO dto) {
  10.         WorkOrderResponse response = workOrderService.createWorkOrder(dto);
  11.         return Result.success(response);
  12.     }
  13.    
  14.     @PutMapping("/{id}/status")
  15.     public Result<Void> updateStatus(
  16.             @PathVariable Long id,
  17.             @RequestParam WorkOrderStatus status,
  18.             @RequestParam(required = false) String remark) {
  19.         workOrderService.updateWorkOrderStatus(id, status, remark);
  20.         return Result.success();
  21.     }
  22.    
  23.     @PostMapping("/{id}/parts")
  24.     public Result<Void> addPart(
  25.             @PathVariable Long id,
  26.             @RequestBody @Valid WorkOrderPartDTO dto) {
  27.         workOrderService.addWorkOrderPart(id, dto);
  28.         return Result.success();
  29.     }
  30.    
  31.     @PutMapping("/{id}/progress")
  32.     public Result<Void> updateProgress(
  33.             @PathVariable Long id,
  34.             @RequestBody @Valid ProgressUpdateDTO dto) {
  35.         workOrderService.updateWorkOrderProgress(id, dto);
  36.         return Result.success();
  37.     }
  38.    
  39.     @GetMapping("/{id}")
  40.     public Result<WorkOrderDetailResponse> getWorkOrder(@PathVariable Long id) {
  41.         WorkOrderDetailResponse detail = workOrderService.getWorkOrderDetail(id);
  42.         return Result.success(detail);
  43.     }
  44. }
复制代码
6. 费用盘算服务

  1. @Service
  2. public class CostCalculationService {
  3.    
  4.     @Autowired
  5.     private ServiceItemRepository serviceItemRepository;
  6.    
  7.     @Autowired
  8.     private PartRepository partRepository;
  9.    
  10.     public BigDecimal calculateLaborCost(List<WorkOrderItem> items) {
  11.         return items.stream()
  12.             .map(this::calculateItemLaborCost)
  13.             .reduce(BigDecimal.ZERO, BigDecimal::add);
  14.     }
  15.    
  16.     public BigDecimal calculatePartsCost(List<WorkOrderPart> parts) {
  17.         return parts.stream()
  18.             .map(this::calculatePartCost)
  19.             .reduce(BigDecimal.ZERO, BigDecimal::add);
  20.     }
  21.    
  22.     private BigDecimal calculateItemLaborCost(WorkOrderItem item) {
  23.         ServiceItem serviceItem = serviceItemRepository.findById(item.getServiceItemId())
  24.             .orElseThrow(() -> new BusinessException("服务项目不存在"));
  25.             
  26.         return serviceItem.getHourlyRate()
  27.             .multiply(item.getActualHours() != null ?
  28.                 item.getActualHours() : item.getEstimatedHours());
  29.     }
  30.    
  31.     private BigDecimal calculatePartCost(WorkOrderPart part) {
  32.         return part.getUnitPrice().multiply(BigDecimal.valueOf(part.getQuantity()));
  33.     }
  34. }
复制代码
7. 状态机实现

  1. @Component
  2. public class WorkOrderStateMachine {
  3.    
  4.     private static final Map<WorkOrderStatus, Set<WorkOrderStatus>> VALID_TRANSITIONS;
  5.    
  6.     static {
  7.         VALID_TRANSITIONS = new HashMap<>();
  8.         VALID_TRANSITIONS.put(WorkOrderStatus.CREATED,
  9.             Set.of(WorkOrderStatus.INSPECTING, WorkOrderStatus.CANCELLED));
  10.         VALID_TRANSITIONS.put(WorkOrderStatus.INSPECTING,
  11.             Set.of(WorkOrderStatus.REPAIRING, WorkOrderStatus.CANCELLED));
  12.         VALID_TRANSITIONS.put(WorkOrderStatus.REPAIRING,
  13.             Set.of(WorkOrderStatus.QUALITY_CHECK, WorkOrderStatus.CANCELLED));
  14.         VALID_TRANSITIONS.put(WorkOrderStatus.QUALITY_CHECK,
  15.             Set.of(WorkOrderStatus.COMPLETED, WorkOrderStatus.REPAIRING));
  16.     }
  17.    
  18.     public boolean canTransit(WorkOrderStatus current, WorkOrderStatus target) {
  19.         Set<WorkOrderStatus> validTargets = VALID_TRANSITIONS.get(current);
  20.         return validTargets != null && validTargets.contains(target);
  21.     }
  22.    
  23.     public void validateTransition(WorkOrderStatus current, WorkOrderStatus target) {
  24.         if (!canTransit(current, target)) {
  25.             throw new BusinessException(
  26.                 String.format("不允许从%s状态变更为%s状态",
  27.                     current.getDescription(),
  28.                     target.getDescription())
  29.             );
  30.         }
  31.     }
  32. }
复制代码
8. 进度跟踪实现

  1. @Service
  2. public class ProgressTrackingService {
  3.    
  4.     @Autowired
  5.     private WorkOrderProgressRepository progressRepository;
  6.    
  7.     @Autowired
  8.     private FileService fileService;
  9.    
  10.     public void saveProgress(WorkOrder workOrder, String remark, List<MultipartFile> photos) {
  11.         // 1. 保存照片
  12.         List<String> photoUrls = new ArrayList<>();
  13.         if (photos != null && !photos.isEmpty()) {
  14.             photoUrls = photos.stream()
  15.                 .map(photo -> fileService.uploadFile(photo))
  16.                 .collect(Collectors.toList());
  17.         }
  18.         
  19.         // 2. 创建进度记录
  20.         WorkOrderProgress progress = new WorkOrderProgress();
  21.         progress.setWorkOrderId(workOrder.getId());
  22.         progress.setStatus(workOrder.getStatus());
  23.         progress.setRemark(remark);
  24.         progress.setPhotos(String.join(",", photoUrls));
  25.         progress.setOperatorId(SecurityUtils.getCurrentUserId());
  26.         
  27.         // 3. 保存记录
  28.         progressRepository.save(progress);
  29.     }
  30.    
  31.     public List<ProgressResponse> getProgressHistory(Long workOrderId) {
  32.         List<WorkOrderProgress> progressList = progressRepository
  33.             .findByWorkOrderIdOrderByCreatedTimeDesc(workOrderId);
  34.             
  35.         return progressList.stream()
  36.             .map(this::convertToResponse)
  37.             .collect(Collectors.toList());
  38.     }
  39.    
  40.     private ProgressResponse convertToResponse(WorkOrderProgress progress) {
  41.         ProgressResponse response = new ProgressResponse();
  42.         BeanUtils.copyProperties(progress, response);
  43.         
  44.         // 设置操作人信息
  45.         User operator = userService.getUser(progress.getOperatorId());
  46.         response.setOperatorName(operator.getName());
  47.         
  48.         // 处理照片URL
  49.         if (StringUtils.hasText(progress.getPhotos())) {
  50.             response.setPhotoUrls(Arrays.asList(progress.getPhotos().split(",")));
  51.         }
  52.         
  53.         return response;
  54.     }
  55. }
复制代码
9. 工单查询服务

  1. @Service
  2. public class WorkOrderQueryService {
  3.    
  4.     @Autowired
  5.     private WorkOrderRepository workOrderRepository;
  6.    
  7.     public Page<WorkOrderResponse> queryWorkOrders(WorkOrderQueryDTO query) {
  8.         // 1. 构建查询条件
  9.         Specification<WorkOrder> spec = buildSpecification(query);
  10.         
  11.         // 2. 创建分页对象
  12.         PageRequest pageRequest = PageRequest.of(
  13.             query.getPageNum(),
  14.             query.getPageSize(),
  15.             Sort.by(Sort.Direction.DESC, "createdTime")
  16.         );
  17.         
  18.         // 3. 执行查询
  19.         Page<WorkOrder> page = workOrderRepository.findAll(spec, pageRequest);
  20.         
  21.         // 4. 转换响应
  22.         return page.map(this::convertToResponse);
  23.     }
  24.    
  25.     private Specification<WorkOrder> buildSpecification(WorkOrderQueryDTO query) {
  26.         return (root, criteriaQuery, criteriaBuilder) -> {
  27.             List<Predicate> predicates = new ArrayList<>();
  28.             
  29.             // 工单号
  30.             if (StringUtils.hasText(query.getOrderNo())) {
  31.                 predicates.add(criteriaBuilder.like(
  32.                     root.get("orderNo"),
  33.                     "%" + query.getOrderNo() + "%"
  34.                 ));
  35.             }
  36.             
  37.             // 状态
  38.             if (query.getStatus() != null) {
  39.                 predicates.add(criteriaBuilder.equal(
  40.                     root.get("status"),
  41.                     query.getStatus()
  42.                 ));
  43.             }
  44.             
  45.             // 时间范围
  46.             if (query.getStartTime() != null) {
  47.                 predicates.add(criteriaBuilder.greaterThanOrEqualTo(
  48.                     root.get("createdTime"),
  49.                     query.getStartTime()
  50.                 ));
  51.             }
  52.             
  53.             if (query.getEndTime() != null) {
  54.                 predicates.add(criteriaBuilder.lessThanOrEqualTo(
  55.                     root.get("createdTime"),
  56.                     query.getEndTime()
  57.                 ));
  58.             }
  59.             
  60.             return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
  61.         };
  62.     }
  63. }
复制代码
这些代码实现了工单管理的核心功能,包罗:

  • 工单创建和管理
  • 维修项目跟踪
  • 配件使用管理
  • 费用盘算
  • 状态流转控制
  • 进度记录跟踪
关键特点:


  • 完整的状态机实现
  • 细粒度的费用盘算
  • 具体的进度跟踪
  • 灵活的查询功能
  • 完满的数据验证
库存管理模块的核心代码实现

1. 数据库设计

  1. -- 配件信息表
  2. CREATE TABLE part (
  3.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  4.     code VARCHAR(32) UNIQUE NOT NULL COMMENT '配件编号',
  5.     name VARCHAR(100) NOT NULL COMMENT '配件名称',
  6.     category_id BIGINT NOT NULL COMMENT '分类ID',
  7.     brand VARCHAR(50) COMMENT '品牌',
  8.     model VARCHAR(50) COMMENT '型号',
  9.     unit VARCHAR(20) NOT NULL COMMENT '单位',
  10.     price DECIMAL(10,2) NOT NULL COMMENT '单价',
  11.     min_stock INT NOT NULL COMMENT '最低库存',
  12.     max_stock INT NOT NULL COMMENT '最高库存',
  13.     shelf_life INT COMMENT '保质期(天)',
  14.     status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 0-停用 1-启用',
  15.     remark TEXT COMMENT '备注',
  16.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  17.     updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  18. );
  19. -- 库存记录表
  20. CREATE TABLE inventory (
  21.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  22.     part_id BIGINT NOT NULL COMMENT '配件ID',
  23.     warehouse_id BIGINT NOT NULL COMMENT '仓库ID',
  24.     quantity INT NOT NULL DEFAULT 0 COMMENT '当前库存量',
  25.     locked_quantity INT NOT NULL DEFAULT 0 COMMENT '锁定数量',
  26.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  27.     updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  28.     UNIQUE KEY `uk_part_warehouse` (`part_id`, `warehouse_id`)
  29. );
  30. -- 入库记录表
  31. CREATE TABLE stock_in (
  32.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  33.     order_no VARCHAR(32) UNIQUE NOT NULL COMMENT '入库单号',
  34.     warehouse_id BIGINT NOT NULL COMMENT '仓库ID',
  35.     supplier_id BIGINT NOT NULL COMMENT '供应商ID',
  36.     type VARCHAR(20) NOT NULL COMMENT '入库类型',
  37.     status VARCHAR(20) NOT NULL COMMENT '状态',
  38.     total_amount DECIMAL(10,2) NOT NULL COMMENT '总金额',
  39.     operator_id BIGINT NOT NULL COMMENT '操作人',
  40.     remark TEXT COMMENT '备注',
  41.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  42. );
  43. -- 入库明细表
  44. CREATE TABLE stock_in_item (
  45.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  46.     stock_in_id BIGINT NOT NULL COMMENT '入库单ID',
  47.     part_id BIGINT NOT NULL COMMENT '配件ID',
  48.     quantity INT NOT NULL COMMENT '数量',
  49.     unit_price DECIMAL(10,2) NOT NULL COMMENT '单价',
  50.     amount DECIMAL(10,2) NOT NULL COMMENT '金额',
  51.     batch_no VARCHAR(50) COMMENT '批次号',
  52.     production_date DATE COMMENT '生产日期',
  53.     expiry_date DATE COMMENT '过期日期',
  54.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  55.     FOREIGN KEY (stock_in_id) REFERENCES stock_in(id)
  56. );
  57. -- 库存变动记录表
  58. CREATE TABLE inventory_transaction (
  59.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  60.     part_id BIGINT NOT NULL COMMENT '配件ID',
  61.     warehouse_id BIGINT NOT NULL COMMENT '仓库ID',
  62.     type VARCHAR(20) NOT NULL COMMENT '变动类型',
  63.     quantity INT NOT NULL COMMENT '变动数量',
  64.     before_quantity INT NOT NULL COMMENT '变动前数量',
  65.     after_quantity INT NOT NULL COMMENT '变动后数量',
  66.     reference_no VARCHAR(32) COMMENT '关联单号',
  67.     operator_id BIGINT NOT NULL COMMENT '操作人',
  68.     remark TEXT COMMENT '备注',
  69.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  70. );
  71. -- 库存盘点表
  72. CREATE TABLE inventory_check (
  73.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  74.     check_no VARCHAR(32) UNIQUE NOT NULL COMMENT '盘点单号',
  75.     warehouse_id BIGINT NOT NULL COMMENT '仓库ID',
  76.     status VARCHAR(20) NOT NULL COMMENT '状态',
  77.     start_time DATETIME NOT NULL COMMENT '开始时间',
  78.     end_time DATETIME COMMENT '结束时间',
  79.     operator_id BIGINT NOT NULL COMMENT '操作人',
  80.     remark TEXT COMMENT '备注',
  81.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  82. );
  83. -- 盘点明细表
  84. CREATE TABLE inventory_check_item (
  85.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  86.     check_id BIGINT NOT NULL COMMENT '盘点单ID',
  87.     part_id BIGINT NOT NULL COMMENT '配件ID',
  88.     system_quantity INT NOT NULL COMMENT '系统数量',
  89.     actual_quantity INT NOT NULL COMMENT '实际数量',
  90.     difference INT NOT NULL COMMENT '差异数量',
  91.     remark TEXT COMMENT '备注',
  92.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  93.     FOREIGN KEY (check_id) REFERENCES inventory_check(id)
  94. );
复制代码
2. 实体类设计

  1. @Data
  2. @Entity
  3. @Table(name = "part")
  4. public class Part {
  5.     @Id
  6.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  7.     private Long id;
  8.    
  9.     private String code;
  10.     private String name;
  11.     private Long categoryId;
  12.     private String brand;
  13.     private String model;
  14.     private String unit;
  15.     private BigDecimal price;
  16.     private Integer minStock;
  17.     private Integer maxStock;
  18.     private Integer shelfLife;
  19.     private Integer status;
  20.     private String remark;
  21.     private LocalDateTime createdTime;
  22.     private LocalDateTime updatedTime;
  23. }
  24. @Data
  25. @Entity
  26. @Table(name = "inventory")
  27. public class Inventory {
  28.     @Id
  29.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  30.     private Long id;
  31.    
  32.     private Long partId;
  33.     private Long warehouseId;
  34.     private Integer quantity;
  35.     private Integer lockedQuantity;
  36.     private LocalDateTime createdTime;
  37.     private LocalDateTime updatedTime;
  38.    
  39.     @Version
  40.     private Integer version;  // 乐观锁版本号
  41. }
  42. @Data
  43. @Entity
  44. @Table(name = "stock_in")
  45. public class StockIn {
  46.     @Id
  47.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  48.     private Long id;
  49.    
  50.     private String orderNo;
  51.     private Long warehouseId;
  52.     private Long supplierId;
  53.    
  54.     @Enumerated(EnumType.STRING)
  55.     private StockInType type;
  56.    
  57.     @Enumerated(EnumType.STRING)
  58.     private StockInStatus status;
  59.    
  60.     private BigDecimal totalAmount;
  61.     private Long operatorId;
  62.     private String remark;
  63.     private LocalDateTime createdTime;
  64.    
  65.     @OneToMany(mappedBy = "stockIn", cascade = CascadeType.ALL)
  66.     private List<StockInItem> items;
  67. }
复制代码
3. 入库服务实现

  1. @Service
  2. @Transactional
  3. public class StockInService {
  4.    
  5.     @Autowired
  6.     private StockInRepository stockInRepository;
  7.    
  8.     @Autowired
  9.     private InventoryService inventoryService;
  10.    
  11.     @Autowired
  12.     private SequenceGenerator sequenceGenerator;
  13.    
  14.     public StockInResponse createStockIn(StockInDTO dto) {
  15.         // 1. 生成入库单号
  16.         String orderNo = sequenceGenerator.generateStockInNo();
  17.         
  18.         // 2. 创建入库单
  19.         StockIn stockIn = new StockIn();
  20.         BeanUtils.copyProperties(dto, stockIn);
  21.         stockIn.setOrderNo(orderNo);
  22.         stockIn.setStatus(StockInStatus.PENDING);
  23.         
  24.         // 3. 创建入库明细
  25.         List<StockInItem> items = createStockInItems(dto.getItems(), stockIn);
  26.         stockIn.setItems(items);
  27.         
  28.         // 4. 计算总金额
  29.         BigDecimal totalAmount = calculateTotalAmount(items);
  30.         stockIn.setTotalAmount(totalAmount);
  31.         
  32.         // 5. 保存入库单
  33.         stockIn = stockInRepository.save(stockIn);
  34.         
  35.         return buildResponse(stockIn);
  36.     }
  37.    
  38.     public void confirmStockIn(Long id) {
  39.         StockIn stockIn = stockInRepository.findById(id)
  40.             .orElseThrow(() -> new BusinessException("入库单不存在"));
  41.             
  42.         // 1. 验证状态
  43.         if (stockIn.getStatus() != StockInStatus.PENDING) {
  44.             throw new BusinessException("入库单状态不正确");
  45.         }
  46.         
  47.         // 2. 更新库存
  48.         for (StockInItem item : stockIn.getItems()) {
  49.             inventoryService.increaseStock(
  50.                 item.getPartId(),
  51.                 stockIn.getWarehouseId(),
  52.                 item.getQuantity(),
  53.                 stockIn.getOrderNo()
  54.             );
  55.         }
  56.         
  57.         // 3. 更新入库单状态
  58.         stockIn.setStatus(StockInStatus.COMPLETED);
  59.         stockInRepository.save(stockIn);
  60.     }
  61. }
复制代码
4. 库存服务实现

  1. @Service
  2. @Transactional
  3. public class InventoryService {
  4.    
  5.     @Autowired
  6.     private InventoryRepository inventoryRepository;
  7.    
  8.     @Autowired
  9.     private InventoryTransactionRepository transactionRepository;
  10.    
  11.     @Autowired
  12.     private RedisTemplate<String, Object> redisTemplate;
  13.    
  14.     public void increaseStock(Long partId, Long warehouseId, Integer quantity, String referenceNo) {
  15.         // 1. 获取或创建库存记录
  16.         Inventory inventory = getOrCreateInventory(partId, warehouseId);
  17.         
  18.         // 2. 更新库存(使用乐观锁)
  19.         int retryCount = 0;
  20.         while (retryCount < 3) {
  21.             try {
  22.                 inventory.setQuantity(inventory.getQuantity() + quantity);
  23.                 inventoryRepository.save(inventory);
  24.                 break;
  25.             } catch (OptimisticLockingFailureException e) {
  26.                 if (++retryCount == 3) {
  27.                     throw new BusinessException("更新库存失败,请重试");
  28.                 }
  29.                 inventory = inventoryRepository.findByPartIdAndWarehouseId(partId, warehouseId)
  30.                     .orElseThrow();
  31.             }
  32.         }
  33.         
  34.         // 3. 记录库存变动
  35.         saveInventoryTransaction(
  36.             inventory,
  37.             TransactionType.STOCK_IN,
  38.             quantity,
  39.             referenceNo
  40.         );
  41.         
  42.         // 4. 检查库存预警
  43.         checkStockWarning(inventory);
  44.     }
  45.    
  46.     public void decreaseStock(Long partId, Long warehouseId, Integer quantity, String referenceNo) {
  47.         // 1. 获取库存记录
  48.         Inventory inventory = inventoryRepository.findByPartIdAndWarehouseId(partId, warehouseId)
  49.             .orElseThrow(() -> new BusinessException("库存记录不存在"));
  50.             
  51.         // 2. 检查库存是否足够
  52.         if (inventory.getQuantity() - inventory.getLockedQuantity() < quantity) {
  53.             throw new BusinessException("可用库存不足");
  54.         }
  55.         
  56.         // 3. 更新库存(使用乐观锁)
  57.         int retryCount = 0;
  58.         while (retryCount < 3) {
  59.             try {
  60.                 inventory.setQuantity(inventory.getQuantity() - quantity);
  61.                 inventoryRepository.save(inventory);
  62.                 break;
  63.             } catch (OptimisticLockingFailureException e) {
  64.                 if (++retryCount == 3) {
  65.                     throw new BusinessException("更新库存失败,请重试");
  66.                 }
  67.                 inventory = inventoryRepository.findByPartIdAndWarehouseId(partId, warehouseId)
  68.                     .orElseThrow();
  69.             }
  70.         }
  71.         
  72.         // 4. 记录库存变动
  73.         saveInventoryTransaction(
  74.             inventory,
  75.             TransactionType.STOCK_OUT,
  76.             -quantity,
  77.             referenceNo
  78.         );
  79.         
  80.         // 5. 检查库存预警
  81.         checkStockWarning(inventory);
  82.     }
  83.    
  84.     private void checkStockWarning(Inventory inventory) {
  85.         Part part = partRepository.findById(inventory.getPartId())
  86.             .orElseThrow();
  87.             
  88.         // 检查是否低于最低库存
  89.         if (inventory.getQuantity() <= part.getMinStock()) {
  90.             // 发送库存预警
  91.             sendStockWarning(inventory, part);
  92.             
  93.             // 缓存预警信息
  94.             cacheStockWarning(inventory, part);
  95.         }
  96.     }
  97. }
复制代码
5. 库存盘货服务实现

  1. @Service
  2. @Transactional
  3. public class InventoryCheckService {
  4.    
  5.     @Autowired
  6.     private InventoryCheckRepository checkRepository;
  7.    
  8.     @Autowired
  9.     private InventoryService inventoryService;
  10.    
  11.     public InventoryCheckResponse createCheck(InventoryCheckDTO dto) {
  12.         // 1. 生成盘点单号
  13.         String checkNo = sequenceGenerator.generateCheckNo();
  14.         
  15.         // 2. 创建盘点单
  16.         InventoryCheck check = new InventoryCheck();
  17.         BeanUtils.copyProperties(dto, check);
  18.         check.setCheckNo(checkNo);
  19.         check.setStatus(CheckStatus.IN_PROGRESS);
  20.         check.setStartTime(LocalDateTime.now());
  21.         
  22.         // 3. 获取系统库存数据
  23.         List<InventoryCheckItem> items = generateCheckItems(dto.getWarehouseId());
  24.         check.setItems(items);
  25.         
  26.         // 4. 保存盘点单
  27.         check = checkRepository.save(check);
  28.         
  29.         return buildResponse(check);
  30.     }
  31.    
  32.     public void completeCheck(Long id, List<CheckItemDTO> items) {
  33.         InventoryCheck check = checkRepository.findById(id)
  34.             .orElseThrow(() -> new BusinessException("盘点单不存在"));
  35.             
  36.         // 1. 验证状态
  37.         if (check.getStatus() != CheckStatus.IN_PROGRESS) {
  38.             throw new BusinessException("盘点单状态不正确");
  39.         }
  40.         
  41.         // 2. 更新盘点结果
  42.         updateCheckItems(check, items);
  43.         
  44.         // 3. 处理盘盈盘亏
  45.         handleInventoryDifference(check);
  46.         
  47.         // 4. 完成盘点
  48.         check.setStatus(CheckStatus.COMPLETED);
  49.         check.setEndTime(LocalDateTime.now());
  50.         checkRepository.save(check);
  51.     }
  52.    
  53.     private void handleInventoryDifference(InventoryCheck check) {
  54.         for (InventoryCheckItem item : check.getItems()) {
  55.             if (item.getDifference() != 0) {
  56.                 // 记录库存调整
  57.                 inventoryService.adjustStock(
  58.                     item.getPartId(),
  59.                     check.getWarehouseId(),
  60.                     item.getDifference(),
  61.                     check.getCheckNo()
  62.                 );
  63.             }
  64.         }
  65.     }
  66. }
复制代码
6. 库存预警服务实现

  1. @Service
  2. public class StockWarningService {
  3.    
  4.     @Autowired
  5.     private RedisTemplate<String, Object> redisTemplate;
  6.    
  7.     @Autowired
  8.     private NotificationService notificationService;
  9.    
  10.     private static final String WARNING_KEY_PREFIX = "stock:warning:";
  11.    
  12.     public void sendStockWarning(Inventory inventory, Part part) {
  13.         StockWarningMessage message = StockWarningMessage.builder()
  14.             .partCode(part.getCode())
  15.             .partName(part.getName())
  16.             .currentStock(inventory.getQuantity())
  17.             .minStock(part.getMinStock())
  18.             .warehouseId(inventory.getWarehouseId())
  19.             .build();
  20.             
  21.         // 1. 发送消息通知
  22.         notificationService.sendStockWarning(message);
  23.         
  24.         // 2. 缓存预警信息
  25.         cacheWarningInfo(inventory.getPartId(), message);
  26.     }
  27.    
  28.     public List<StockWarningMessage> getWarningList() {
  29.         Set<String> keys = redisTemplate.keys(WARNING_KEY_PREFIX + "*");
  30.         if (keys == null || keys.isEmpty()) {
  31.             return Collections.emptyList();
  32.         }
  33.         
  34.         return keys.stream()
  35.             .map(key -> (StockWarningMessage) redisTemplate.opsForValue().get(key))
  36.             .collect(Collectors.toList());
  37.     }
  38.    
  39.     private void cacheWarningInfo(Long partId, StockWarningMessage message) {
  40.         String key = WARNING_KEY_PREFIX + partId;
  41.         redisTemplate.opsForValue().set(key, message, 24, TimeUnit.HOURS);
  42.     }
  43. }
复制代码
7. 库存统计服务实现

  1. @Service
  2. public class InventoryStatisticsService {
  3.    
  4.     @Autowired
  5.     private InventoryRepository inventoryRepository;
  6.    
  7.     @Autowired
  8.     private InventoryTransactionRepository transactionRepository;
  9.    
  10.     public InventoryStatisticsResponse getStatistics(StatisticsQueryDTO query) {
  11.         // 1. 库存总量统计
  12.         InventoryTotalVO total = calculateInventoryTotal(query);
  13.         
  14.         // 2. 库存金额统计
  15.         InventoryAmountVO amount = calculateInventoryAmount(query);
  16.         
  17.         // 3. 库存周转率统计
  18.         TurnoverRateVO turnover = calculateTurnoverRate(query);
  19.         
  20.         // 4. 库存预警统计
  21.         WarningStatisticsVO warning = calculateWarningStatistics(query);
  22.         
  23.         return InventoryStatisticsResponse.builder()
  24.             .total(total)
  25.             .amount(amount)
  26.             .turnover(turnover)
  27.             .warning(warning)
  28.             .build();
  29.     }
  30.    
  31.     public List<InventoryTransactionVO> getTransactionHistory(
  32.             Long partId, LocalDateTime startTime, LocalDateTime endTime) {
  33.         List<InventoryTransaction> transactions =
  34.             transactionRepository.findByPartIdAndCreatedTimeBetween(
  35.                 partId, startTime, endTime);
  36.                
  37.         return transactions.stream()
  38.             .map(this::convertToVO)
  39.             .collect(Collectors.toList());
  40.     }
  41.    
  42.     private TurnoverRateVO calculateTurnoverRate(StatisticsQueryDTO query) {
  43.         // 1. 获取期初库存
  44.         BigDecimal beginningInventory = getBeginningInventory(query);
  45.         
  46.         // 2. 获取期末库存
  47.         BigDecimal endingInventory = getEndingInventory(query);
  48.         
  49.         // 3. 获取期间出库数量
  50.         BigDecimal outboundQuantity = getOutboundQuantity(query);
  51.         
  52.         // 4. 计算平均库存
  53.         BigDecimal averageInventory = beginningInventory.add(endingInventory)
  54.             .divide(BigDecimal.valueOf(2), 2, RoundingMode.HALF_UP);
  55.             
  56.         // 5. 计算周转率
  57.         BigDecimal turnoverRate = BigDecimal.ZERO;
  58.         if (averageInventory.compareTo(BigDecimal.ZERO) > 0) {
  59.             turnoverRate = outboundQuantity.divide(averageInventory, 2, RoundingMode.HALF_UP);
  60.         }
  61.         
  62.         return new TurnoverRateVO(turnoverRate);
  63.     }
  64. }
复制代码
8. 库存查询接口实现

  1. @RestController
  2. @RequestMapping("/api/inventory")
  3. public class InventoryController {
  4.    
  5.     @Autowired
  6.     private InventoryService inventoryService;
  7.    
  8.     @Autowired
  9.     private InventoryStatisticsService statisticsService;
  10.    
  11.     @GetMapping("/stock")
  12.     public Result<Page<InventoryVO>> queryStock(InventoryQueryDTO query) {
  13.         Page<InventoryVO> page = inventoryService.queryStock(query);
  14.         return Result.success(page);
  15.     }
  16.    
  17.     @GetMapping("/warning")
  18.     public Result<List<StockWarningMessage>> getWarningList() {
  19.         List<StockWarningMessage> warnings = inventoryService.getWarningList();
  20.         return Result.success(warnings);
  21.     }
  22.    
  23.     @GetMapping("/statistics")
  24.     public Result<InventoryStatisticsResponse> getStatistics(StatisticsQueryDTO query) {
  25.         InventoryStatisticsResponse statistics = statisticsService.getStatistics(query);
  26.         return Result.success(statistics);
  27.     }
  28.    
  29.     @GetMapping("/transaction-history")
  30.     public Result<List<InventoryTransactionVO>> getTransactionHistory(
  31.             @RequestParam Long partId,
  32.             @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
  33.             @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
  34.         List<InventoryTransactionVO> history =
  35.             statisticsService.getTransactionHistory(partId, startTime, endTime);
  36.         return Result.success(history);
  37.     }
  38. }
复制代码
这些代码实现了库存管理的核心功能,包罗:

  • 配件入库管理
  • 库存变动控制
  • 库存预警机制
  • 库存盘货处理
  • 库存统计分析
关键特点:


  • 使用乐观锁控制并发
  • Redis缓存预警信息
  • 完整的库存变动追踪
  • 具体的统计分析功能
  • 支持库存盘货处理
客户管理模块的核心代码实现

1. 数据库设计

  1. -- 客户信息表
  2. CREATE TABLE customer (
  3.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  4.     code VARCHAR(32) UNIQUE NOT NULL COMMENT '客户编号',
  5.     name VARCHAR(100) NOT NULL COMMENT '客户姓名',
  6.     phone VARCHAR(20) NOT NULL COMMENT '联系电话',
  7.     id_card VARCHAR(18) COMMENT '身份证号',
  8.     gender TINYINT COMMENT '性别: 0-女 1-男',
  9.     birthday DATE COMMENT '生日',
  10.     email VARCHAR(100) COMMENT '邮箱',
  11.     address TEXT COMMENT '地址',
  12.     source VARCHAR(50) COMMENT '客户来源',
  13.     level VARCHAR(20) NOT NULL DEFAULT 'NORMAL' COMMENT '客户等级',
  14.     points INT NOT NULL DEFAULT 0 COMMENT '积分',
  15.     status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 0-禁用 1-启用',
  16.     remark TEXT COMMENT '备注',
  17.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  18.     updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  19. );
  20. -- 车辆信息表
  21. CREATE TABLE vehicle (
  22.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  23.     customer_id BIGINT NOT NULL COMMENT '客户ID',
  24.     plate_number VARCHAR(20) NOT NULL COMMENT '车牌号',
  25.     brand VARCHAR(50) NOT NULL COMMENT '品牌',
  26.     model VARCHAR(50) NOT NULL COMMENT '型号',
  27.     vin VARCHAR(50) UNIQUE COMMENT '车架号',
  28.     engine_number VARCHAR(50) COMMENT '发动机号',
  29.     color VARCHAR(20) COMMENT '颜色',
  30.     mileage INT COMMENT '行驶里程',
  31.     purchase_date DATE COMMENT '购买日期',
  32.     insurance_expiry DATE COMMENT '保险到期日',
  33.     last_service_date DATE COMMENT '最后保养日期',
  34.     status TINYINT NOT NULL DEFAULT 1 COMMENT '状态',
  35.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  36.     updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  37.     FOREIGN KEY (customer_id) REFERENCES customer(id)
  38. );
  39. -- 维修记录表
  40. CREATE TABLE service_record (
  41.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  42.     work_order_id BIGINT NOT NULL COMMENT '工单ID',
  43.     customer_id BIGINT NOT NULL COMMENT '客户ID',
  44.     vehicle_id BIGINT NOT NULL COMMENT '车辆ID',
  45.     service_type VARCHAR(50) NOT NULL COMMENT '服务类型',
  46.     service_items TEXT COMMENT '服务项目',
  47.     total_amount DECIMAL(10,2) NOT NULL COMMENT '总金额',
  48.     service_date DATE NOT NULL COMMENT '服务日期',
  49.     mileage INT COMMENT '服务时里程',
  50.     technician_id BIGINT COMMENT '技师ID',
  51.     remark TEXT COMMENT '备注',
  52.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  53.     FOREIGN KEY (customer_id) REFERENCES customer(id),
  54.     FOREIGN KEY (vehicle_id) REFERENCES vehicle(id)
  55. );
  56. -- 积分变动记录表
  57. CREATE TABLE points_transaction (
  58.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  59.     customer_id BIGINT NOT NULL COMMENT '客户ID',
  60.     type VARCHAR(20) NOT NULL COMMENT '变动类型',
  61.     points INT NOT NULL COMMENT '变动积分',
  62.     before_points INT NOT NULL COMMENT '变动前积分',
  63.     after_points INT NOT NULL COMMENT '变动后积分',
  64.     reference_no VARCHAR(32) COMMENT '关联单号',
  65.     remark TEXT COMMENT '备注',
  66.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  67.     FOREIGN KEY (customer_id) REFERENCES customer(id)
  68. );
复制代码
2. 实体类设计

  1. @Data
  2. @Entity
  3. @Table(name = "customer")
  4. public class Customer {
  5.     @Id
  6.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  7.     private Long id;
  8.    
  9.     private String code;
  10.     private String name;
  11.     private String phone;
  12.     private String idCard;
  13.     private Integer gender;
  14.     private LocalDate birthday;
  15.     private String email;
  16.     private String address;
  17.     private String source;
  18.    
  19.     @Enumerated(EnumType.STRING)
  20.     private CustomerLevel level;
  21.    
  22.     private Integer points;
  23.     private Integer status;
  24.     private String remark;
  25.     private LocalDateTime createdTime;
  26.     private LocalDateTime updatedTime;
  27.    
  28.     @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
  29.     private List<Vehicle> vehicles;
  30. }
  31. @Data
  32. @Entity
  33. @Table(name = "vehicle")
  34. public class Vehicle {
  35.     @Id
  36.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  37.     private Long id;
  38.    
  39.     @ManyToOne
  40.     @JoinColumn(name = "customer_id")
  41.     private Customer customer;
  42.    
  43.     private String plateNumber;
  44.     private String brand;
  45.     private String model;
  46.     private String vin;
  47.     private String engineNumber;
  48.     private String color;
  49.     private Integer mileage;
  50.     private LocalDate purchaseDate;
  51.     private LocalDate insuranceExpiry;
  52.     private LocalDate lastServiceDate;
  53.     private Integer status;
  54. }
复制代码
3. 客户服务实现

  1. @Service
  2. @Transactional
  3. public class CustomerService {
  4.    
  5.     @Autowired
  6.     private CustomerRepository customerRepository;
  7.    
  8.     @Autowired
  9.     private SequenceGenerator sequenceGenerator;
  10.    
  11.     @Autowired
  12.     private PointsService pointsService;
  13.    
  14.     public CustomerResponse createCustomer(CustomerDTO dto) {
  15.         // 1. 验证手机号是否已存在
  16.         validatePhone(dto.getPhone());
  17.         
  18.         // 2. 生成客户编号
  19.         String code = sequenceGenerator.generateCustomerCode();
  20.         
  21.         // 3. 创建客户信息
  22.         Customer customer = new Customer();
  23.         BeanUtils.copyProperties(dto, customer);
  24.         customer.setCode(code);
  25.         customer.setLevel(CustomerLevel.NORMAL);
  26.         customer.setPoints(0);
  27.         customer.setStatus(1);
  28.         
  29.         // 4. 保存客户信息
  30.         customer = customerRepository.save(customer);
  31.         
  32.         // 5. 处理车辆信息
  33.         if (dto.getVehicles() != null && !dto.getVehicles().isEmpty()) {
  34.             List<Vehicle> vehicles = createVehicles(dto.getVehicles(), customer);
  35.             customer.setVehicles(vehicles);
  36.         }
  37.         
  38.         return buildResponse(customer);
  39.     }
  40.    
  41.     public void updateCustomer(Long id, CustomerUpdateDTO dto) {
  42.         Customer customer = customerRepository.findById(id)
  43.             .orElseThrow(() -> new BusinessException("客户不存在"));
  44.             
  45.         // 1. 如果修改手机号,需要验证唯一性
  46.         if (!customer.getPhone().equals(dto.getPhone())) {
  47.             validatePhone(dto.getPhone());
  48.         }
  49.         
  50.         // 2. 更新客户信息
  51.         BeanUtils.copyProperties(dto, customer);
  52.         customerRepository.save(customer);
  53.     }
  54.    
  55.     public CustomerDetailResponse getCustomerDetail(Long id) {
  56.         Customer customer = customerRepository.findById(id)
  57.             .orElseThrow(() -> new BusinessException("客户不存在"));
  58.             
  59.         // 1. 获取客户基本信息
  60.         CustomerDetailResponse response = buildDetailResponse(customer);
  61.         
  62.         // 2. 获取车辆信息
  63.         List<VehicleVO> vehicles = getCustomerVehicles(id);
  64.         response.setVehicles(vehicles);
  65.         
  66.         // 3. 获取最近维修记录
  67.         List<ServiceRecordVO> serviceRecords = getRecentServiceRecords(id);
  68.         response.setServiceRecords(serviceRecords);
  69.         
  70.         // 4. 获取积分明细
  71.         List<PointsTransactionVO> pointsHistory = getPointsHistory(id);
  72.         response.setPointsHistory(pointsHistory);
  73.         
  74.         return response;
  75.     }
  76.    
  77.     @Cacheable(value = "customerLevel", key = "#customerId")
  78.     public CustomerLevel calculateCustomerLevel(Long customerId) {
  79.         // 1. 获取消费总额
  80.         BigDecimal totalAmount = serviceRecordRepository
  81.             .calculateTotalAmount(customerId);
  82.             
  83.         // 2. 计算客户等级
  84.         return CustomerLevel.calculateLevel(totalAmount);
  85.     }
  86. }
复制代码
4. 车辆服务实现

  1. @Service
  2. @Transactional
  3. public class VehicleService {
  4.    
  5.     @Autowired
  6.     private VehicleRepository vehicleRepository;
  7.    
  8.     @Autowired
  9.     private ServiceRecordRepository serviceRecordRepository;
  10.    
  11.     public VehicleResponse addVehicle(VehicleDTO dto) {
  12.         // 1. 验证车牌号是否已存在
  13.         validatePlateNumber(dto.getPlateNumber());
  14.         
  15.         // 2. 创建车辆信息
  16.         Vehicle vehicle = new Vehicle();
  17.         BeanUtils.copyProperties(dto, vehicle);
  18.         
  19.         // 3. 保存车辆信息
  20.         vehicle = vehicleRepository.save(vehicle);
  21.         
  22.         return buildResponse(vehicle);
  23.     }
  24.    
  25.     public void updateVehicle(Long id, VehicleUpdateDTO dto) {
  26.         Vehicle vehicle = vehicleRepository.findById(id)
  27.             .orElseThrow(() -> new BusinessException("车辆不存在"));
  28.             
  29.         // 1. 如果修改车牌号,需要验证唯一性
  30.         if (!vehicle.getPlateNumber().equals(dto.getPlateNumber())) {
  31.             validatePlateNumber(dto.getPlateNumber());
  32.         }
  33.         
  34.         // 2. 更新车辆信息
  35.         BeanUtils.copyProperties(dto, vehicle);
  36.         vehicleRepository.save(vehicle);
  37.     }
  38.    
  39.     public VehicleDetailResponse getVehicleDetail(Long id) {
  40.         Vehicle vehicle = vehicleRepository.findById(id)
  41.             .orElseThrow(() -> new BusinessException("车辆不存在"));
  42.             
  43.         // 1. 获取车辆基本信息
  44.         VehicleDetailResponse response = buildDetailResponse(vehicle);
  45.         
  46.         // 2. 获取维修记录
  47.         List<ServiceRecordVO> serviceRecords = getServiceRecords(id);
  48.         response.setServiceRecords(serviceRecords);
  49.         
  50.         // 3. 获取保养提醒
  51.         List<MaintenanceReminderVO> reminders = calculateMaintenanceReminders(vehicle);
  52.         response.setMaintenanceReminders(reminders);
  53.         
  54.         return response;
  55.     }
  56.    
  57.     private List<MaintenanceReminderVO> calculateMaintenanceReminders(Vehicle vehicle) {
  58.         List<MaintenanceReminderVO> reminders = new ArrayList<>();
  59.         
  60.         // 1. 常规保养提醒(按里程)
  61.         if (vehicle.getMileage() != null) {
  62.             int nextServiceMileage = calculateNextServiceMileage(vehicle.getMileage());
  63.             reminders.add(new MaintenanceReminderVO(
  64.                 "常规保养",
  65.                 "行驶里程达到" + nextServiceMileage + "公里时建议进行保养"
  66.             ));
  67.         }
  68.         
  69.         // 2. 保险到期提醒
  70.         if (vehicle.getInsuranceExpiry() != null) {
  71.             LocalDate today = LocalDate.now();
  72.             long daysUntilExpiry = ChronoUnit.DAYS.between(today, vehicle.getInsuranceExpiry());
  73.             
  74.             if (daysUntilExpiry <= 30) {
  75.                 reminders.add(new MaintenanceReminderVO(
  76.                     "保险到期提醒",
  77.                     "保险将在" + daysUntilExpiry + "天后到期"
  78.                 ));
  79.             }
  80.         }
  81.         
  82.         return reminders;
  83.     }
  84. }
复制代码
5. 积分服务实现

  1. @Service
  2. @Transactional
  3. public class PointsService {
  4.    
  5.     @Autowired
  6.     private CustomerRepository customerRepository;
  7.    
  8.     @Autowired
  9.     private PointsTransactionRepository transactionRepository;
  10.    
  11.     public void addPoints(PointsAddDTO dto) {
  12.         Customer customer = customerRepository.findById(dto.getCustomerId())
  13.             .orElseThrow(() -> new BusinessException("客户不存在"));
  14.             
  15.         // 1. 计算积分变动
  16.         int beforePoints = customer.getPoints();
  17.         int afterPoints = beforePoints + dto.getPoints();
  18.         
  19.         // 2. 更新客户积分
  20.         customer.setPoints(afterPoints);
  21.         customerRepository.save(customer);
  22.         
  23.         // 3. 记录积分变动
  24.         savePointsTransaction(
  25.             customer.getId(),
  26.             PointsTransactionType.EARN,
  27.             dto.getPoints(),
  28.             beforePoints,
  29.             afterPoints,
  30.             dto.getReferenceNo(),
  31.             dto.getRemark()
  32.         );
  33.         
  34.         // 4. 检查等级变更
  35.         checkAndUpdateLevel(customer);
  36.     }
  37.    
  38.     public void deductPoints(PointsDeductDTO dto) {
  39.         Customer customer = customerRepository.findById(dto.getCustomerId())
  40.             .orElseThrow(() -> new BusinessException("客户不存在"));
  41.             
  42.         // 1. 验证积分是否足够
  43.         if (customer.getPoints() < dto.getPoints()) {
  44.             throw new BusinessException("积分不足");
  45.         }
  46.         
  47.         // 2. 计算积分变动
  48.         int beforePoints = customer.getPoints();
  49.         int afterPoints = beforePoints - dto.getPoints();
  50.         
  51.         // 3. 更新客户积分
  52.         customer.setPoints(afterPoints);
  53.         customerRepository.save(customer);
  54.         
  55.         // 4. 记录积分变动
  56.         savePointsTransaction(
  57.             customer.getId(),
  58.             PointsTransactionType.CONSUME,
  59.             -dto.getPoints(),
  60.             beforePoints,
  61.             afterPoints,
  62.             dto.getReferenceNo(),
  63.             dto.getRemark()
  64.         );
  65.     }
  66.    
  67.     public PointsStatisticsResponse getPointsStatistics(Long customerId) {
  68.         // 1. 获取当前积分
  69.         Customer customer = customerRepository.findById(customerId)
  70.             .orElseThrow(() -> new BusinessException("客户不存在"));
  71.             
  72.         // 2. 获取积分汇总信息
  73.         PointsSummaryVO summary = calculatePointsSummary(customerId);
  74.         
  75.         // 3. 获取近期积分变动
  76.         List<PointsTransactionVO> recentTransactions =
  77.             getRecentTransactions(customerId);
  78.             
  79.         return PointsStatisticsResponse.builder()
  80.             .currentPoints(customer.getPoints())
  81.             .summary(summary)
  82.             .recentTransactions(recentTransactions)
  83.             .build();
  84.     }
  85.    
  86.     private void checkAndUpdateLevel(Customer customer) {
  87.         CustomerLevel newLevel = customerService.calculateCustomerLevel(customer.getId());
  88.         if (newLevel != customer.getLevel()) {
  89.             // 更新客户等级
  90.             customer.setLevel(newLevel);
  91.             customerRepository.save(customer);
  92.             
  93.             // 发送等级变更通知
  94.             notificationService.sendLevelChangeNotification(customer);
  95.         }
  96.     }
  97. }
复制代码
6. 维修记录查询服务

  1. @Service
  2. public class ServiceRecordQueryService {
  3.    
  4.     @Autowired
  5.     private ServiceRecordRepository serviceRecordRepository;
  6.    
  7.     public Page<ServiceRecordVO> queryServiceRecords(ServiceRecordQueryDTO query) {
  8.         // 1. 构建查询条件
  9.         Specification<ServiceRecord> spec = buildSpecification(query);
  10.         
  11.         // 2. 创建分页对象
  12.         PageRequest pageRequest = PageRequest.of(
  13.             query.getPageNum(),
  14.             query.getPageSize(),
  15.             Sort.by(Sort.Direction.DESC, "serviceDate")
  16.         );
  17.         
  18.         // 3. 执行查询
  19.         Page<ServiceRecord> page = serviceRecordRepository.findAll(spec, pageRequest);
  20.         
  21.         // 4. 转换响应
  22.         return page.map(this::convertToVO);
  23.     }
  24.    
  25.     public ServiceRecordDetailResponse getServiceRecordDetail(Long id) {
  26.         ServiceRecord record = serviceRecordRepository.findById(id)
  27.             .orElseThrow(() -> new BusinessException("维修记录不存在"));
  28.             
  29.         // 1. 获取基本信息
  30.         ServiceRecordDetailResponse response = buildDetailResponse(record);
  31.         
  32.         // 2. 获取服务项目明细
  33.         List<ServiceItemVO> items = getServiceItems(record);
  34.         response.setItems(items);
  35.         
  36.         // 3. 获取配件使用记录
  37.         List<PartUsageVO> partUsages = getPartUsages(record);
  38.         response.setPartUsages(partUsages);
  39.         
  40.         return response;
  41.     }
  42.    
  43.     public List<ServiceStatisticsVO> getServiceStatistics(Long customerId) {
  44.         // 1. 获取维修频次统计
  45.         Map<String, Long> serviceFrequency = calculateServiceFrequency(customerId);
  46.         
  47.         // 2. 获取维修金额统计
  48.         Map<String, BigDecimal> serviceAmount = calculateServiceAmount(customerId);
  49.         
  50.         // 3. 获取常见维修项目
  51.         List<CommonServiceItemVO> commonItems = getCommonServiceItems(customerId);
  52.         
  53.         return buildStatisticsResponse(serviceFrequency, serviceAmount, commonItems);
  54.     }
  55. }
复制代码
7. 客户查询接口实现

  1. @RestController
  2. @RequestMapping("/api/customers")
  3. public class CustomerController {
  4.    
  5.     @Autowired
  6.     private CustomerService customerService;
  7.    
  8.     @Autowired
  9.     private VehicleService vehicleService;
  10.    
  11.     @Autowired
  12.     private PointsService pointsService;
  13.    
  14.     @PostMapping
  15.     public Result<CustomerResponse> createCustomer(@RequestBody @Valid CustomerDTO dto) {
  16.         CustomerResponse response = customerService.createCustomer(dto);
  17.         return Result.success(response);
  18.     }
  19.    
  20.     @PutMapping("/{id}")
  21.     public Result<Void> updateCustomer(
  22.             @PathVariable Long id,
  23.             @RequestBody @Valid CustomerUpdateDTO dto) {
  24.         customerService.updateCustomer(id, dto);
  25.         return Result.success();
  26.     }
  27.    
  28.     @GetMapping("/{id}")
  29.     public Result<CustomerDetailResponse> getCustomerDetail(@PathVariable Long id) {
  30.         CustomerDetailResponse detail = customerService.getCustomerDetail(id);
  31.         return Result.success(detail);
  32.     }
  33.    
  34.     @PostMapping("/{id}/vehicles")
  35.     public Result<VehicleResponse> addVehicle(
  36.             @PathVariable Long id,
  37.             @RequestBody @Valid VehicleDTO dto) {
  38.         dto.setCustomerId(id);
  39.         VehicleResponse response = vehicleService.addVehicle(dto);
  40.         return Result.success(response);
  41.     }
  42.    
  43.     @PostMapping("/{id}/points/add")
  44.     public Result<Void> addPoints(
  45.             @PathVariable Long id,
  46.             @RequestBody @Valid PointsAddDTO dto) {
  47.         dto.setCustomerId(id);
  48.         pointsService.addPoints(dto);
  49.         return Result.success();
  50.     }
  51.    
  52.     @GetMapping("/{id}/points/statistics")
  53.     public Result<PointsStatisticsResponse> getPointsStatistics(@PathVariable Long id) {
  54.         PointsStatisticsResponse statistics = pointsService.getPointsStatistics(id);
  55.         return Result.success(statistics);
  56.     }
  57.    
  58.     @GetMapping("/{id}/service-records")
  59.     public Result<Page<ServiceRecordVO>> getServiceRecords(
  60.             @PathVariable Long id,
  61.             ServiceRecordQueryDTO query) {
  62.         query.setCustomerId(id);
  63.         Page<ServiceRecordVO> page = serviceRecordQueryService.queryServiceRecords(query);
  64.         return Result.success(page);
  65.     }
  66. }
复制代码
这些代码实现了客户管理的核心功能,包罗:

  • 客户信息的CRUD操作
  • 车辆信息管理
  • 维修记录查询
  • 积分管理和品级盘算
  • 统计分析功能
关键特点:


  • 完整的客户生命周期管理
  • 车辆信息关联
  • 维修记录追踪
  • 积分变动记录
  • 客户品级自动盘算
  • 保养提示功能
员工管理模块的核心代码实现

1. 数据库设计

  1. -- 员工信息表
  2. CREATE TABLE employee (
  3.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  4.     code VARCHAR(32) UNIQUE NOT NULL COMMENT '员工编号',
  5.     name VARCHAR(50) NOT NULL COMMENT '姓名',
  6.     gender TINYINT NOT NULL COMMENT '性别: 0-女 1-男',
  7.     id_card VARCHAR(18) UNIQUE NOT NULL COMMENT '身份证号',
  8.     phone VARCHAR(20) NOT NULL COMMENT '联系电话',
  9.     email VARCHAR(100) COMMENT '邮箱',
  10.     address TEXT COMMENT '住址',
  11.     job_type_id BIGINT NOT NULL COMMENT '工种ID',
  12.     department_id BIGINT NOT NULL COMMENT '部门ID',
  13.     entry_date DATE NOT NULL COMMENT '入职日期',
  14.     leave_date DATE COMMENT '离职日期',
  15.     status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 0-离职 1-在职',
  16.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  17.     updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  18. );
  19. -- 工种分类表
  20. CREATE TABLE job_type (
  21.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  22.     name VARCHAR(50) NOT NULL COMMENT '工种名称',
  23.     description TEXT COMMENT '工种描述',
  24.     base_salary DECIMAL(10,2) NOT NULL COMMENT '基本工资',
  25.     commission_rate DECIMAL(5,2) COMMENT '提成比例',
  26.     status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 0-禁用 1-启用',
  27.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  28. );
  29. -- 工作量记录表
  30. CREATE TABLE work_record (
  31.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  32.     employee_id BIGINT NOT NULL COMMENT '员工ID',
  33.     work_order_id BIGINT NOT NULL COMMENT '工单ID',
  34.     service_item_id BIGINT NOT NULL COMMENT '服务项目ID',
  35.     work_hours DECIMAL(5,2) NOT NULL COMMENT '工时',
  36.     amount DECIMAL(10,2) NOT NULL COMMENT '金额',
  37.     commission DECIMAL(10,2) NOT NULL COMMENT '提成金额',
  38.     work_date DATE NOT NULL COMMENT '工作日期',
  39.     status TINYINT NOT NULL DEFAULT 1 COMMENT '状态',
  40.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  41.     FOREIGN KEY (employee_id) REFERENCES employee(id)
  42. );
  43. -- 绩效考核表
  44. CREATE TABLE performance_evaluation (
  45.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  46.     employee_id BIGINT NOT NULL COMMENT '员工ID',
  47.     evaluation_month VARCHAR(7) NOT NULL COMMENT '考核月份 YYYY-MM',
  48.     work_quality_score INT NOT NULL COMMENT '工作质量得分',
  49.     work_attitude_score INT NOT NULL COMMENT '工作态度得分',
  50.     customer_feedback_score INT NOT NULL COMMENT '客户反馈得分',
  51.     total_score INT NOT NULL COMMENT '总分',
  52.     evaluator_id BIGINT NOT NULL COMMENT '评估人ID',
  53.     evaluation_date DATE NOT NULL COMMENT '评估日期',
  54.     remark TEXT COMMENT '评语',
  55.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  56.     FOREIGN KEY (employee_id) REFERENCES employee(id),
  57.     UNIQUE KEY `uk_employee_month` (`employee_id`, `evaluation_month`)
  58. );
  59. -- 考核指标表
  60. CREATE TABLE evaluation_criteria (
  61.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  62.     name VARCHAR(50) NOT NULL COMMENT '指标名称',
  63.     category VARCHAR(50) NOT NULL COMMENT '指标类别',
  64.     description TEXT COMMENT '指标描述',
  65.     weight INT NOT NULL COMMENT '权重',
  66.     max_score INT NOT NULL COMMENT '最高分',
  67.     status TINYINT NOT NULL DEFAULT 1 COMMENT '状态',
  68.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  69. );
复制代码
2. 实体类设计

  1. @Data
  2. @Entity
  3. @Table(name = "employee")
  4. public class Employee {
  5.     @Id
  6.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  7.     private Long id;
  8.    
  9.     private String code;
  10.     private String name;
  11.     private Integer gender;
  12.     private String idCard;
  13.     private String phone;
  14.     private String email;
  15.     private String address;
  16.     private Long jobTypeId;
  17.     private Long departmentId;
  18.     private LocalDate entryDate;
  19.     private LocalDate leaveDate;
  20.     private Integer status;
  21.    
  22.     @ManyToOne
  23.     @JoinColumn(name = "job_type_id", insertable = false, updatable = false)
  24.     private JobType jobType;
  25. }
  26. @Data
  27. @Entity
  28. @Table(name = "job_type")
  29. public class JobType {
  30.     @Id
  31.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  32.     private Long id;
  33.    
  34.     private String name;
  35.     private String description;
  36.     private BigDecimal baseSalary;
  37.     private BigDecimal commissionRate;
  38.     private Integer status;
  39. }
  40. @Data
  41. @Entity
  42. @Table(name = "performance_evaluation")
  43. public class PerformanceEvaluation {
  44.     @Id
  45.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  46.     private Long id;
  47.    
  48.     private Long employeeId;
  49.     private String evaluationMonth;
  50.     private Integer workQualityScore;
  51.     private Integer workAttitudeScore;
  52.     private Integer customerFeedbackScore;
  53.     private Integer totalScore;
  54.     private Long evaluatorId;
  55.     private LocalDate evaluationDate;
  56.     private String remark;
  57. }
复制代码
3. 员工服务实现

  1. @Service
  2. @Transactional
  3. public class EmployeeService {
  4.    
  5.     @Autowired
  6.     private EmployeeRepository employeeRepository;
  7.    
  8.     @Autowired
  9.     private SequenceGenerator sequenceGenerator;
  10.    
  11.     public EmployeeResponse createEmployee(EmployeeDTO dto) {
  12.         // 1. 验证身份证号是否已存在
  13.         validateIdCard(dto.getIdCard());
  14.         
  15.         // 2. 生成员工编号
  16.         String code = sequenceGenerator.generateEmployeeCode();
  17.         
  18.         // 3. 创建员工信息
  19.         Employee employee = new Employee();
  20.         BeanUtils.copyProperties(dto, employee);
  21.         employee.setCode(code);
  22.         employee.setStatus(1);
  23.         
  24.         // 4. 保存员工信息
  25.         employee = employeeRepository.save(employee);
  26.         
  27.         // 5. 创建系统账号
  28.         createUserAccount(employee);
  29.         
  30.         return buildResponse(employee);
  31.     }
  32.    
  33.     public void updateEmployee(Long id, EmployeeUpdateDTO dto) {
  34.         Employee employee = employeeRepository.findById(id)
  35.             .orElseThrow(() -> new BusinessException("员工不存在"));
  36.             
  37.         // 1. 如果修改身份证号,需要验证唯一性
  38.         if (!employee.getIdCard().equals(dto.getIdCard())) {
  39.             validateIdCard(dto.getIdCard());
  40.         }
  41.         
  42.         // 2. 更新员工信息
  43.         BeanUtils.copyProperties(dto, employee);
  44.         employeeRepository.save(employee);
  45.     }
  46.    
  47.     public void handleEmployeeResignation(Long id, ResignationDTO dto) {
  48.         Employee employee = employeeRepository.findById(id)
  49.             .orElseThrow(() -> new BusinessException("员工不存在"));
  50.             
  51.         // 1. 设置离职信息
  52.         employee.setLeaveDate(dto.getLeaveDate());
  53.         employee.setStatus(0);
  54.         
  55.         // 2. 更新员工状态
  56.         employeeRepository.save(employee);
  57.         
  58.         // 3. 处理相关系统账号
  59.         disableUserAccount(employee.getCode());
  60.         
  61.         // 4. 记录离职信息
  62.         saveResignationRecord(employee, dto);
  63.     }
  64.    
  65.     private void createUserAccount(Employee employee) {
  66.         UserCreateDTO userDto = UserCreateDTO.builder()
  67.             .username(employee.getCode())
  68.             .name(employee.getName())
  69.             .phone(employee.getPhone())
  70.             .email(employee.getEmail())
  71.             .roleIds(getRolesByJobType(employee.getJobTypeId()))
  72.             .build();
  73.             
  74.         userService.createUser(userDto);
  75.     }
  76. }
复制代码
4. 工种管理服务实现

  1. @Service
  2. @Transactional
  3. public class JobTypeService {
  4.    
  5.     @Autowired
  6.     private JobTypeRepository jobTypeRepository;
  7.    
  8.     public JobTypeResponse createJobType(JobTypeDTO dto) {
  9.         // 1. 验证工种名称是否已存在
  10.         validateJobTypeName(dto.getName());
  11.         
  12.         // 2. 创建工种信息
  13.         JobType jobType = new JobType();
  14.         BeanUtils.copyProperties(dto, jobType);
  15.         jobType.setStatus(1);
  16.         
  17.         // 3. 保存工种信息
  18.         jobType = jobTypeRepository.save(jobType);
  19.         
  20.         return buildResponse(jobType);
  21.     }
  22.    
  23.     public void updateJobType(Long id, JobTypeUpdateDTO dto) {
  24.         JobType jobType = jobTypeRepository.findById(id)
  25.             .orElseThrow(() -> new BusinessException("工种不存在"));
  26.             
  27.         // 1. 如果修改名称,需要验证唯一性
  28.         if (!jobType.getName().equals(dto.getName())) {
  29.             validateJobTypeName(dto.getName());
  30.         }
  31.         
  32.         // 2. 更新工种信息
  33.         BeanUtils.copyProperties(dto, jobType);
  34.         jobTypeRepository.save(jobType);
  35.     }
  36.    
  37.     public void updateCommissionRate(Long id, BigDecimal newRate) {
  38.         JobType jobType = jobTypeRepository.findById(id)
  39.             .orElseThrow(() -> new BusinessException("工种不存在"));
  40.             
  41.         // 1. 验证提成比例
  42.         if (newRate.compareTo(BigDecimal.ZERO) < 0 ||
  43.             newRate.compareTo(BigDecimal.valueOf(100)) > 0) {
  44.             throw new BusinessException("提成比例必须在0-100之间");
  45.         }
  46.         
  47.         // 2. 更新提成比例
  48.         jobType.setCommissionRate(newRate);
  49.         jobTypeRepository.save(jobType);
  50.     }
  51. }
复制代码
5. 工作量统计服务实现

  1. @Service
  2. public class WorkloadStatisticsService {
  3.    
  4.     @Autowired
  5.     private WorkRecordRepository workRecordRepository;
  6.    
  7.     public WorkloadStatisticsResponse getEmployeeWorkload(
  8.             Long employeeId, LocalDate startDate, LocalDate endDate) {
  9.         // 1. 获取工作量汇总
  10.         WorkloadSummaryVO summary = calculateWorkloadSummary(employeeId, startDate, endDate);
  11.         
  12.         // 2. 获取每日工作量
  13.         List<DailyWorkloadVO> dailyWorkloads =
  14.             calculateDailyWorkload(employeeId, startDate, endDate);
  15.         
  16.         // 3. 获取项目分布
  17.         List<ServiceItemDistributionVO> itemDistribution =
  18.             calculateServiceItemDistribution(employeeId, startDate, endDate);
  19.         
  20.         return WorkloadStatisticsResponse.builder()
  21.             .summary(summary)
  22.             .dailyWorkloads(dailyWorkloads)
  23.             .itemDistribution(itemDistribution)
  24.             .build();
  25.     }
  26.    
  27.     public Page<WorkRecordVO> queryWorkRecords(WorkRecordQueryDTO query) {
  28.         // 1. 构建查询条件
  29.         Specification<WorkRecord> spec = buildSpecification(query);
  30.         
  31.         // 2. 创建分页对象
  32.         PageRequest pageRequest = PageRequest.of(
  33.             query.getPageNum(),
  34.             query.getPageSize(),
  35.             Sort.by(Sort.Direction.DESC, "workDate")
  36.         );
  37.         
  38.         // 3. 执行查询
  39.         Page<WorkRecord> page = workRecordRepository.findAll(spec, pageRequest);
  40.         
  41.         // 4. 转换响应
  42.         return page.map(this::convertToVO);
  43.     }
  44.    
  45.     private WorkloadSummaryVO calculateWorkloadSummary(
  46.             Long employeeId, LocalDate startDate, LocalDate endDate) {
  47.         // 1. 计算总工时
  48.         BigDecimal totalHours = workRecordRepository
  49.             .sumWorkHours(employeeId, startDate, endDate);
  50.             
  51.         // 2. 计算总金额
  52.         BigDecimal totalAmount = workRecordRepository
  53.             .sumAmount(employeeId, startDate, endDate);
  54.             
  55.         // 3. 计算总提成
  56.         BigDecimal totalCommission = workRecordRepository
  57.             .sumCommission(employeeId, startDate, endDate);
  58.             
  59.         // 4. 计算完成工单数
  60.         Long orderCount = workRecordRepository
  61.             .countWorkOrders(employeeId, startDate, endDate);
  62.             
  63.         return WorkloadSummaryVO.builder()
  64.             .totalHours(totalHours)
  65.             .totalAmount(totalAmount)
  66.             .totalCommission(totalCommission)
  67.             .orderCount(orderCount)
  68.             .build();
  69.     }
  70. }
复制代码
6. 绩效考核服务实现

  1. @Service
  2. @Transactional
  3. public class PerformanceEvaluationService {
  4.    
  5.     @Autowired
  6.     private PerformanceEvaluationRepository evaluationRepository;
  7.    
  8.     @Autowired
  9.     private EvaluationCriteriaRepository criteriaRepository;
  10.    
  11.     public void createEvaluation(PerformanceEvaluationDTO dto) {
  12.         // 1. 验证是否已存在当月考核
  13.         validateMonthlyEvaluation(dto.getEmployeeId(), dto.getEvaluationMonth());
  14.         
  15.         // 2. 计算总分
  16.         int totalScore = calculateTotalScore(dto);
  17.         
  18.         // 3. 创建考核记录
  19.         PerformanceEvaluation evaluation = new PerformanceEvaluation();
  20.         BeanUtils.copyProperties(dto, evaluation);
  21.         evaluation.setTotalScore(totalScore);
  22.         evaluation.setEvaluationDate(LocalDate.now());
  23.         evaluation.setEvaluatorId(SecurityUtils.getCurrentUserId());
  24.         
  25.         // 4. 保存考核记录
  26.         evaluationRepository.save(evaluation);
  27.         
  28.         // 5. 处理绩效奖金
  29.         handlePerformanceBonus(evaluation);
  30.     }
  31.    
  32.     public PerformanceStatisticsResponse getPerformanceStatistics(
  33.             Long employeeId, String startMonth, String endMonth) {
  34.         // 1. 获取考核汇总
  35.         PerformanceSummaryVO summary =
  36.             calculatePerformanceSummary(employeeId, startMonth, endMonth);
  37.         
  38.         // 2. 获取月度考核趋势
  39.         List<MonthlyPerformanceVO> monthlyTrend =
  40.             calculateMonthlyTrend(employeeId, startMonth, endMonth);
  41.         
  42.         // 3. 获取各项得分分布
  43.         List<ScoreDistributionVO> scoreDistribution =
  44.             calculateScoreDistribution(employeeId, startMonth, endMonth);
  45.         
  46.         return PerformanceStatisticsResponse.builder()
  47.             .summary(summary)
  48.             .monthlyTrend(monthlyTrend)
  49.             .scoreDistribution(scoreDistribution)
  50.             .build();
  51.     }
  52.    
  53.     private void handlePerformanceBonus(PerformanceEvaluation evaluation) {
  54.         // 1. 获取员工信息
  55.         Employee employee = employeeRepository.findById(evaluation.getEmployeeId())
  56.             .orElseThrow();
  57.             
  58.         // 2. 获取工种信息
  59.         JobType jobType = jobTypeRepository.findById(employee.getJobTypeId())
  60.             .orElseThrow();
  61.             
  62.         // 3. 计算绩效奖金
  63.         BigDecimal bonus = calculatePerformanceBonus(
  64.             evaluation.getTotalScore(),
  65.             jobType.getBaseSalary()
  66.         );
  67.         
  68.         // 4. 保存奖金记录
  69.         saveBonusRecord(evaluation, bonus);
  70.     }
  71.    
  72.     private int calculateTotalScore(PerformanceEvaluationDTO dto) {
  73.         // 1. 获取考核指标权重
  74.         Map<String, Integer> weights = getEvaluationWeights();
  75.         
  76.         // 2. 计算加权总分
  77.         return dto.getWorkQualityScore() * weights.get("QUALITY") / 100 +
  78.                dto.getWorkAttitudeScore() * weights.get("ATTITUDE") / 100 +
  79.                dto.getCustomerFeedbackScore() * weights.get("FEEDBACK") / 100;
  80.     }
  81. }
复制代码
7. 员工查询接口实现

  1. @RestController
  2. @RequestMapping("/api/employees")
  3. public class EmployeeController {
  4.    
  5.     @Autowired
  6.     private EmployeeService employeeService;
  7.    
  8.     @Autowired
  9.     private WorkloadStatisticsService workloadService;
  10.    
  11.     @Autowired
  12.     private PerformanceEvaluationService performanceService;
  13.    
  14.     @PostMapping
  15.     public Result<EmployeeResponse> createEmployee(@RequestBody @Valid EmployeeDTO dto) {
  16.         EmployeeResponse response = employeeService.createEmployee(dto);
  17.         return Result.success(response);
  18.     }
  19.    
  20.     @PutMapping("/{id}")
  21.     public Result<Void> updateEmployee(
  22.             @PathVariable Long id,
  23.             @RequestBody @Valid EmployeeUpdateDTO dto) {
  24.         employeeService.updateEmployee(id, dto);
  25.         return Result.success();
  26.     }
  27.    
  28.     @PostMapping("/{id}/resignation")
  29.     public Result<Void> handleResignation(
  30.             @PathVariable Long id,
  31.             @RequestBody @Valid ResignationDTO dto) {
  32.         employeeService.handleEmployeeResignation(id, dto);
  33.         return Result.success();
  34.     }
  35.    
  36.     @GetMapping("/{id}/workload")
  37.     public Result<WorkloadStatisticsResponse> getWorkloadStatistics(
  38.             @PathVariable Long id,
  39.             @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
  40.             @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
  41.         WorkloadStatisticsResponse statistics =
  42.             workloadService.getEmployeeWorkload(id, startDate, endDate);
  43.         return Result.success(statistics);
  44.     }
  45.    
  46.     @PostMapping("/{id}/performance-evaluation")
  47.     public Result<Void> createPerformanceEvaluation(
  48.             @PathVariable Long id,
  49.             @RequestBody @Valid PerformanceEvaluationDTO dto) {
  50.         dto.setEmployeeId(id);
  51.         performanceService.createEvaluation(dto);
  52.         return Result.success();
  53.     }
  54.    
  55.     @GetMapping("/{id}/performance-statistics")
  56.     public Result<PerformanceStatisticsResponse> getPerformanceStatistics(
  57.             @PathVariable Long id,
  58.             @RequestParam String startMonth,
  59.             @RequestParam String endMonth) {
  60.         PerformanceStatisticsResponse statistics =
  61.             performanceService.getPerformanceStatistics(id, startMonth, endMonth);
  62.         return Result.success(statistics);
  63.     }
  64. }
复制代码
这些代码实现了员工管理的核心功能,包罗:

  • 员工信息的CRUD操作
  • 工种分类管理
  • 工作量统计分析
  • 绩效考核管理
关键特点:


  • 完整的员工生命周期管理
  • 灵活的工种配置
  • 具体的工作量记录
  • 多维度的绩效考核
  • 自动化的提成盘算
  • 完满的统计分析功能
财务管理模块的核心代码实现

1. 数据库设计

  1. -- 财务收支记录表
  2. CREATE TABLE financial_transaction (
  3.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  4.     transaction_no VARCHAR(32) UNIQUE NOT NULL COMMENT '交易编号',
  5.     type VARCHAR(20) NOT NULL COMMENT '交易类型: INCOME/EXPENSE',
  6.     category_id BIGINT NOT NULL COMMENT '类别ID',
  7.     amount DECIMAL(12,2) NOT NULL COMMENT '金额',
  8.     payment_method VARCHAR(20) NOT NULL COMMENT '支付方式',
  9.     transaction_date DATE NOT NULL COMMENT '交易日期',
  10.     reference_no VARCHAR(32) COMMENT '关联单号',
  11.     reference_type VARCHAR(20) COMMENT '关联单据类型',
  12.     operator_id BIGINT NOT NULL COMMENT '操作人',
  13.     remark TEXT COMMENT '备注',
  14.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  15. );
  16. -- 收支类别表
  17. CREATE TABLE transaction_category (
  18.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  19.     name VARCHAR(50) NOT NULL COMMENT '类别名称',
  20.     type VARCHAR(20) NOT NULL COMMENT '类型: INCOME/EXPENSE',
  21.     parent_id BIGINT COMMENT '父类别ID',
  22.     status TINYINT NOT NULL DEFAULT 1 COMMENT '状态',
  23.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  24. );
  25. -- 成本记录表
  26. CREATE TABLE cost_record (
  27.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  28.     cost_type VARCHAR(20) NOT NULL COMMENT '成本类型',
  29.     category_id BIGINT NOT NULL COMMENT '类别ID',
  30.     amount DECIMAL(12,2) NOT NULL COMMENT '金额',
  31.     record_month VARCHAR(7) NOT NULL COMMENT '记录月份 YYYY-MM',
  32.     remark TEXT COMMENT '备注',
  33.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  34. );
  35. -- 利润核算表
  36. CREATE TABLE profit_statement (
  37.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  38.     statement_month VARCHAR(7) NOT NULL COMMENT '核算月份 YYYY-MM',
  39.     total_revenue DECIMAL(12,2) NOT NULL COMMENT '总收入',
  40.     total_cost DECIMAL(12,2) NOT NULL COMMENT '总成本',
  41.     gross_profit DECIMAL(12,2) NOT NULL COMMENT '毛利润',
  42.     operating_expenses DECIMAL(12,2) NOT NULL COMMENT '运营费用',
  43.     net_profit DECIMAL(12,2) NOT NULL COMMENT '净利润',
  44.     status VARCHAR(20) NOT NULL COMMENT '状态',
  45.     created_by BIGINT NOT NULL COMMENT '创建人',
  46.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  47.     UNIQUE KEY `uk_month` (`statement_month`)
  48. );
  49. -- 收入明细表
  50. CREATE TABLE revenue_detail (
  51.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  52.     statement_id BIGINT NOT NULL COMMENT '利润表ID',
  53.     category_id BIGINT NOT NULL COMMENT '收入类别ID',
  54.     amount DECIMAL(12,2) NOT NULL COMMENT '金额',
  55.     percentage DECIMAL(5,2) NOT NULL COMMENT '占比',
  56.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  57.     FOREIGN KEY (statement_id) REFERENCES profit_statement(id)
  58. );
  59. -- 成本明细表
  60. CREATE TABLE cost_detail (
  61.     id BIGINT PRIMARY KEY AUTO_INCREMENT,
  62.     statement_id BIGINT NOT NULL COMMENT '利润表ID',
  63.     category_id BIGINT NOT NULL COMMENT '成本类别ID',
  64.     amount DECIMAL(12,2) NOT NULL COMMENT '金额',
  65.     percentage DECIMAL(5,2) NOT NULL COMMENT '占比',
  66.     created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  67.     FOREIGN KEY (statement_id) REFERENCES profit_statement(id)
  68. );
复制代码
2. 实体类设计

  1. @Data
  2. @Entity
  3. @Table(name = "financial_transaction")
  4. public class FinancialTransaction {
  5.     @Id
  6.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  7.     private Long id;
  8.    
  9.     private String transactionNo;
  10.    
  11.     @Enumerated(EnumType.STRING)
  12.     private TransactionType type;
  13.    
  14.     private Long categoryId;
  15.     private BigDecimal amount;
  16.    
  17.     @Enumerated(EnumType.STRING)
  18.     private PaymentMethod paymentMethod;
  19.    
  20.     private LocalDate transactionDate;
  21.     private String referenceNo;
  22.     private String referenceType;
  23.     private Long operatorId;
  24.     private String remark;
  25.    
  26.     @ManyToOne
  27.     @JoinColumn(name = "category_id", insertable = false, updatable = false)
  28.     private TransactionCategory category;
  29. }
  30. @Data
  31. @Entity
  32. @Table(name = "profit_statement")
  33. public class ProfitStatement {
  34.     @Id
  35.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  36.     private Long id;
  37.    
  38.     private String statementMonth;
  39.     private BigDecimal totalRevenue;
  40.     private BigDecimal totalCost;
  41.     private BigDecimal grossProfit;
  42.     private BigDecimal operatingExpenses;
  43.     private BigDecimal netProfit;
  44.    
  45.     @Enumerated(EnumType.STRING)
  46.     private StatementStatus status;
  47.    
  48.     private Long createdBy;
  49.    
  50.     @OneToMany(mappedBy = "statement", cascade = CascadeType.ALL)
  51.     private List<RevenueDetail> revenueDetails;
  52.    
  53.     @OneToMany(mappedBy = "statement", cascade = CascadeType.ALL)
  54.     private List<CostDetail> costDetails;
  55. }
复制代码
3. 财务买卖业务服务实现

  1. @Service
  2. @Transactional
  3. public class FinancialTransactionService {
  4.    
  5.     @Autowired
  6.     private FinancialTransactionRepository transactionRepository;
  7.    
  8.     @Autowired
  9.     private SequenceGenerator sequenceGenerator;
  10.    
  11.     public TransactionResponse recordTransaction(TransactionDTO dto) {
  12.         // 1. 生成交易编号
  13.         String transactionNo = sequenceGenerator.generateTransactionNo();
  14.         
  15.         // 2. 创建交易记录
  16.         FinancialTransaction transaction = new FinancialTransaction();
  17.         BeanUtils.copyProperties(dto, transaction);
  18.         transaction.setTransactionNo(transactionNo);
  19.         transaction.setOperatorId(SecurityUtils.getCurrentUserId());
  20.         
  21.         // 3. 保存交易记录
  22.         transaction = transactionRepository.save(transaction);
  23.         
  24.         // 4. 更新相关统计数据
  25.         updateStatistics(transaction);
  26.         
  27.         return buildResponse(transaction);
  28.     }
  29.    
  30.     public Page<TransactionVO> queryTransactions(TransactionQueryDTO query) {
  31.         // 1. 构建查询条件
  32.         Specification<FinancialTransaction> spec = buildSpecification(query);
  33.         
  34.         // 2. 创建分页对象
  35.         PageRequest pageRequest = PageRequest.of(
  36.             query.getPageNum(),
  37.             query.getPageSize(),
  38.             Sort.by(Sort.Direction.DESC, "transactionDate")
  39.         );
  40.         
  41.         // 3. 执行查询
  42.         Page<FinancialTransaction> page = transactionRepository.findAll(spec, pageRequest);
  43.         
  44.         // 4. 转换响应
  45.         return page.map(this::convertToVO);
  46.     }
  47.    
  48.     public TransactionStatisticsResponse getStatistics(
  49.             LocalDate startDate, LocalDate endDate) {
  50.         // 1. 获取收入统计
  51.         List<CategoryStatisticsVO> incomeStats =
  52.             calculateCategoryStatistics(TransactionType.INCOME, startDate, endDate);
  53.         
  54.         // 2. 获取支出统计
  55.         List<CategoryStatisticsVO> expenseStats =
  56.             calculateCategoryStatistics(TransactionType.EXPENSE, startDate, endDate);
  57.         
  58.         // 3. 获取支付方式统计
  59.         List<PaymentMethodStatisticsVO> paymentStats =
  60.             calculatePaymentMethodStatistics(startDate, endDate);
  61.         
  62.         return TransactionStatisticsResponse.builder()
  63.             .incomeStatistics(incomeStats)
  64.             .expenseStatistics(expenseStats)
  65.             .paymentMethodStatistics(paymentStats)
  66.             .build();
  67.     }
  68.    
  69.     private void updateStatistics(FinancialTransaction transaction) {
  70.         // 1. 更新日统计
  71.         updateDailyStatistics(transaction);
  72.         
  73.         // 2. 更新月统计
  74.         updateMonthlyStatistics(transaction);
  75.         
  76.         // 3. 更新类别统计
  77.         updateCategoryStatistics(transaction);
  78.     }
  79. }
复制代码
4. 营收报表服务实现

  1. @Service
  2. public class RevenueReportService {
  3.    
  4.     @Autowired
  5.     private FinancialTransactionRepository transactionRepository;
  6.    
  7.     public RevenueReportResponse generateMonthlyReport(String month) {
  8.         // 1. 获取收入汇总
  9.         RevenueSummaryVO summary = calculateRevenueSummary(month);
  10.         
  11.         // 2. 获取收入趋势
  12.         List<DailyRevenueVO> dailyTrend = calculateDailyRevenue(month);
  13.         
  14.         // 3. 获取收入构成
  15.         List<RevenueCategoryVO> categoryDistribution =
  16.             calculateCategoryDistribution(month);
  17.         
  18.         // 4. 获取同比环比数据
  19.         ComparisonDataVO comparison = calculateComparison(month);
  20.         
  21.         return RevenueReportResponse.builder()
  22.             .summary(summary)
  23.             .dailyTrend(dailyTrend)
  24.             .categoryDistribution(categoryDistribution)
  25.             .comparison(comparison)
  26.             .build();
  27.     }
  28.    
  29.     private RevenueSummaryVO calculateRevenueSummary(String month) {
  30.         // 1. 计算总收入
  31.         BigDecimal totalRevenue = transactionRepository
  32.             .sumByTypeAndMonth(TransactionType.INCOME, month);
  33.             
  34.         // 2. 计算服务收入
  35.         BigDecimal serviceRevenue = transactionRepository
  36.             .sumByCategoryAndMonth(Arrays.asList(1L, 2L), month);
  37.             
  38.         // 3. 计算配件收入
  39.         BigDecimal partsRevenue = transactionRepository
  40.             .sumByCategoryAndMonth(Arrays.asList(3L), month);
  41.             
  42.         // 4. 计算其他收入
  43.         BigDecimal otherRevenue = totalRevenue
  44.             .subtract(serviceRevenue)
  45.             .subtract(partsRevenue);
  46.             
  47.         return RevenueSummaryVO.builder()
  48.             .totalRevenue(totalRevenue)
  49.             .serviceRevenue(serviceRevenue)
  50.             .partsRevenue(partsRevenue)
  51.             .otherRevenue(otherRevenue)
  52.             .build();
  53.     }
  54. }
复制代码
5. 成本分析服务实现

  1. @Service
  2. public class CostAnalysisService {
  3.    
  4.     @Autowired
  5.     private CostRecordRepository costRecordRepository;
  6.    
  7.     public CostAnalysisResponse analyzeMonthlyCost(String month) {
  8.         // 1. 获取成本汇总
  9.         CostSummaryVO summary = calculateCostSummary(month);
  10.         
  11.         // 2. 获取成本构成
  12.         List<CostCategoryVO> categoryAnalysis = analyzeCostCategory(month);
  13.         
  14.         // 3. 获取成本趋势
  15.         List<MonthlyCostTrendVO> costTrend = analyzeCostTrend(month);
  16.         
  17.         // 4. 计算成本比率
  18.         List<CostRatioVO> costRatios = calculateCostRatios(month);
  19.         
  20.         return CostAnalysisResponse.builder()
  21.             .summary(summary)
  22.             .categoryAnalysis(categoryAnalysis)
  23.             .costTrend(costTrend)
  24.             .costRatios(costRatios)
  25.             .build();
  26.     }
  27.    
  28.     private List<CostRatioVO> calculateCostRatios(String month) {
  29.         List<CostRatioVO> ratios = new ArrayList<>();
  30.         
  31.         // 1. 获取总收入
  32.         BigDecimal totalRevenue = revenueService.calculateMonthlyRevenue(month);
  33.         
  34.         // 2. 获取各类成本
  35.         Map<String, BigDecimal> costMap = costRecordRepository
  36.             .getCostsByTypeAndMonth(month);
  37.             
  38.         // 3. 计算各项成本比率
  39.         for (Map.Entry<String, BigDecimal> entry : costMap.entrySet()) {
  40.             BigDecimal ratio = BigDecimal.ZERO;
  41.             if (totalRevenue.compareTo(BigDecimal.ZERO) > 0) {
  42.                 ratio = entry.getValue()
  43.                     .divide(totalRevenue, 4, RoundingMode.HALF_UP)
  44.                     .multiply(BigDecimal.valueOf(100));
  45.             }
  46.             
  47.             ratios.add(new CostRatioVO(
  48.                 entry.getKey(),
  49.                 entry.getValue(),
  50.                 ratio
  51.             ));
  52.         }
  53.         
  54.         return ratios;
  55.     }
  56. }
复制代码
6. 利润核算服务实现

  1. @Service
  2. @Transactional
  3. public class ProfitStatementService {
  4.    
  5.     @Autowired
  6.     private ProfitStatementRepository statementRepository;
  7.    
  8.     @Autowired
  9.     private RevenueReportService revenueService;
  10.    
  11.     @Autowired
  12.     private CostAnalysisService costService;
  13.    
  14.     public void generateMonthlyStatement(String month) {
  15.         // 1. 验证月份是否已生成报表
  16.         validateMonth(month);
  17.         
  18.         // 2. 创建利润表
  19.         ProfitStatement statement = new ProfitStatement();
  20.         statement.setStatementMonth(month);
  21.         statement.setStatus(StatementStatus.DRAFT);
  22.         statement.setCreatedBy(SecurityUtils.getCurrentUserId());
  23.         
  24.         // 3. 计算收入数据
  25.         calculateRevenue(statement);
  26.         
  27.         // 4. 计算成本数据
  28.         calculateCost(statement);
  29.         
  30.         // 5. 计算利润数据
  31.         calculateProfit(statement);
  32.         
  33.         // 6. 保存利润表
  34.         statement = statementRepository.save(statement);
  35.         
  36.         // 7. 生成明细数据
  37.         generateDetails(statement);
  38.     }
  39.    
  40.     public void approveStatement(Long id) {
  41.         ProfitStatement statement = statementRepository.findById(id)
  42.             .orElseThrow(() -> new BusinessException("利润表不存在"));
  43.             
  44.         // 1. 验证状态
  45.         if (statement.getStatus() != StatementStatus.DRAFT) {
  46.             throw new BusinessException("只有草稿状态的利润表可以审批");
  47.         }
  48.         
  49.         // 2. 更新状态
  50.         statement.setStatus(StatementStatus.APPROVED);
  51.         statementRepository.save(statement);
  52.         
  53.         // 3. 生成财务凭证
  54.         generateVoucher(statement);
  55.     }
  56.    
  57.     public ProfitAnalysisResponse analyzeProfitTrend(
  58.             String startMonth, String endMonth) {
  59.         // 1. 获取利润趋势
  60.         List<MonthlyProfitVO> profitTrend =
  61.             calculateProfitTrend(startMonth, endMonth);
  62.         
  63.         // 2. 计算利润率
  64.         List<ProfitRatioVO> profitRatios =
  65.             calculateProfitRatios(startMonth, endMonth);
  66.         
  67.         // 3. 计算同比数据
  68.         List<YearOverYearVO> yearOverYear =
  69.             calculateYearOverYear(startMonth, endMonth);
  70.         
  71.         return ProfitAnalysisResponse.builder()
  72.             .profitTrend(profitTrend)
  73.             .profitRatios(profitRatios)
  74.             .yearOverYear(yearOverYear)
  75.             .build();
  76.     }
  77.    
  78.     private void calculateProfit(ProfitStatement statement) {
  79.         // 1. 计算毛利润
  80.         BigDecimal grossProfit = statement.getTotalRevenue()
  81.             .subtract(statement.getTotalCost());
  82.         statement.setGrossProfit(grossProfit);
  83.         
  84.         // 2. 计算净利润
  85.         BigDecimal netProfit = grossProfit
  86.             .subtract(statement.getOperatingExpenses());
  87.         statement.setNetProfit(netProfit);
  88.     }
  89. }
复制代码
7. 财务报表接口实现

  1. @RestController
  2. @RequestMapping("/api/finance")
  3. public class FinanceController {
  4.    
  5.     @Autowired
  6.     private FinancialTransactionService transactionService;
  7.    
  8.     @Autowired
  9.     private RevenueReportService revenueService;
  10.    
  11.     @Autowired
  12.     private CostAnalysisService costService;
  13.    
  14.     @Autowired
  15.     private ProfitStatementService profitService;
  16.    
  17.     @PostMapping("/transactions")
  18.     public Result<TransactionResponse> recordTransaction(
  19.             @RequestBody @Valid TransactionDTO dto) {
  20.         TransactionResponse response = transactionService.recordTransaction(dto);
  21.         return Result.success(response);
  22.     }
  23.    
  24.     @GetMapping("/transactions/statistics")
  25.     public Result<TransactionStatisticsResponse> getTransactionStatistics(
  26.             @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
  27.             @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
  28.         TransactionStatisticsResponse statistics =
  29.             transactionService.getStatistics(startDate, endDate);
  30.         return Result.success(statistics);
  31.     }
  32.    
  33.     @GetMapping("/revenue/monthly-report")
  34.     public Result<RevenueReportResponse> getMonthlyRevenueReport(
  35.             @RequestParam String month) {
  36.         RevenueReportResponse report = revenueService.generateMonthlyReport(month);
  37.         return Result.success(report);
  38.     }
  39.    
  40.     @GetMapping("/cost/analysis")
  41.     public Result<CostAnalysisResponse> getCostAnalysis(
  42.             @RequestParam String month) {
  43.         CostAnalysisResponse analysis = costService.analyzeMonthlyCost(month);
  44.         return Result.success(analysis);
  45.     }
  46.    
  47.     @PostMapping("/profit-statements")
  48.     public Result<Void> generateProfitStatement(@RequestParam String month) {
  49.         profitService.generateMonthlyStatement(month);
  50.         return Result.success();
  51.     }
  52.    
  53.     @PostMapping("/profit-statements/{id}/approve")
  54.     public Result<Void> approveProfitStatement(@PathVariable Long id) {
  55.         profitService.approveStatement(id);
  56.         return Result.success();
  57.     }
  58.    
  59.     @GetMapping("/profit/analysis")
  60.     public Result<ProfitAnalysisResponse> getProfitAnalysis(
  61.             @RequestParam String startMonth,
  62.             @RequestParam String endMonth) {
  63.         ProfitAnalysisResponse analysis =
  64.             profitService.analyzeProfitTrend(startMonth, endMonth);
  65.         return Result.success(analysis);
  66.     }
  67. }
复制代码
这些代码实现了财务管理的核心功能,包罗:

  • 收支明细记录
  • 营收报表统计
  • 成本分析
  • 利润核算
关键特点:


  • 完整的财务买卖业务记录
  • 多维度的营收分析
  • 具体的成本核算
  • 自动化的利润盘算
  • 完满的报表功能
  • 支持同比环比分析

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

徐锦洪

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表