项目介绍
汽车维修服务管理平台是一个面向汽修店的综合业务管理系统。该平台帮助汽修店实现维修预约、工单管理、库存管理、客户管理等核心业务流程的数字化,提拔运营服从。
技术架构
后端技术栈
- 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. 财务管理
系统特点
- 从预约到结算的完整业务闭环
- 减少人工操作环节
- 提高工作服从
- 简洁清楚的界面设计
- 便捷的操作流程
- 完满的提示信息
项目亮点
- 客户消费分析
- 配件使用分析
- 维修项目分析
- 营收趋势分析
项目收获
- 掌握了完整的Java全栈开辟技术栈
- 深入理解了微服务架构设计思想
- 提拔了项目开辟和管理能力
- 积聚了丰富的业务领域经验
项目展望
- 引入人工智能技术,实现故障智能诊断
- 开辟移动端应用,提供更便捷的服务
- 对接物联网设备,实现智能化管理
- 扩展更多增值服务功能
总结
本项目采取主流的Java全栈技术,实现了汽修行业核心业务的信息化管理。通过该项目的开辟,不仅提拔了技术能力,也深入理解了业务需求分析和系统架构设计的重要性。项目具有较强的实用价值,为汽修企业提供了完满的管理解决方案。
维修预约管理模块的核心代码实现
1. 数据库设计
- -- 预约表
- CREATE TABLE appointment (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- customer_id BIGINT NOT NULL COMMENT '客户ID',
- vehicle_id BIGINT NOT NULL COMMENT '车辆ID',
- service_type VARCHAR(50) NOT NULL COMMENT '服务类型',
- appointment_time DATETIME NOT NULL COMMENT '预约时间',
- time_slot VARCHAR(20) NOT NULL COMMENT '预约时段',
- status VARCHAR(20) NOT NULL COMMENT '预约状态',
- description TEXT COMMENT '维修描述',
- contact_name VARCHAR(50) NOT NULL COMMENT '联系人',
- contact_phone VARCHAR(20) NOT NULL COMMENT '联系电话',
- photos TEXT COMMENT '车辆照片URLs',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- FOREIGN KEY (customer_id) REFERENCES customer(id),
- FOREIGN KEY (vehicle_id) REFERENCES vehicle(id)
- );
- -- 预约时段配置表
- CREATE TABLE time_slot_config (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- slot_time VARCHAR(20) NOT NULL COMMENT '时间段',
- max_capacity INT NOT NULL COMMENT '最大预约数',
- current_capacity INT NOT NULL DEFAULT 0 COMMENT '当前预约数',
- is_available BOOLEAN NOT NULL DEFAULT true COMMENT '是否可用',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
- );
- -- 预约状态变更记录表
- CREATE TABLE appointment_status_log (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- appointment_id BIGINT NOT NULL,
- old_status VARCHAR(20) COMMENT '原状态',
- new_status VARCHAR(20) NOT NULL COMMENT '新状态',
- operator_id BIGINT NOT NULL COMMENT '操作人',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (appointment_id) REFERENCES appointment(id)
- );
复制代码 2. 实体类设计
- @Data
- @Entity
- @Table(name = "appointment")
- public class Appointment {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private Long customerId;
- private Long vehicleId;
- private String serviceType;
- private LocalDateTime appointmentTime;
- private String timeSlot;
-
- @Enumerated(EnumType.STRING)
- private AppointmentStatus status;
-
- private String description;
- private String contactName;
- private String contactPhone;
- private String photos;
- private LocalDateTime createdTime;
- private LocalDateTime updatedTime;
- }
- @Data
- @Entity
- @Table(name = "time_slot_config")
- public class TimeSlotConfig {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String slotTime;
- private Integer maxCapacity;
- private Integer currentCapacity;
- private Boolean isAvailable;
- private LocalDateTime createdTime;
- private LocalDateTime updatedTime;
- }
复制代码 3. 枚举定义
- public enum AppointmentStatus {
- PENDING("待确认"),
- CONFIRMED("已确认"),
- WAITING("待到店"),
- ARRIVED("已到店"),
- COMPLETED("已完成"),
- CANCELLED("已取消");
-
- private String description;
-
- AppointmentStatus(String description) {
- this.description = description;
- }
- }
- public enum ServiceType {
- REGULAR_MAINTENANCE("常规保养"),
- REPAIR("故障维修"),
- INSPECTION("年检服务"),
- CUSTOM("其他服务");
-
- private String description;
-
- ServiceType(String description) {
- this.description = description;
- }
- }
复制代码 4. DTO对象
- @Data
- public class AppointmentDTO {
- private Long customerId;
- private Long vehicleId;
- private String serviceType;
- private String appointmentDate;
- private String timeSlot;
- private String description;
- private String contactName;
- private String contactPhone;
- private List<String> photos;
- }
- @Data
- public class TimeSlotDTO {
- private String date;
- private List<TimeSlotInfo> availableSlots;
-
- @Data
- public static class TimeSlotInfo {
- private String slotTime;
- private Integer availableCapacity;
- private Boolean isAvailable;
- }
- }
复制代码 5. Service层实现
- @Service
- @Transactional
- public class AppointmentService {
-
- @Autowired
- private AppointmentRepository appointmentRepository;
-
- @Autowired
- private TimeSlotConfigRepository timeSlotConfigRepository;
-
- @Autowired
- private NotificationService notificationService;
-
- @Autowired
- private RedisTemplate<String, Object> redisTemplate;
-
- public AppointmentResponse createAppointment(AppointmentDTO dto) {
- // 1. 验证时间段是否可预约
- validateTimeSlot(dto.getAppointmentDate(), dto.getTimeSlot());
-
- // 2. 创建预约记录
- Appointment appointment = new Appointment();
- BeanUtils.copyProperties(dto, appointment);
- appointment.setStatus(AppointmentStatus.PENDING);
-
- // 3. 更新时间段容量
- updateTimeSlotCapacity(dto.getAppointmentDate(), dto.getTimeSlot());
-
- // 4. 保存预约信息
- appointment = appointmentRepository.save(appointment);
-
- // 5. 发送通知
- notificationService.sendAppointmentNotification(appointment);
-
- return buildResponse(appointment);
- }
-
- @Cacheable(value = "timeSlots", key = "#date")
- public List<TimeSlotDTO> getAvailableTimeSlots(String date) {
- List<TimeSlotConfig> configs = timeSlotConfigRepository.findByDateAndIsAvailable(date, true);
- return convertToDTO(configs);
- }
-
- public void updateAppointmentStatus(Long appointmentId, AppointmentStatus newStatus) {
- Appointment appointment = appointmentRepository.findById(appointmentId)
- .orElseThrow(() -> new BusinessException("预约不存在"));
-
- // 记录状态变更
- logStatusChange(appointment, newStatus);
-
- // 更新状态
- appointment.setStatus(newStatus);
- appointmentRepository.save(appointment);
-
- // 发送状态变更通知
- notificationService.sendStatusChangeNotification(appointment);
- }
-
- private void validateTimeSlot(String date, String timeSlot) {
- String cacheKey = "timeSlot:" + date + ":" + timeSlot;
- TimeSlotConfig config = (TimeSlotConfig) redisTemplate.opsForValue().get(cacheKey);
-
- if (config == null) {
- config = timeSlotConfigRepository.findByDateAndSlotTime(date, timeSlot)
- .orElseThrow(() -> new BusinessException("无效的时间段"));
- }
-
- if (!config.getIsAvailable() || config.getCurrentCapacity() >= config.getMaxCapacity()) {
- throw new BusinessException("该时间段已约满");
- }
- }
-
- private void updateTimeSlotCapacity(String date, String timeSlot) {
- timeSlotConfigRepository.incrementCurrentCapacity(date, timeSlot);
- // 更新缓存
- String cacheKey = "timeSlot:" + date + ":" + timeSlot;
- redisTemplate.delete(cacheKey);
- }
- }
复制代码 6. Controller层实现
- @RestController
- @RequestMapping("/api/appointments")
- public class AppointmentController {
-
- @Autowired
- private AppointmentService appointmentService;
-
- @PostMapping
- public Result<AppointmentResponse> createAppointment(@RequestBody @Valid AppointmentDTO dto) {
- try {
- AppointmentResponse response = appointmentService.createAppointment(dto);
- return Result.success(response);
- } catch (BusinessException e) {
- return Result.failure(e.getMessage());
- }
- }
-
- @GetMapping("/time-slots")
- public Result<List<TimeSlotDTO>> getAvailableTimeSlots(
- @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") String date) {
- List<TimeSlotDTO> slots = appointmentService.getAvailableTimeSlots(date);
- return Result.success(slots);
- }
-
- @PutMapping("/{id}/status")
- public Result<Void> updateStatus(
- @PathVariable Long id,
- @RequestParam AppointmentStatus status) {
- appointmentService.updateAppointmentStatus(id, status);
- return Result.success();
- }
-
- @GetMapping("/{id}")
- public Result<AppointmentResponse> getAppointment(@PathVariable Long id) {
- AppointmentResponse appointment = appointmentService.getAppointmentById(id);
- return Result.success(appointment);
- }
- }
复制代码 7. 关照服务实现
- @Service
- public class NotificationService {
-
- @Autowired
- private SMSProvider smsProvider;
-
- @Autowired
- private NotificationTemplateService templateService;
-
- @Async
- public void sendAppointmentNotification(Appointment appointment) {
- try {
- String template = templateService.getTemplate("APPOINTMENT_CREATED");
- String content = buildNotificationContent(template, appointment);
-
- SMSRequest request = SMSRequest.builder()
- .mobile(appointment.getContactPhone())
- .content(content)
- .build();
-
- smsProvider.send(request);
- } catch (Exception e) {
- log.error("发送预约通知失败", e);
- // 添加重试机制
- retryNotification(appointment);
- }
- }
-
- @Async
- public void sendStatusChangeNotification(Appointment appointment) {
- String template = templateService.getTemplate("STATUS_CHANGED");
- String content = buildNotificationContent(template, appointment);
-
- SMSRequest request = SMSRequest.builder()
- .mobile(appointment.getContactPhone())
- .content(content)
- .build();
-
- smsProvider.send(request);
- }
-
- private void retryNotification(Appointment appointment) {
- // 使用重试策略(如:exponential backoff)
- }
- }
复制代码 8. 缓存配置
- @Configuration
- @EnableCaching
- public class CacheConfig {
-
- @Bean
- public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
- RedisTemplate<String, Object> template = new RedisTemplate<>();
- template.setConnectionFactory(factory);
-
- // 设置key的序列化方式
- template.setKeySerializer(new StringRedisSerializer());
-
- // 设置value的序列化方式
- Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
- template.setValueSerializer(serializer);
-
- return template;
- }
-
- @Bean
- public CacheManager cacheManager(RedisConnectionFactory factory) {
- RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
- .entryTtl(Duration.ofHours(1))
- .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
- .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
-
- return RedisCacheManager.builder(factory)
- .cacheDefaults(config)
- .build();
- }
- }
复制代码 9. 非常处理
- @RestControllerAdvice
- public class GlobalExceptionHandler {
-
- @ExceptionHandler(BusinessException.class)
- public Result<Void> handleBusinessException(BusinessException e) {
- return Result.failure(e.getMessage());
- }
-
- @ExceptionHandler(MethodArgumentNotValidException.class)
- public Result<Void> handleValidationException(MethodArgumentNotValidException e) {
- String message = e.getBindingResult().getFieldErrors().stream()
- .map(FieldError::getDefaultMessage)
- .collect(Collectors.joining(", "));
- return Result.failure(message);
- }
-
- @ExceptionHandler(Exception.class)
- public Result<Void> handleException(Exception e) {
- log.error("系统异常", e);
- return Result.failure("系统繁忙,请稍后重试");
- }
- }
复制代码 这些代码实现了预约管理的核心功能,包罗:
- 预约创建和管理
- 时间段容量控制
- 状态跟踪和变动
- 短信关照
- 缓存优化
- 非常处理
关键特点:
- 使用Redis缓存热点数据(时间段信息)
- 异步处理关照发送
- 完满的非常处理机制
- 状态变动日志记录
- 预约容量控制
工单管理模块的核心代码实现
1. 数据库设计
- -- 工单主表
- CREATE TABLE work_order (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- order_no VARCHAR(32) UNIQUE NOT NULL COMMENT '工单编号',
- appointment_id BIGINT COMMENT '关联预约ID',
- customer_id BIGINT NOT NULL COMMENT '客户ID',
- vehicle_id BIGINT NOT NULL COMMENT '车辆ID',
- technician_id BIGINT COMMENT '主责技师ID',
- status VARCHAR(20) NOT NULL COMMENT '工单状态',
- estimated_completion_time DATETIME COMMENT '预计完工时间',
- actual_completion_time DATETIME COMMENT '实际完工时间',
- total_amount DECIMAL(10,2) DEFAULT 0 COMMENT '总金额',
- labor_cost DECIMAL(10,2) DEFAULT 0 COMMENT '工时费',
- parts_cost DECIMAL(10,2) DEFAULT 0 COMMENT '配件费',
- description TEXT COMMENT '维修描述',
- diagnosis_result TEXT COMMENT '检查结果',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
- );
- -- 工单项目明细表
- CREATE TABLE work_order_item (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- work_order_id BIGINT NOT NULL COMMENT '工单ID',
- service_item_id BIGINT NOT NULL COMMENT '服务项目ID',
- technician_id BIGINT COMMENT '技师ID',
- status VARCHAR(20) NOT NULL COMMENT '项目状态',
- estimated_hours DECIMAL(4,1) COMMENT '预计工时',
- actual_hours DECIMAL(4,1) COMMENT '实际工时',
- amount DECIMAL(10,2) COMMENT '项目金额',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (work_order_id) REFERENCES work_order(id)
- );
- -- 工单配件使用记录表
- CREATE TABLE work_order_part (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- work_order_id BIGINT NOT NULL COMMENT '工单ID',
- part_id BIGINT NOT NULL COMMENT '配件ID',
- quantity INT NOT NULL COMMENT '使用数量',
- unit_price DECIMAL(10,2) NOT NULL COMMENT '单价',
- amount DECIMAL(10,2) NOT NULL COMMENT '金额',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (work_order_id) REFERENCES work_order(id)
- );
- -- 工单进度记录表
- CREATE TABLE work_order_progress (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- work_order_id BIGINT NOT NULL COMMENT '工单ID',
- status VARCHAR(20) NOT NULL COMMENT '状态',
- operator_id BIGINT NOT NULL COMMENT '操作人',
- remark TEXT COMMENT '备注',
- photos TEXT COMMENT '照片URLs',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (work_order_id) REFERENCES work_order(id)
- );
复制代码 2. 实体类设计
- @Data
- @Entity
- @Table(name = "work_order")
- public class WorkOrder {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String orderNo;
- private Long appointmentId;
- private Long customerId;
- private Long vehicleId;
- private Long technicianId;
-
- @Enumerated(EnumType.STRING)
- private WorkOrderStatus status;
-
- private LocalDateTime estimatedCompletionTime;
- private LocalDateTime actualCompletionTime;
- private BigDecimal totalAmount;
- private BigDecimal laborCost;
- private BigDecimal partsCost;
- private String description;
- private String diagnosisResult;
-
- @OneToMany(mappedBy = "workOrder", cascade = CascadeType.ALL)
- private List<WorkOrderItem> items;
-
- @OneToMany(mappedBy = "workOrder", cascade = CascadeType.ALL)
- private List<WorkOrderPart> parts;
- }
- @Data
- @Entity
- @Table(name = "work_order_item")
- public class WorkOrderItem {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- @ManyToOne
- @JoinColumn(name = "work_order_id")
- private WorkOrder workOrder;
-
- private Long serviceItemId;
- private Long technicianId;
-
- @Enumerated(EnumType.STRING)
- private ItemStatus status;
-
- private BigDecimal estimatedHours;
- private BigDecimal actualHours;
- private BigDecimal amount;
- private String remark;
- }
复制代码 3. 枚举定义
- public enum WorkOrderStatus {
- CREATED("已创建"),
- INSPECTING("检查中"),
- REPAIRING("维修中"),
- QUALITY_CHECK("质检中"),
- COMPLETED("已完成"),
- CANCELLED("已取消");
-
- private String description;
-
- WorkOrderStatus(String description) {
- this.description = description;
- }
- }
- public enum ItemStatus {
- PENDING("待处理"),
- IN_PROGRESS("进行中"),
- COMPLETED("已完成"),
- CANCELLED("已取消");
-
- private String description;
- }
复制代码 4. Service层实现
- @Service
- @Transactional
- public class WorkOrderService {
-
- @Autowired
- private WorkOrderRepository workOrderRepository;
-
- @Autowired
- private WorkOrderItemRepository itemRepository;
-
- @Autowired
- private PartInventoryService partInventoryService;
-
- @Autowired
- private NotificationService notificationService;
-
- public WorkOrderResponse createWorkOrder(WorkOrderDTO dto) {
- // 1. 生成工单编号
- String orderNo = generateOrderNo();
-
- // 2. 创建工单
- WorkOrder workOrder = new WorkOrder();
- BeanUtils.copyProperties(dto, workOrder);
- workOrder.setOrderNo(orderNo);
- workOrder.setStatus(WorkOrderStatus.CREATED);
-
- // 3. 创建工单项目
- List<WorkOrderItem> items = createWorkOrderItems(dto.getItems(), workOrder);
- workOrder.setItems(items);
-
- // 4. 计算预估金额
- calculateEstimatedAmount(workOrder);
-
- // 5. 保存工单
- workOrder = workOrderRepository.save(workOrder);
-
- // 6. 发送通知
- notificationService.sendWorkOrderCreatedNotification(workOrder);
-
- return buildResponse(workOrder);
- }
-
- public void updateWorkOrderStatus(Long id, WorkOrderStatus newStatus, String remark) {
- WorkOrder workOrder = workOrderRepository.findById(id)
- .orElseThrow(() -> new BusinessException("工单不存在"));
-
- // 1. 验证状态变更是否合法
- validateStatusTransition(workOrder.getStatus(), newStatus);
-
- // 2. 更新状态
- workOrder.setStatus(newStatus);
-
- // 3. 记录进度
- saveProgress(workOrder, newStatus, remark);
-
- // 4. 特殊状态处理
- handleSpecialStatus(workOrder, newStatus);
-
- // 5. 保存更新
- workOrderRepository.save(workOrder);
-
- // 6. 发送通知
- notificationService.sendStatusChangeNotification(workOrder);
- }
-
- public void addWorkOrderPart(Long workOrderId, WorkOrderPartDTO dto) {
- WorkOrder workOrder = workOrderRepository.findById(workOrderId)
- .orElseThrow(() -> new BusinessException("工单不存在"));
-
- // 1. 检查库存
- partInventoryService.checkInventory(dto.getPartId(), dto.getQuantity());
-
- // 2. 创建配件使用记录
- WorkOrderPart part = new WorkOrderPart();
- BeanUtils.copyProperties(dto, part);
- part.setWorkOrder(workOrder);
-
- // 3. 计算金额
- calculatePartAmount(part);
-
- // 4. 更新工单金额
- updateWorkOrderAmount(workOrder, part.getAmount());
-
- // 5. 扣减库存
- partInventoryService.deductInventory(dto.getPartId(), dto.getQuantity());
-
- // 6. 保存记录
- workOrderPartRepository.save(part);
- }
-
- public void updateWorkOrderProgress(Long id, ProgressUpdateDTO dto) {
- WorkOrder workOrder = workOrderRepository.findById(id)
- .orElseThrow(() -> new BusinessException("工单不存在"));
-
- // 1. 更新项目进度
- updateItemsProgress(workOrder, dto.getItemProgresses());
-
- // 2. 更新工时
- updateLaborHours(workOrder, dto.getItemProgresses());
-
- // 3. 重新计算费用
- recalculateAmount(workOrder);
-
- // 4. 保存更新
- workOrderRepository.save(workOrder);
-
- // 5. 记录进度
- saveProgress(workOrder, dto.getRemark(), dto.getPhotos());
- }
-
- private void calculateEstimatedAmount(WorkOrder workOrder) {
- BigDecimal laborCost = calculateLaborCost(workOrder.getItems());
- BigDecimal partsCost = calculatePartsCost(workOrder.getParts());
- workOrder.setLaborCost(laborCost);
- workOrder.setPartsCost(partsCost);
- workOrder.setTotalAmount(laborCost.add(partsCost));
- }
-
- private void handleSpecialStatus(WorkOrder workOrder, WorkOrderStatus status) {
- switch (status) {
- case COMPLETED:
- workOrder.setActualCompletionTime(LocalDateTime.now());
- break;
- case QUALITY_CHECK:
- validateAllItemsCompleted(workOrder);
- break;
- }
- }
- }
复制代码 5. Controller层实现
- @RestController
- @RequestMapping("/api/work-orders")
- public class WorkOrderController {
-
- @Autowired
- private WorkOrderService workOrderService;
-
- @PostMapping
- public Result<WorkOrderResponse> createWorkOrder(@RequestBody @Valid WorkOrderDTO dto) {
- WorkOrderResponse response = workOrderService.createWorkOrder(dto);
- return Result.success(response);
- }
-
- @PutMapping("/{id}/status")
- public Result<Void> updateStatus(
- @PathVariable Long id,
- @RequestParam WorkOrderStatus status,
- @RequestParam(required = false) String remark) {
- workOrderService.updateWorkOrderStatus(id, status, remark);
- return Result.success();
- }
-
- @PostMapping("/{id}/parts")
- public Result<Void> addPart(
- @PathVariable Long id,
- @RequestBody @Valid WorkOrderPartDTO dto) {
- workOrderService.addWorkOrderPart(id, dto);
- return Result.success();
- }
-
- @PutMapping("/{id}/progress")
- public Result<Void> updateProgress(
- @PathVariable Long id,
- @RequestBody @Valid ProgressUpdateDTO dto) {
- workOrderService.updateWorkOrderProgress(id, dto);
- return Result.success();
- }
-
- @GetMapping("/{id}")
- public Result<WorkOrderDetailResponse> getWorkOrder(@PathVariable Long id) {
- WorkOrderDetailResponse detail = workOrderService.getWorkOrderDetail(id);
- return Result.success(detail);
- }
- }
复制代码 6. 费用盘算服务
- @Service
- public class CostCalculationService {
-
- @Autowired
- private ServiceItemRepository serviceItemRepository;
-
- @Autowired
- private PartRepository partRepository;
-
- public BigDecimal calculateLaborCost(List<WorkOrderItem> items) {
- return items.stream()
- .map(this::calculateItemLaborCost)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- }
-
- public BigDecimal calculatePartsCost(List<WorkOrderPart> parts) {
- return parts.stream()
- .map(this::calculatePartCost)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- }
-
- private BigDecimal calculateItemLaborCost(WorkOrderItem item) {
- ServiceItem serviceItem = serviceItemRepository.findById(item.getServiceItemId())
- .orElseThrow(() -> new BusinessException("服务项目不存在"));
-
- return serviceItem.getHourlyRate()
- .multiply(item.getActualHours() != null ?
- item.getActualHours() : item.getEstimatedHours());
- }
-
- private BigDecimal calculatePartCost(WorkOrderPart part) {
- return part.getUnitPrice().multiply(BigDecimal.valueOf(part.getQuantity()));
- }
- }
复制代码 7. 状态机实现
- @Component
- public class WorkOrderStateMachine {
-
- private static final Map<WorkOrderStatus, Set<WorkOrderStatus>> VALID_TRANSITIONS;
-
- static {
- VALID_TRANSITIONS = new HashMap<>();
- VALID_TRANSITIONS.put(WorkOrderStatus.CREATED,
- Set.of(WorkOrderStatus.INSPECTING, WorkOrderStatus.CANCELLED));
- VALID_TRANSITIONS.put(WorkOrderStatus.INSPECTING,
- Set.of(WorkOrderStatus.REPAIRING, WorkOrderStatus.CANCELLED));
- VALID_TRANSITIONS.put(WorkOrderStatus.REPAIRING,
- Set.of(WorkOrderStatus.QUALITY_CHECK, WorkOrderStatus.CANCELLED));
- VALID_TRANSITIONS.put(WorkOrderStatus.QUALITY_CHECK,
- Set.of(WorkOrderStatus.COMPLETED, WorkOrderStatus.REPAIRING));
- }
-
- public boolean canTransit(WorkOrderStatus current, WorkOrderStatus target) {
- Set<WorkOrderStatus> validTargets = VALID_TRANSITIONS.get(current);
- return validTargets != null && validTargets.contains(target);
- }
-
- public void validateTransition(WorkOrderStatus current, WorkOrderStatus target) {
- if (!canTransit(current, target)) {
- throw new BusinessException(
- String.format("不允许从%s状态变更为%s状态",
- current.getDescription(),
- target.getDescription())
- );
- }
- }
- }
复制代码 8. 进度跟踪实现
- @Service
- public class ProgressTrackingService {
-
- @Autowired
- private WorkOrderProgressRepository progressRepository;
-
- @Autowired
- private FileService fileService;
-
- public void saveProgress(WorkOrder workOrder, String remark, List<MultipartFile> photos) {
- // 1. 保存照片
- List<String> photoUrls = new ArrayList<>();
- if (photos != null && !photos.isEmpty()) {
- photoUrls = photos.stream()
- .map(photo -> fileService.uploadFile(photo))
- .collect(Collectors.toList());
- }
-
- // 2. 创建进度记录
- WorkOrderProgress progress = new WorkOrderProgress();
- progress.setWorkOrderId(workOrder.getId());
- progress.setStatus(workOrder.getStatus());
- progress.setRemark(remark);
- progress.setPhotos(String.join(",", photoUrls));
- progress.setOperatorId(SecurityUtils.getCurrentUserId());
-
- // 3. 保存记录
- progressRepository.save(progress);
- }
-
- public List<ProgressResponse> getProgressHistory(Long workOrderId) {
- List<WorkOrderProgress> progressList = progressRepository
- .findByWorkOrderIdOrderByCreatedTimeDesc(workOrderId);
-
- return progressList.stream()
- .map(this::convertToResponse)
- .collect(Collectors.toList());
- }
-
- private ProgressResponse convertToResponse(WorkOrderProgress progress) {
- ProgressResponse response = new ProgressResponse();
- BeanUtils.copyProperties(progress, response);
-
- // 设置操作人信息
- User operator = userService.getUser(progress.getOperatorId());
- response.setOperatorName(operator.getName());
-
- // 处理照片URL
- if (StringUtils.hasText(progress.getPhotos())) {
- response.setPhotoUrls(Arrays.asList(progress.getPhotos().split(",")));
- }
-
- return response;
- }
- }
复制代码 9. 工单查询服务
- @Service
- public class WorkOrderQueryService {
-
- @Autowired
- private WorkOrderRepository workOrderRepository;
-
- public Page<WorkOrderResponse> queryWorkOrders(WorkOrderQueryDTO query) {
- // 1. 构建查询条件
- Specification<WorkOrder> spec = buildSpecification(query);
-
- // 2. 创建分页对象
- PageRequest pageRequest = PageRequest.of(
- query.getPageNum(),
- query.getPageSize(),
- Sort.by(Sort.Direction.DESC, "createdTime")
- );
-
- // 3. 执行查询
- Page<WorkOrder> page = workOrderRepository.findAll(spec, pageRequest);
-
- // 4. 转换响应
- return page.map(this::convertToResponse);
- }
-
- private Specification<WorkOrder> buildSpecification(WorkOrderQueryDTO query) {
- return (root, criteriaQuery, criteriaBuilder) -> {
- List<Predicate> predicates = new ArrayList<>();
-
- // 工单号
- if (StringUtils.hasText(query.getOrderNo())) {
- predicates.add(criteriaBuilder.like(
- root.get("orderNo"),
- "%" + query.getOrderNo() + "%"
- ));
- }
-
- // 状态
- if (query.getStatus() != null) {
- predicates.add(criteriaBuilder.equal(
- root.get("status"),
- query.getStatus()
- ));
- }
-
- // 时间范围
- if (query.getStartTime() != null) {
- predicates.add(criteriaBuilder.greaterThanOrEqualTo(
- root.get("createdTime"),
- query.getStartTime()
- ));
- }
-
- if (query.getEndTime() != null) {
- predicates.add(criteriaBuilder.lessThanOrEqualTo(
- root.get("createdTime"),
- query.getEndTime()
- ));
- }
-
- return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
- };
- }
- }
复制代码 这些代码实现了工单管理的核心功能,包罗:
- 工单创建和管理
- 维修项目跟踪
- 配件使用管理
- 费用盘算
- 状态流转控制
- 进度记录跟踪
关键特点:
- 完整的状态机实现
- 细粒度的费用盘算
- 具体的进度跟踪
- 灵活的查询功能
- 完满的数据验证
库存管理模块的核心代码实现
1. 数据库设计
- -- 配件信息表
- CREATE TABLE part (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- code VARCHAR(32) UNIQUE NOT NULL COMMENT '配件编号',
- name VARCHAR(100) NOT NULL COMMENT '配件名称',
- category_id BIGINT NOT NULL COMMENT '分类ID',
- brand VARCHAR(50) COMMENT '品牌',
- model VARCHAR(50) COMMENT '型号',
- unit VARCHAR(20) NOT NULL COMMENT '单位',
- price DECIMAL(10,2) NOT NULL COMMENT '单价',
- min_stock INT NOT NULL COMMENT '最低库存',
- max_stock INT NOT NULL COMMENT '最高库存',
- shelf_life INT COMMENT '保质期(天)',
- status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 0-停用 1-启用',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
- );
- -- 库存记录表
- CREATE TABLE inventory (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- part_id BIGINT NOT NULL COMMENT '配件ID',
- warehouse_id BIGINT NOT NULL COMMENT '仓库ID',
- quantity INT NOT NULL DEFAULT 0 COMMENT '当前库存量',
- locked_quantity INT NOT NULL DEFAULT 0 COMMENT '锁定数量',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- UNIQUE KEY `uk_part_warehouse` (`part_id`, `warehouse_id`)
- );
- -- 入库记录表
- CREATE TABLE stock_in (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- order_no VARCHAR(32) UNIQUE NOT NULL COMMENT '入库单号',
- warehouse_id BIGINT NOT NULL COMMENT '仓库ID',
- supplier_id BIGINT NOT NULL COMMENT '供应商ID',
- type VARCHAR(20) NOT NULL COMMENT '入库类型',
- status VARCHAR(20) NOT NULL COMMENT '状态',
- total_amount DECIMAL(10,2) NOT NULL COMMENT '总金额',
- operator_id BIGINT NOT NULL COMMENT '操作人',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- -- 入库明细表
- CREATE TABLE stock_in_item (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- stock_in_id BIGINT NOT NULL COMMENT '入库单ID',
- part_id BIGINT NOT NULL COMMENT '配件ID',
- quantity INT NOT NULL COMMENT '数量',
- unit_price DECIMAL(10,2) NOT NULL COMMENT '单价',
- amount DECIMAL(10,2) NOT NULL COMMENT '金额',
- batch_no VARCHAR(50) COMMENT '批次号',
- production_date DATE COMMENT '生产日期',
- expiry_date DATE COMMENT '过期日期',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (stock_in_id) REFERENCES stock_in(id)
- );
- -- 库存变动记录表
- CREATE TABLE inventory_transaction (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- part_id BIGINT NOT NULL COMMENT '配件ID',
- warehouse_id BIGINT NOT NULL COMMENT '仓库ID',
- type VARCHAR(20) NOT NULL COMMENT '变动类型',
- quantity INT NOT NULL COMMENT '变动数量',
- before_quantity INT NOT NULL COMMENT '变动前数量',
- after_quantity INT NOT NULL COMMENT '变动后数量',
- reference_no VARCHAR(32) COMMENT '关联单号',
- operator_id BIGINT NOT NULL COMMENT '操作人',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- -- 库存盘点表
- CREATE TABLE inventory_check (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- check_no VARCHAR(32) UNIQUE NOT NULL COMMENT '盘点单号',
- warehouse_id BIGINT NOT NULL COMMENT '仓库ID',
- status VARCHAR(20) NOT NULL COMMENT '状态',
- start_time DATETIME NOT NULL COMMENT '开始时间',
- end_time DATETIME COMMENT '结束时间',
- operator_id BIGINT NOT NULL COMMENT '操作人',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- -- 盘点明细表
- CREATE TABLE inventory_check_item (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- check_id BIGINT NOT NULL COMMENT '盘点单ID',
- part_id BIGINT NOT NULL COMMENT '配件ID',
- system_quantity INT NOT NULL COMMENT '系统数量',
- actual_quantity INT NOT NULL COMMENT '实际数量',
- difference INT NOT NULL COMMENT '差异数量',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (check_id) REFERENCES inventory_check(id)
- );
复制代码 2. 实体类设计
- @Data
- @Entity
- @Table(name = "part")
- public class Part {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String code;
- private String name;
- private Long categoryId;
- private String brand;
- private String model;
- private String unit;
- private BigDecimal price;
- private Integer minStock;
- private Integer maxStock;
- private Integer shelfLife;
- private Integer status;
- private String remark;
- private LocalDateTime createdTime;
- private LocalDateTime updatedTime;
- }
- @Data
- @Entity
- @Table(name = "inventory")
- public class Inventory {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private Long partId;
- private Long warehouseId;
- private Integer quantity;
- private Integer lockedQuantity;
- private LocalDateTime createdTime;
- private LocalDateTime updatedTime;
-
- @Version
- private Integer version; // 乐观锁版本号
- }
- @Data
- @Entity
- @Table(name = "stock_in")
- public class StockIn {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String orderNo;
- private Long warehouseId;
- private Long supplierId;
-
- @Enumerated(EnumType.STRING)
- private StockInType type;
-
- @Enumerated(EnumType.STRING)
- private StockInStatus status;
-
- private BigDecimal totalAmount;
- private Long operatorId;
- private String remark;
- private LocalDateTime createdTime;
-
- @OneToMany(mappedBy = "stockIn", cascade = CascadeType.ALL)
- private List<StockInItem> items;
- }
复制代码 3. 入库服务实现
- @Service
- @Transactional
- public class StockInService {
-
- @Autowired
- private StockInRepository stockInRepository;
-
- @Autowired
- private InventoryService inventoryService;
-
- @Autowired
- private SequenceGenerator sequenceGenerator;
-
- public StockInResponse createStockIn(StockInDTO dto) {
- // 1. 生成入库单号
- String orderNo = sequenceGenerator.generateStockInNo();
-
- // 2. 创建入库单
- StockIn stockIn = new StockIn();
- BeanUtils.copyProperties(dto, stockIn);
- stockIn.setOrderNo(orderNo);
- stockIn.setStatus(StockInStatus.PENDING);
-
- // 3. 创建入库明细
- List<StockInItem> items = createStockInItems(dto.getItems(), stockIn);
- stockIn.setItems(items);
-
- // 4. 计算总金额
- BigDecimal totalAmount = calculateTotalAmount(items);
- stockIn.setTotalAmount(totalAmount);
-
- // 5. 保存入库单
- stockIn = stockInRepository.save(stockIn);
-
- return buildResponse(stockIn);
- }
-
- public void confirmStockIn(Long id) {
- StockIn stockIn = stockInRepository.findById(id)
- .orElseThrow(() -> new BusinessException("入库单不存在"));
-
- // 1. 验证状态
- if (stockIn.getStatus() != StockInStatus.PENDING) {
- throw new BusinessException("入库单状态不正确");
- }
-
- // 2. 更新库存
- for (StockInItem item : stockIn.getItems()) {
- inventoryService.increaseStock(
- item.getPartId(),
- stockIn.getWarehouseId(),
- item.getQuantity(),
- stockIn.getOrderNo()
- );
- }
-
- // 3. 更新入库单状态
- stockIn.setStatus(StockInStatus.COMPLETED);
- stockInRepository.save(stockIn);
- }
- }
复制代码 4. 库存服务实现
- @Service
- @Transactional
- public class InventoryService {
-
- @Autowired
- private InventoryRepository inventoryRepository;
-
- @Autowired
- private InventoryTransactionRepository transactionRepository;
-
- @Autowired
- private RedisTemplate<String, Object> redisTemplate;
-
- public void increaseStock(Long partId, Long warehouseId, Integer quantity, String referenceNo) {
- // 1. 获取或创建库存记录
- Inventory inventory = getOrCreateInventory(partId, warehouseId);
-
- // 2. 更新库存(使用乐观锁)
- int retryCount = 0;
- while (retryCount < 3) {
- try {
- inventory.setQuantity(inventory.getQuantity() + quantity);
- inventoryRepository.save(inventory);
- break;
- } catch (OptimisticLockingFailureException e) {
- if (++retryCount == 3) {
- throw new BusinessException("更新库存失败,请重试");
- }
- inventory = inventoryRepository.findByPartIdAndWarehouseId(partId, warehouseId)
- .orElseThrow();
- }
- }
-
- // 3. 记录库存变动
- saveInventoryTransaction(
- inventory,
- TransactionType.STOCK_IN,
- quantity,
- referenceNo
- );
-
- // 4. 检查库存预警
- checkStockWarning(inventory);
- }
-
- public void decreaseStock(Long partId, Long warehouseId, Integer quantity, String referenceNo) {
- // 1. 获取库存记录
- Inventory inventory = inventoryRepository.findByPartIdAndWarehouseId(partId, warehouseId)
- .orElseThrow(() -> new BusinessException("库存记录不存在"));
-
- // 2. 检查库存是否足够
- if (inventory.getQuantity() - inventory.getLockedQuantity() < quantity) {
- throw new BusinessException("可用库存不足");
- }
-
- // 3. 更新库存(使用乐观锁)
- int retryCount = 0;
- while (retryCount < 3) {
- try {
- inventory.setQuantity(inventory.getQuantity() - quantity);
- inventoryRepository.save(inventory);
- break;
- } catch (OptimisticLockingFailureException e) {
- if (++retryCount == 3) {
- throw new BusinessException("更新库存失败,请重试");
- }
- inventory = inventoryRepository.findByPartIdAndWarehouseId(partId, warehouseId)
- .orElseThrow();
- }
- }
-
- // 4. 记录库存变动
- saveInventoryTransaction(
- inventory,
- TransactionType.STOCK_OUT,
- -quantity,
- referenceNo
- );
-
- // 5. 检查库存预警
- checkStockWarning(inventory);
- }
-
- private void checkStockWarning(Inventory inventory) {
- Part part = partRepository.findById(inventory.getPartId())
- .orElseThrow();
-
- // 检查是否低于最低库存
- if (inventory.getQuantity() <= part.getMinStock()) {
- // 发送库存预警
- sendStockWarning(inventory, part);
-
- // 缓存预警信息
- cacheStockWarning(inventory, part);
- }
- }
- }
复制代码 5. 库存盘货服务实现
- @Service
- @Transactional
- public class InventoryCheckService {
-
- @Autowired
- private InventoryCheckRepository checkRepository;
-
- @Autowired
- private InventoryService inventoryService;
-
- public InventoryCheckResponse createCheck(InventoryCheckDTO dto) {
- // 1. 生成盘点单号
- String checkNo = sequenceGenerator.generateCheckNo();
-
- // 2. 创建盘点单
- InventoryCheck check = new InventoryCheck();
- BeanUtils.copyProperties(dto, check);
- check.setCheckNo(checkNo);
- check.setStatus(CheckStatus.IN_PROGRESS);
- check.setStartTime(LocalDateTime.now());
-
- // 3. 获取系统库存数据
- List<InventoryCheckItem> items = generateCheckItems(dto.getWarehouseId());
- check.setItems(items);
-
- // 4. 保存盘点单
- check = checkRepository.save(check);
-
- return buildResponse(check);
- }
-
- public void completeCheck(Long id, List<CheckItemDTO> items) {
- InventoryCheck check = checkRepository.findById(id)
- .orElseThrow(() -> new BusinessException("盘点单不存在"));
-
- // 1. 验证状态
- if (check.getStatus() != CheckStatus.IN_PROGRESS) {
- throw new BusinessException("盘点单状态不正确");
- }
-
- // 2. 更新盘点结果
- updateCheckItems(check, items);
-
- // 3. 处理盘盈盘亏
- handleInventoryDifference(check);
-
- // 4. 完成盘点
- check.setStatus(CheckStatus.COMPLETED);
- check.setEndTime(LocalDateTime.now());
- checkRepository.save(check);
- }
-
- private void handleInventoryDifference(InventoryCheck check) {
- for (InventoryCheckItem item : check.getItems()) {
- if (item.getDifference() != 0) {
- // 记录库存调整
- inventoryService.adjustStock(
- item.getPartId(),
- check.getWarehouseId(),
- item.getDifference(),
- check.getCheckNo()
- );
- }
- }
- }
- }
复制代码 6. 库存预警服务实现
- @Service
- public class StockWarningService {
-
- @Autowired
- private RedisTemplate<String, Object> redisTemplate;
-
- @Autowired
- private NotificationService notificationService;
-
- private static final String WARNING_KEY_PREFIX = "stock:warning:";
-
- public void sendStockWarning(Inventory inventory, Part part) {
- StockWarningMessage message = StockWarningMessage.builder()
- .partCode(part.getCode())
- .partName(part.getName())
- .currentStock(inventory.getQuantity())
- .minStock(part.getMinStock())
- .warehouseId(inventory.getWarehouseId())
- .build();
-
- // 1. 发送消息通知
- notificationService.sendStockWarning(message);
-
- // 2. 缓存预警信息
- cacheWarningInfo(inventory.getPartId(), message);
- }
-
- public List<StockWarningMessage> getWarningList() {
- Set<String> keys = redisTemplate.keys(WARNING_KEY_PREFIX + "*");
- if (keys == null || keys.isEmpty()) {
- return Collections.emptyList();
- }
-
- return keys.stream()
- .map(key -> (StockWarningMessage) redisTemplate.opsForValue().get(key))
- .collect(Collectors.toList());
- }
-
- private void cacheWarningInfo(Long partId, StockWarningMessage message) {
- String key = WARNING_KEY_PREFIX + partId;
- redisTemplate.opsForValue().set(key, message, 24, TimeUnit.HOURS);
- }
- }
复制代码 7. 库存统计服务实现
- @Service
- public class InventoryStatisticsService {
-
- @Autowired
- private InventoryRepository inventoryRepository;
-
- @Autowired
- private InventoryTransactionRepository transactionRepository;
-
- public InventoryStatisticsResponse getStatistics(StatisticsQueryDTO query) {
- // 1. 库存总量统计
- InventoryTotalVO total = calculateInventoryTotal(query);
-
- // 2. 库存金额统计
- InventoryAmountVO amount = calculateInventoryAmount(query);
-
- // 3. 库存周转率统计
- TurnoverRateVO turnover = calculateTurnoverRate(query);
-
- // 4. 库存预警统计
- WarningStatisticsVO warning = calculateWarningStatistics(query);
-
- return InventoryStatisticsResponse.builder()
- .total(total)
- .amount(amount)
- .turnover(turnover)
- .warning(warning)
- .build();
- }
-
- public List<InventoryTransactionVO> getTransactionHistory(
- Long partId, LocalDateTime startTime, LocalDateTime endTime) {
- List<InventoryTransaction> transactions =
- transactionRepository.findByPartIdAndCreatedTimeBetween(
- partId, startTime, endTime);
-
- return transactions.stream()
- .map(this::convertToVO)
- .collect(Collectors.toList());
- }
-
- private TurnoverRateVO calculateTurnoverRate(StatisticsQueryDTO query) {
- // 1. 获取期初库存
- BigDecimal beginningInventory = getBeginningInventory(query);
-
- // 2. 获取期末库存
- BigDecimal endingInventory = getEndingInventory(query);
-
- // 3. 获取期间出库数量
- BigDecimal outboundQuantity = getOutboundQuantity(query);
-
- // 4. 计算平均库存
- BigDecimal averageInventory = beginningInventory.add(endingInventory)
- .divide(BigDecimal.valueOf(2), 2, RoundingMode.HALF_UP);
-
- // 5. 计算周转率
- BigDecimal turnoverRate = BigDecimal.ZERO;
- if (averageInventory.compareTo(BigDecimal.ZERO) > 0) {
- turnoverRate = outboundQuantity.divide(averageInventory, 2, RoundingMode.HALF_UP);
- }
-
- return new TurnoverRateVO(turnoverRate);
- }
- }
复制代码 8. 库存查询接口实现
- @RestController
- @RequestMapping("/api/inventory")
- public class InventoryController {
-
- @Autowired
- private InventoryService inventoryService;
-
- @Autowired
- private InventoryStatisticsService statisticsService;
-
- @GetMapping("/stock")
- public Result<Page<InventoryVO>> queryStock(InventoryQueryDTO query) {
- Page<InventoryVO> page = inventoryService.queryStock(query);
- return Result.success(page);
- }
-
- @GetMapping("/warning")
- public Result<List<StockWarningMessage>> getWarningList() {
- List<StockWarningMessage> warnings = inventoryService.getWarningList();
- return Result.success(warnings);
- }
-
- @GetMapping("/statistics")
- public Result<InventoryStatisticsResponse> getStatistics(StatisticsQueryDTO query) {
- InventoryStatisticsResponse statistics = statisticsService.getStatistics(query);
- return Result.success(statistics);
- }
-
- @GetMapping("/transaction-history")
- public Result<List<InventoryTransactionVO>> getTransactionHistory(
- @RequestParam Long partId,
- @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
- @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
- List<InventoryTransactionVO> history =
- statisticsService.getTransactionHistory(partId, startTime, endTime);
- return Result.success(history);
- }
- }
复制代码 这些代码实现了库存管理的核心功能,包罗:
- 配件入库管理
- 库存变动控制
- 库存预警机制
- 库存盘货处理
- 库存统计分析
关键特点:
- 使用乐观锁控制并发
- Redis缓存预警信息
- 完整的库存变动追踪
- 具体的统计分析功能
- 支持库存盘货处理
客户管理模块的核心代码实现
1. 数据库设计
- -- 客户信息表
- CREATE TABLE customer (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- code VARCHAR(32) UNIQUE NOT NULL COMMENT '客户编号',
- name VARCHAR(100) NOT NULL COMMENT '客户姓名',
- phone VARCHAR(20) NOT NULL COMMENT '联系电话',
- id_card VARCHAR(18) COMMENT '身份证号',
- gender TINYINT COMMENT '性别: 0-女 1-男',
- birthday DATE COMMENT '生日',
- email VARCHAR(100) COMMENT '邮箱',
- address TEXT COMMENT '地址',
- source VARCHAR(50) COMMENT '客户来源',
- level VARCHAR(20) NOT NULL DEFAULT 'NORMAL' COMMENT '客户等级',
- points INT NOT NULL DEFAULT 0 COMMENT '积分',
- status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 0-禁用 1-启用',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
- );
- -- 车辆信息表
- CREATE TABLE vehicle (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- customer_id BIGINT NOT NULL COMMENT '客户ID',
- plate_number VARCHAR(20) NOT NULL COMMENT '车牌号',
- brand VARCHAR(50) NOT NULL COMMENT '品牌',
- model VARCHAR(50) NOT NULL COMMENT '型号',
- vin VARCHAR(50) UNIQUE COMMENT '车架号',
- engine_number VARCHAR(50) COMMENT '发动机号',
- color VARCHAR(20) COMMENT '颜色',
- mileage INT COMMENT '行驶里程',
- purchase_date DATE COMMENT '购买日期',
- insurance_expiry DATE COMMENT '保险到期日',
- last_service_date DATE COMMENT '最后保养日期',
- status TINYINT NOT NULL DEFAULT 1 COMMENT '状态',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- FOREIGN KEY (customer_id) REFERENCES customer(id)
- );
- -- 维修记录表
- CREATE TABLE service_record (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- work_order_id BIGINT NOT NULL COMMENT '工单ID',
- customer_id BIGINT NOT NULL COMMENT '客户ID',
- vehicle_id BIGINT NOT NULL COMMENT '车辆ID',
- service_type VARCHAR(50) NOT NULL COMMENT '服务类型',
- service_items TEXT COMMENT '服务项目',
- total_amount DECIMAL(10,2) NOT NULL COMMENT '总金额',
- service_date DATE NOT NULL COMMENT '服务日期',
- mileage INT COMMENT '服务时里程',
- technician_id BIGINT COMMENT '技师ID',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (customer_id) REFERENCES customer(id),
- FOREIGN KEY (vehicle_id) REFERENCES vehicle(id)
- );
- -- 积分变动记录表
- CREATE TABLE points_transaction (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- customer_id BIGINT NOT NULL COMMENT '客户ID',
- type VARCHAR(20) NOT NULL COMMENT '变动类型',
- points INT NOT NULL COMMENT '变动积分',
- before_points INT NOT NULL COMMENT '变动前积分',
- after_points INT NOT NULL COMMENT '变动后积分',
- reference_no VARCHAR(32) COMMENT '关联单号',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (customer_id) REFERENCES customer(id)
- );
复制代码 2. 实体类设计
- @Data
- @Entity
- @Table(name = "customer")
- public class Customer {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String code;
- private String name;
- private String phone;
- private String idCard;
- private Integer gender;
- private LocalDate birthday;
- private String email;
- private String address;
- private String source;
-
- @Enumerated(EnumType.STRING)
- private CustomerLevel level;
-
- private Integer points;
- private Integer status;
- private String remark;
- private LocalDateTime createdTime;
- private LocalDateTime updatedTime;
-
- @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
- private List<Vehicle> vehicles;
- }
- @Data
- @Entity
- @Table(name = "vehicle")
- public class Vehicle {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- @ManyToOne
- @JoinColumn(name = "customer_id")
- private Customer customer;
-
- private String plateNumber;
- private String brand;
- private String model;
- private String vin;
- private String engineNumber;
- private String color;
- private Integer mileage;
- private LocalDate purchaseDate;
- private LocalDate insuranceExpiry;
- private LocalDate lastServiceDate;
- private Integer status;
- }
复制代码 3. 客户服务实现
- @Service
- @Transactional
- public class CustomerService {
-
- @Autowired
- private CustomerRepository customerRepository;
-
- @Autowired
- private SequenceGenerator sequenceGenerator;
-
- @Autowired
- private PointsService pointsService;
-
- public CustomerResponse createCustomer(CustomerDTO dto) {
- // 1. 验证手机号是否已存在
- validatePhone(dto.getPhone());
-
- // 2. 生成客户编号
- String code = sequenceGenerator.generateCustomerCode();
-
- // 3. 创建客户信息
- Customer customer = new Customer();
- BeanUtils.copyProperties(dto, customer);
- customer.setCode(code);
- customer.setLevel(CustomerLevel.NORMAL);
- customer.setPoints(0);
- customer.setStatus(1);
-
- // 4. 保存客户信息
- customer = customerRepository.save(customer);
-
- // 5. 处理车辆信息
- if (dto.getVehicles() != null && !dto.getVehicles().isEmpty()) {
- List<Vehicle> vehicles = createVehicles(dto.getVehicles(), customer);
- customer.setVehicles(vehicles);
- }
-
- return buildResponse(customer);
- }
-
- public void updateCustomer(Long id, CustomerUpdateDTO dto) {
- Customer customer = customerRepository.findById(id)
- .orElseThrow(() -> new BusinessException("客户不存在"));
-
- // 1. 如果修改手机号,需要验证唯一性
- if (!customer.getPhone().equals(dto.getPhone())) {
- validatePhone(dto.getPhone());
- }
-
- // 2. 更新客户信息
- BeanUtils.copyProperties(dto, customer);
- customerRepository.save(customer);
- }
-
- public CustomerDetailResponse getCustomerDetail(Long id) {
- Customer customer = customerRepository.findById(id)
- .orElseThrow(() -> new BusinessException("客户不存在"));
-
- // 1. 获取客户基本信息
- CustomerDetailResponse response = buildDetailResponse(customer);
-
- // 2. 获取车辆信息
- List<VehicleVO> vehicles = getCustomerVehicles(id);
- response.setVehicles(vehicles);
-
- // 3. 获取最近维修记录
- List<ServiceRecordVO> serviceRecords = getRecentServiceRecords(id);
- response.setServiceRecords(serviceRecords);
-
- // 4. 获取积分明细
- List<PointsTransactionVO> pointsHistory = getPointsHistory(id);
- response.setPointsHistory(pointsHistory);
-
- return response;
- }
-
- @Cacheable(value = "customerLevel", key = "#customerId")
- public CustomerLevel calculateCustomerLevel(Long customerId) {
- // 1. 获取消费总额
- BigDecimal totalAmount = serviceRecordRepository
- .calculateTotalAmount(customerId);
-
- // 2. 计算客户等级
- return CustomerLevel.calculateLevel(totalAmount);
- }
- }
复制代码 4. 车辆服务实现
- @Service
- @Transactional
- public class VehicleService {
-
- @Autowired
- private VehicleRepository vehicleRepository;
-
- @Autowired
- private ServiceRecordRepository serviceRecordRepository;
-
- public VehicleResponse addVehicle(VehicleDTO dto) {
- // 1. 验证车牌号是否已存在
- validatePlateNumber(dto.getPlateNumber());
-
- // 2. 创建车辆信息
- Vehicle vehicle = new Vehicle();
- BeanUtils.copyProperties(dto, vehicle);
-
- // 3. 保存车辆信息
- vehicle = vehicleRepository.save(vehicle);
-
- return buildResponse(vehicle);
- }
-
- public void updateVehicle(Long id, VehicleUpdateDTO dto) {
- Vehicle vehicle = vehicleRepository.findById(id)
- .orElseThrow(() -> new BusinessException("车辆不存在"));
-
- // 1. 如果修改车牌号,需要验证唯一性
- if (!vehicle.getPlateNumber().equals(dto.getPlateNumber())) {
- validatePlateNumber(dto.getPlateNumber());
- }
-
- // 2. 更新车辆信息
- BeanUtils.copyProperties(dto, vehicle);
- vehicleRepository.save(vehicle);
- }
-
- public VehicleDetailResponse getVehicleDetail(Long id) {
- Vehicle vehicle = vehicleRepository.findById(id)
- .orElseThrow(() -> new BusinessException("车辆不存在"));
-
- // 1. 获取车辆基本信息
- VehicleDetailResponse response = buildDetailResponse(vehicle);
-
- // 2. 获取维修记录
- List<ServiceRecordVO> serviceRecords = getServiceRecords(id);
- response.setServiceRecords(serviceRecords);
-
- // 3. 获取保养提醒
- List<MaintenanceReminderVO> reminders = calculateMaintenanceReminders(vehicle);
- response.setMaintenanceReminders(reminders);
-
- return response;
- }
-
- private List<MaintenanceReminderVO> calculateMaintenanceReminders(Vehicle vehicle) {
- List<MaintenanceReminderVO> reminders = new ArrayList<>();
-
- // 1. 常规保养提醒(按里程)
- if (vehicle.getMileage() != null) {
- int nextServiceMileage = calculateNextServiceMileage(vehicle.getMileage());
- reminders.add(new MaintenanceReminderVO(
- "常规保养",
- "行驶里程达到" + nextServiceMileage + "公里时建议进行保养"
- ));
- }
-
- // 2. 保险到期提醒
- if (vehicle.getInsuranceExpiry() != null) {
- LocalDate today = LocalDate.now();
- long daysUntilExpiry = ChronoUnit.DAYS.between(today, vehicle.getInsuranceExpiry());
-
- if (daysUntilExpiry <= 30) {
- reminders.add(new MaintenanceReminderVO(
- "保险到期提醒",
- "保险将在" + daysUntilExpiry + "天后到期"
- ));
- }
- }
-
- return reminders;
- }
- }
复制代码 5. 积分服务实现
- @Service
- @Transactional
- public class PointsService {
-
- @Autowired
- private CustomerRepository customerRepository;
-
- @Autowired
- private PointsTransactionRepository transactionRepository;
-
- public void addPoints(PointsAddDTO dto) {
- Customer customer = customerRepository.findById(dto.getCustomerId())
- .orElseThrow(() -> new BusinessException("客户不存在"));
-
- // 1. 计算积分变动
- int beforePoints = customer.getPoints();
- int afterPoints = beforePoints + dto.getPoints();
-
- // 2. 更新客户积分
- customer.setPoints(afterPoints);
- customerRepository.save(customer);
-
- // 3. 记录积分变动
- savePointsTransaction(
- customer.getId(),
- PointsTransactionType.EARN,
- dto.getPoints(),
- beforePoints,
- afterPoints,
- dto.getReferenceNo(),
- dto.getRemark()
- );
-
- // 4. 检查等级变更
- checkAndUpdateLevel(customer);
- }
-
- public void deductPoints(PointsDeductDTO dto) {
- Customer customer = customerRepository.findById(dto.getCustomerId())
- .orElseThrow(() -> new BusinessException("客户不存在"));
-
- // 1. 验证积分是否足够
- if (customer.getPoints() < dto.getPoints()) {
- throw new BusinessException("积分不足");
- }
-
- // 2. 计算积分变动
- int beforePoints = customer.getPoints();
- int afterPoints = beforePoints - dto.getPoints();
-
- // 3. 更新客户积分
- customer.setPoints(afterPoints);
- customerRepository.save(customer);
-
- // 4. 记录积分变动
- savePointsTransaction(
- customer.getId(),
- PointsTransactionType.CONSUME,
- -dto.getPoints(),
- beforePoints,
- afterPoints,
- dto.getReferenceNo(),
- dto.getRemark()
- );
- }
-
- public PointsStatisticsResponse getPointsStatistics(Long customerId) {
- // 1. 获取当前积分
- Customer customer = customerRepository.findById(customerId)
- .orElseThrow(() -> new BusinessException("客户不存在"));
-
- // 2. 获取积分汇总信息
- PointsSummaryVO summary = calculatePointsSummary(customerId);
-
- // 3. 获取近期积分变动
- List<PointsTransactionVO> recentTransactions =
- getRecentTransactions(customerId);
-
- return PointsStatisticsResponse.builder()
- .currentPoints(customer.getPoints())
- .summary(summary)
- .recentTransactions(recentTransactions)
- .build();
- }
-
- private void checkAndUpdateLevel(Customer customer) {
- CustomerLevel newLevel = customerService.calculateCustomerLevel(customer.getId());
- if (newLevel != customer.getLevel()) {
- // 更新客户等级
- customer.setLevel(newLevel);
- customerRepository.save(customer);
-
- // 发送等级变更通知
- notificationService.sendLevelChangeNotification(customer);
- }
- }
- }
复制代码 6. 维修记录查询服务
- @Service
- public class ServiceRecordQueryService {
-
- @Autowired
- private ServiceRecordRepository serviceRecordRepository;
-
- public Page<ServiceRecordVO> queryServiceRecords(ServiceRecordQueryDTO query) {
- // 1. 构建查询条件
- Specification<ServiceRecord> spec = buildSpecification(query);
-
- // 2. 创建分页对象
- PageRequest pageRequest = PageRequest.of(
- query.getPageNum(),
- query.getPageSize(),
- Sort.by(Sort.Direction.DESC, "serviceDate")
- );
-
- // 3. 执行查询
- Page<ServiceRecord> page = serviceRecordRepository.findAll(spec, pageRequest);
-
- // 4. 转换响应
- return page.map(this::convertToVO);
- }
-
- public ServiceRecordDetailResponse getServiceRecordDetail(Long id) {
- ServiceRecord record = serviceRecordRepository.findById(id)
- .orElseThrow(() -> new BusinessException("维修记录不存在"));
-
- // 1. 获取基本信息
- ServiceRecordDetailResponse response = buildDetailResponse(record);
-
- // 2. 获取服务项目明细
- List<ServiceItemVO> items = getServiceItems(record);
- response.setItems(items);
-
- // 3. 获取配件使用记录
- List<PartUsageVO> partUsages = getPartUsages(record);
- response.setPartUsages(partUsages);
-
- return response;
- }
-
- public List<ServiceStatisticsVO> getServiceStatistics(Long customerId) {
- // 1. 获取维修频次统计
- Map<String, Long> serviceFrequency = calculateServiceFrequency(customerId);
-
- // 2. 获取维修金额统计
- Map<String, BigDecimal> serviceAmount = calculateServiceAmount(customerId);
-
- // 3. 获取常见维修项目
- List<CommonServiceItemVO> commonItems = getCommonServiceItems(customerId);
-
- return buildStatisticsResponse(serviceFrequency, serviceAmount, commonItems);
- }
- }
复制代码 7. 客户查询接口实现
- @RestController
- @RequestMapping("/api/customers")
- public class CustomerController {
-
- @Autowired
- private CustomerService customerService;
-
- @Autowired
- private VehicleService vehicleService;
-
- @Autowired
- private PointsService pointsService;
-
- @PostMapping
- public Result<CustomerResponse> createCustomer(@RequestBody @Valid CustomerDTO dto) {
- CustomerResponse response = customerService.createCustomer(dto);
- return Result.success(response);
- }
-
- @PutMapping("/{id}")
- public Result<Void> updateCustomer(
- @PathVariable Long id,
- @RequestBody @Valid CustomerUpdateDTO dto) {
- customerService.updateCustomer(id, dto);
- return Result.success();
- }
-
- @GetMapping("/{id}")
- public Result<CustomerDetailResponse> getCustomerDetail(@PathVariable Long id) {
- CustomerDetailResponse detail = customerService.getCustomerDetail(id);
- return Result.success(detail);
- }
-
- @PostMapping("/{id}/vehicles")
- public Result<VehicleResponse> addVehicle(
- @PathVariable Long id,
- @RequestBody @Valid VehicleDTO dto) {
- dto.setCustomerId(id);
- VehicleResponse response = vehicleService.addVehicle(dto);
- return Result.success(response);
- }
-
- @PostMapping("/{id}/points/add")
- public Result<Void> addPoints(
- @PathVariable Long id,
- @RequestBody @Valid PointsAddDTO dto) {
- dto.setCustomerId(id);
- pointsService.addPoints(dto);
- return Result.success();
- }
-
- @GetMapping("/{id}/points/statistics")
- public Result<PointsStatisticsResponse> getPointsStatistics(@PathVariable Long id) {
- PointsStatisticsResponse statistics = pointsService.getPointsStatistics(id);
- return Result.success(statistics);
- }
-
- @GetMapping("/{id}/service-records")
- public Result<Page<ServiceRecordVO>> getServiceRecords(
- @PathVariable Long id,
- ServiceRecordQueryDTO query) {
- query.setCustomerId(id);
- Page<ServiceRecordVO> page = serviceRecordQueryService.queryServiceRecords(query);
- return Result.success(page);
- }
- }
复制代码 这些代码实现了客户管理的核心功能,包罗:
- 客户信息的CRUD操作
- 车辆信息管理
- 维修记录查询
- 积分管理和品级盘算
- 统计分析功能
关键特点:
- 完整的客户生命周期管理
- 车辆信息关联
- 维修记录追踪
- 积分变动记录
- 客户品级自动盘算
- 保养提示功能
员工管理模块的核心代码实现
1. 数据库设计
- -- 员工信息表
- CREATE TABLE employee (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- code VARCHAR(32) UNIQUE NOT NULL COMMENT '员工编号',
- name VARCHAR(50) NOT NULL COMMENT '姓名',
- gender TINYINT NOT NULL COMMENT '性别: 0-女 1-男',
- id_card VARCHAR(18) UNIQUE NOT NULL COMMENT '身份证号',
- phone VARCHAR(20) NOT NULL COMMENT '联系电话',
- email VARCHAR(100) COMMENT '邮箱',
- address TEXT COMMENT '住址',
- job_type_id BIGINT NOT NULL COMMENT '工种ID',
- department_id BIGINT NOT NULL COMMENT '部门ID',
- entry_date DATE NOT NULL COMMENT '入职日期',
- leave_date DATE COMMENT '离职日期',
- status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 0-离职 1-在职',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
- );
- -- 工种分类表
- CREATE TABLE job_type (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- name VARCHAR(50) NOT NULL COMMENT '工种名称',
- description TEXT COMMENT '工种描述',
- base_salary DECIMAL(10,2) NOT NULL COMMENT '基本工资',
- commission_rate DECIMAL(5,2) COMMENT '提成比例',
- status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 0-禁用 1-启用',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- -- 工作量记录表
- CREATE TABLE work_record (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- employee_id BIGINT NOT NULL COMMENT '员工ID',
- work_order_id BIGINT NOT NULL COMMENT '工单ID',
- service_item_id BIGINT NOT NULL COMMENT '服务项目ID',
- work_hours DECIMAL(5,2) NOT NULL COMMENT '工时',
- amount DECIMAL(10,2) NOT NULL COMMENT '金额',
- commission DECIMAL(10,2) NOT NULL COMMENT '提成金额',
- work_date DATE NOT NULL COMMENT '工作日期',
- status TINYINT NOT NULL DEFAULT 1 COMMENT '状态',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (employee_id) REFERENCES employee(id)
- );
- -- 绩效考核表
- CREATE TABLE performance_evaluation (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- employee_id BIGINT NOT NULL COMMENT '员工ID',
- evaluation_month VARCHAR(7) NOT NULL COMMENT '考核月份 YYYY-MM',
- work_quality_score INT NOT NULL COMMENT '工作质量得分',
- work_attitude_score INT NOT NULL COMMENT '工作态度得分',
- customer_feedback_score INT NOT NULL COMMENT '客户反馈得分',
- total_score INT NOT NULL COMMENT '总分',
- evaluator_id BIGINT NOT NULL COMMENT '评估人ID',
- evaluation_date DATE NOT NULL COMMENT '评估日期',
- remark TEXT COMMENT '评语',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (employee_id) REFERENCES employee(id),
- UNIQUE KEY `uk_employee_month` (`employee_id`, `evaluation_month`)
- );
- -- 考核指标表
- CREATE TABLE evaluation_criteria (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- name VARCHAR(50) NOT NULL COMMENT '指标名称',
- category VARCHAR(50) NOT NULL COMMENT '指标类别',
- description TEXT COMMENT '指标描述',
- weight INT NOT NULL COMMENT '权重',
- max_score INT NOT NULL COMMENT '最高分',
- status TINYINT NOT NULL DEFAULT 1 COMMENT '状态',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
复制代码 2. 实体类设计
- @Data
- @Entity
- @Table(name = "employee")
- public class Employee {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String code;
- private String name;
- private Integer gender;
- private String idCard;
- private String phone;
- private String email;
- private String address;
- private Long jobTypeId;
- private Long departmentId;
- private LocalDate entryDate;
- private LocalDate leaveDate;
- private Integer status;
-
- @ManyToOne
- @JoinColumn(name = "job_type_id", insertable = false, updatable = false)
- private JobType jobType;
- }
- @Data
- @Entity
- @Table(name = "job_type")
- public class JobType {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String name;
- private String description;
- private BigDecimal baseSalary;
- private BigDecimal commissionRate;
- private Integer status;
- }
- @Data
- @Entity
- @Table(name = "performance_evaluation")
- public class PerformanceEvaluation {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private Long employeeId;
- private String evaluationMonth;
- private Integer workQualityScore;
- private Integer workAttitudeScore;
- private Integer customerFeedbackScore;
- private Integer totalScore;
- private Long evaluatorId;
- private LocalDate evaluationDate;
- private String remark;
- }
复制代码 3. 员工服务实现
- @Service
- @Transactional
- public class EmployeeService {
-
- @Autowired
- private EmployeeRepository employeeRepository;
-
- @Autowired
- private SequenceGenerator sequenceGenerator;
-
- public EmployeeResponse createEmployee(EmployeeDTO dto) {
- // 1. 验证身份证号是否已存在
- validateIdCard(dto.getIdCard());
-
- // 2. 生成员工编号
- String code = sequenceGenerator.generateEmployeeCode();
-
- // 3. 创建员工信息
- Employee employee = new Employee();
- BeanUtils.copyProperties(dto, employee);
- employee.setCode(code);
- employee.setStatus(1);
-
- // 4. 保存员工信息
- employee = employeeRepository.save(employee);
-
- // 5. 创建系统账号
- createUserAccount(employee);
-
- return buildResponse(employee);
- }
-
- public void updateEmployee(Long id, EmployeeUpdateDTO dto) {
- Employee employee = employeeRepository.findById(id)
- .orElseThrow(() -> new BusinessException("员工不存在"));
-
- // 1. 如果修改身份证号,需要验证唯一性
- if (!employee.getIdCard().equals(dto.getIdCard())) {
- validateIdCard(dto.getIdCard());
- }
-
- // 2. 更新员工信息
- BeanUtils.copyProperties(dto, employee);
- employeeRepository.save(employee);
- }
-
- public void handleEmployeeResignation(Long id, ResignationDTO dto) {
- Employee employee = employeeRepository.findById(id)
- .orElseThrow(() -> new BusinessException("员工不存在"));
-
- // 1. 设置离职信息
- employee.setLeaveDate(dto.getLeaveDate());
- employee.setStatus(0);
-
- // 2. 更新员工状态
- employeeRepository.save(employee);
-
- // 3. 处理相关系统账号
- disableUserAccount(employee.getCode());
-
- // 4. 记录离职信息
- saveResignationRecord(employee, dto);
- }
-
- private void createUserAccount(Employee employee) {
- UserCreateDTO userDto = UserCreateDTO.builder()
- .username(employee.getCode())
- .name(employee.getName())
- .phone(employee.getPhone())
- .email(employee.getEmail())
- .roleIds(getRolesByJobType(employee.getJobTypeId()))
- .build();
-
- userService.createUser(userDto);
- }
- }
复制代码 4. 工种管理服务实现
- @Service
- @Transactional
- public class JobTypeService {
-
- @Autowired
- private JobTypeRepository jobTypeRepository;
-
- public JobTypeResponse createJobType(JobTypeDTO dto) {
- // 1. 验证工种名称是否已存在
- validateJobTypeName(dto.getName());
-
- // 2. 创建工种信息
- JobType jobType = new JobType();
- BeanUtils.copyProperties(dto, jobType);
- jobType.setStatus(1);
-
- // 3. 保存工种信息
- jobType = jobTypeRepository.save(jobType);
-
- return buildResponse(jobType);
- }
-
- public void updateJobType(Long id, JobTypeUpdateDTO dto) {
- JobType jobType = jobTypeRepository.findById(id)
- .orElseThrow(() -> new BusinessException("工种不存在"));
-
- // 1. 如果修改名称,需要验证唯一性
- if (!jobType.getName().equals(dto.getName())) {
- validateJobTypeName(dto.getName());
- }
-
- // 2. 更新工种信息
- BeanUtils.copyProperties(dto, jobType);
- jobTypeRepository.save(jobType);
- }
-
- public void updateCommissionRate(Long id, BigDecimal newRate) {
- JobType jobType = jobTypeRepository.findById(id)
- .orElseThrow(() -> new BusinessException("工种不存在"));
-
- // 1. 验证提成比例
- if (newRate.compareTo(BigDecimal.ZERO) < 0 ||
- newRate.compareTo(BigDecimal.valueOf(100)) > 0) {
- throw new BusinessException("提成比例必须在0-100之间");
- }
-
- // 2. 更新提成比例
- jobType.setCommissionRate(newRate);
- jobTypeRepository.save(jobType);
- }
- }
复制代码 5. 工作量统计服务实现
- @Service
- public class WorkloadStatisticsService {
-
- @Autowired
- private WorkRecordRepository workRecordRepository;
-
- public WorkloadStatisticsResponse getEmployeeWorkload(
- Long employeeId, LocalDate startDate, LocalDate endDate) {
- // 1. 获取工作量汇总
- WorkloadSummaryVO summary = calculateWorkloadSummary(employeeId, startDate, endDate);
-
- // 2. 获取每日工作量
- List<DailyWorkloadVO> dailyWorkloads =
- calculateDailyWorkload(employeeId, startDate, endDate);
-
- // 3. 获取项目分布
- List<ServiceItemDistributionVO> itemDistribution =
- calculateServiceItemDistribution(employeeId, startDate, endDate);
-
- return WorkloadStatisticsResponse.builder()
- .summary(summary)
- .dailyWorkloads(dailyWorkloads)
- .itemDistribution(itemDistribution)
- .build();
- }
-
- public Page<WorkRecordVO> queryWorkRecords(WorkRecordQueryDTO query) {
- // 1. 构建查询条件
- Specification<WorkRecord> spec = buildSpecification(query);
-
- // 2. 创建分页对象
- PageRequest pageRequest = PageRequest.of(
- query.getPageNum(),
- query.getPageSize(),
- Sort.by(Sort.Direction.DESC, "workDate")
- );
-
- // 3. 执行查询
- Page<WorkRecord> page = workRecordRepository.findAll(spec, pageRequest);
-
- // 4. 转换响应
- return page.map(this::convertToVO);
- }
-
- private WorkloadSummaryVO calculateWorkloadSummary(
- Long employeeId, LocalDate startDate, LocalDate endDate) {
- // 1. 计算总工时
- BigDecimal totalHours = workRecordRepository
- .sumWorkHours(employeeId, startDate, endDate);
-
- // 2. 计算总金额
- BigDecimal totalAmount = workRecordRepository
- .sumAmount(employeeId, startDate, endDate);
-
- // 3. 计算总提成
- BigDecimal totalCommission = workRecordRepository
- .sumCommission(employeeId, startDate, endDate);
-
- // 4. 计算完成工单数
- Long orderCount = workRecordRepository
- .countWorkOrders(employeeId, startDate, endDate);
-
- return WorkloadSummaryVO.builder()
- .totalHours(totalHours)
- .totalAmount(totalAmount)
- .totalCommission(totalCommission)
- .orderCount(orderCount)
- .build();
- }
- }
复制代码 6. 绩效考核服务实现
- @Service
- @Transactional
- public class PerformanceEvaluationService {
-
- @Autowired
- private PerformanceEvaluationRepository evaluationRepository;
-
- @Autowired
- private EvaluationCriteriaRepository criteriaRepository;
-
- public void createEvaluation(PerformanceEvaluationDTO dto) {
- // 1. 验证是否已存在当月考核
- validateMonthlyEvaluation(dto.getEmployeeId(), dto.getEvaluationMonth());
-
- // 2. 计算总分
- int totalScore = calculateTotalScore(dto);
-
- // 3. 创建考核记录
- PerformanceEvaluation evaluation = new PerformanceEvaluation();
- BeanUtils.copyProperties(dto, evaluation);
- evaluation.setTotalScore(totalScore);
- evaluation.setEvaluationDate(LocalDate.now());
- evaluation.setEvaluatorId(SecurityUtils.getCurrentUserId());
-
- // 4. 保存考核记录
- evaluationRepository.save(evaluation);
-
- // 5. 处理绩效奖金
- handlePerformanceBonus(evaluation);
- }
-
- public PerformanceStatisticsResponse getPerformanceStatistics(
- Long employeeId, String startMonth, String endMonth) {
- // 1. 获取考核汇总
- PerformanceSummaryVO summary =
- calculatePerformanceSummary(employeeId, startMonth, endMonth);
-
- // 2. 获取月度考核趋势
- List<MonthlyPerformanceVO> monthlyTrend =
- calculateMonthlyTrend(employeeId, startMonth, endMonth);
-
- // 3. 获取各项得分分布
- List<ScoreDistributionVO> scoreDistribution =
- calculateScoreDistribution(employeeId, startMonth, endMonth);
-
- return PerformanceStatisticsResponse.builder()
- .summary(summary)
- .monthlyTrend(monthlyTrend)
- .scoreDistribution(scoreDistribution)
- .build();
- }
-
- private void handlePerformanceBonus(PerformanceEvaluation evaluation) {
- // 1. 获取员工信息
- Employee employee = employeeRepository.findById(evaluation.getEmployeeId())
- .orElseThrow();
-
- // 2. 获取工种信息
- JobType jobType = jobTypeRepository.findById(employee.getJobTypeId())
- .orElseThrow();
-
- // 3. 计算绩效奖金
- BigDecimal bonus = calculatePerformanceBonus(
- evaluation.getTotalScore(),
- jobType.getBaseSalary()
- );
-
- // 4. 保存奖金记录
- saveBonusRecord(evaluation, bonus);
- }
-
- private int calculateTotalScore(PerformanceEvaluationDTO dto) {
- // 1. 获取考核指标权重
- Map<String, Integer> weights = getEvaluationWeights();
-
- // 2. 计算加权总分
- return dto.getWorkQualityScore() * weights.get("QUALITY") / 100 +
- dto.getWorkAttitudeScore() * weights.get("ATTITUDE") / 100 +
- dto.getCustomerFeedbackScore() * weights.get("FEEDBACK") / 100;
- }
- }
复制代码 7. 员工查询接口实现
- @RestController
- @RequestMapping("/api/employees")
- public class EmployeeController {
-
- @Autowired
- private EmployeeService employeeService;
-
- @Autowired
- private WorkloadStatisticsService workloadService;
-
- @Autowired
- private PerformanceEvaluationService performanceService;
-
- @PostMapping
- public Result<EmployeeResponse> createEmployee(@RequestBody @Valid EmployeeDTO dto) {
- EmployeeResponse response = employeeService.createEmployee(dto);
- return Result.success(response);
- }
-
- @PutMapping("/{id}")
- public Result<Void> updateEmployee(
- @PathVariable Long id,
- @RequestBody @Valid EmployeeUpdateDTO dto) {
- employeeService.updateEmployee(id, dto);
- return Result.success();
- }
-
- @PostMapping("/{id}/resignation")
- public Result<Void> handleResignation(
- @PathVariable Long id,
- @RequestBody @Valid ResignationDTO dto) {
- employeeService.handleEmployeeResignation(id, dto);
- return Result.success();
- }
-
- @GetMapping("/{id}/workload")
- public Result<WorkloadStatisticsResponse> getWorkloadStatistics(
- @PathVariable Long id,
- @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
- @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
- WorkloadStatisticsResponse statistics =
- workloadService.getEmployeeWorkload(id, startDate, endDate);
- return Result.success(statistics);
- }
-
- @PostMapping("/{id}/performance-evaluation")
- public Result<Void> createPerformanceEvaluation(
- @PathVariable Long id,
- @RequestBody @Valid PerformanceEvaluationDTO dto) {
- dto.setEmployeeId(id);
- performanceService.createEvaluation(dto);
- return Result.success();
- }
-
- @GetMapping("/{id}/performance-statistics")
- public Result<PerformanceStatisticsResponse> getPerformanceStatistics(
- @PathVariable Long id,
- @RequestParam String startMonth,
- @RequestParam String endMonth) {
- PerformanceStatisticsResponse statistics =
- performanceService.getPerformanceStatistics(id, startMonth, endMonth);
- return Result.success(statistics);
- }
- }
复制代码 这些代码实现了员工管理的核心功能,包罗:
- 员工信息的CRUD操作
- 工种分类管理
- 工作量统计分析
- 绩效考核管理
关键特点:
- 完整的员工生命周期管理
- 灵活的工种配置
- 具体的工作量记录
- 多维度的绩效考核
- 自动化的提成盘算
- 完满的统计分析功能
财务管理模块的核心代码实现
1. 数据库设计
- -- 财务收支记录表
- CREATE TABLE financial_transaction (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- transaction_no VARCHAR(32) UNIQUE NOT NULL COMMENT '交易编号',
- type VARCHAR(20) NOT NULL COMMENT '交易类型: INCOME/EXPENSE',
- category_id BIGINT NOT NULL COMMENT '类别ID',
- amount DECIMAL(12,2) NOT NULL COMMENT '金额',
- payment_method VARCHAR(20) NOT NULL COMMENT '支付方式',
- transaction_date DATE NOT NULL COMMENT '交易日期',
- reference_no VARCHAR(32) COMMENT '关联单号',
- reference_type VARCHAR(20) COMMENT '关联单据类型',
- operator_id BIGINT NOT NULL COMMENT '操作人',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- -- 收支类别表
- CREATE TABLE transaction_category (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- name VARCHAR(50) NOT NULL COMMENT '类别名称',
- type VARCHAR(20) NOT NULL COMMENT '类型: INCOME/EXPENSE',
- parent_id BIGINT COMMENT '父类别ID',
- status TINYINT NOT NULL DEFAULT 1 COMMENT '状态',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- -- 成本记录表
- CREATE TABLE cost_record (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- cost_type VARCHAR(20) NOT NULL COMMENT '成本类型',
- category_id BIGINT NOT NULL COMMENT '类别ID',
- amount DECIMAL(12,2) NOT NULL COMMENT '金额',
- record_month VARCHAR(7) NOT NULL COMMENT '记录月份 YYYY-MM',
- remark TEXT COMMENT '备注',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
- -- 利润核算表
- CREATE TABLE profit_statement (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- statement_month VARCHAR(7) NOT NULL COMMENT '核算月份 YYYY-MM',
- total_revenue DECIMAL(12,2) NOT NULL COMMENT '总收入',
- total_cost DECIMAL(12,2) NOT NULL COMMENT '总成本',
- gross_profit DECIMAL(12,2) NOT NULL COMMENT '毛利润',
- operating_expenses DECIMAL(12,2) NOT NULL COMMENT '运营费用',
- net_profit DECIMAL(12,2) NOT NULL COMMENT '净利润',
- status VARCHAR(20) NOT NULL COMMENT '状态',
- created_by BIGINT NOT NULL COMMENT '创建人',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- UNIQUE KEY `uk_month` (`statement_month`)
- );
- -- 收入明细表
- CREATE TABLE revenue_detail (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- statement_id BIGINT NOT NULL COMMENT '利润表ID',
- category_id BIGINT NOT NULL COMMENT '收入类别ID',
- amount DECIMAL(12,2) NOT NULL COMMENT '金额',
- percentage DECIMAL(5,2) NOT NULL COMMENT '占比',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (statement_id) REFERENCES profit_statement(id)
- );
- -- 成本明细表
- CREATE TABLE cost_detail (
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
- statement_id BIGINT NOT NULL COMMENT '利润表ID',
- category_id BIGINT NOT NULL COMMENT '成本类别ID',
- amount DECIMAL(12,2) NOT NULL COMMENT '金额',
- percentage DECIMAL(5,2) NOT NULL COMMENT '占比',
- created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (statement_id) REFERENCES profit_statement(id)
- );
复制代码 2. 实体类设计
- @Data
- @Entity
- @Table(name = "financial_transaction")
- public class FinancialTransaction {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String transactionNo;
-
- @Enumerated(EnumType.STRING)
- private TransactionType type;
-
- private Long categoryId;
- private BigDecimal amount;
-
- @Enumerated(EnumType.STRING)
- private PaymentMethod paymentMethod;
-
- private LocalDate transactionDate;
- private String referenceNo;
- private String referenceType;
- private Long operatorId;
- private String remark;
-
- @ManyToOne
- @JoinColumn(name = "category_id", insertable = false, updatable = false)
- private TransactionCategory category;
- }
- @Data
- @Entity
- @Table(name = "profit_statement")
- public class ProfitStatement {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String statementMonth;
- private BigDecimal totalRevenue;
- private BigDecimal totalCost;
- private BigDecimal grossProfit;
- private BigDecimal operatingExpenses;
- private BigDecimal netProfit;
-
- @Enumerated(EnumType.STRING)
- private StatementStatus status;
-
- private Long createdBy;
-
- @OneToMany(mappedBy = "statement", cascade = CascadeType.ALL)
- private List<RevenueDetail> revenueDetails;
-
- @OneToMany(mappedBy = "statement", cascade = CascadeType.ALL)
- private List<CostDetail> costDetails;
- }
复制代码 3. 财务买卖业务服务实现
- @Service
- @Transactional
- public class FinancialTransactionService {
-
- @Autowired
- private FinancialTransactionRepository transactionRepository;
-
- @Autowired
- private SequenceGenerator sequenceGenerator;
-
- public TransactionResponse recordTransaction(TransactionDTO dto) {
- // 1. 生成交易编号
- String transactionNo = sequenceGenerator.generateTransactionNo();
-
- // 2. 创建交易记录
- FinancialTransaction transaction = new FinancialTransaction();
- BeanUtils.copyProperties(dto, transaction);
- transaction.setTransactionNo(transactionNo);
- transaction.setOperatorId(SecurityUtils.getCurrentUserId());
-
- // 3. 保存交易记录
- transaction = transactionRepository.save(transaction);
-
- // 4. 更新相关统计数据
- updateStatistics(transaction);
-
- return buildResponse(transaction);
- }
-
- public Page<TransactionVO> queryTransactions(TransactionQueryDTO query) {
- // 1. 构建查询条件
- Specification<FinancialTransaction> spec = buildSpecification(query);
-
- // 2. 创建分页对象
- PageRequest pageRequest = PageRequest.of(
- query.getPageNum(),
- query.getPageSize(),
- Sort.by(Sort.Direction.DESC, "transactionDate")
- );
-
- // 3. 执行查询
- Page<FinancialTransaction> page = transactionRepository.findAll(spec, pageRequest);
-
- // 4. 转换响应
- return page.map(this::convertToVO);
- }
-
- public TransactionStatisticsResponse getStatistics(
- LocalDate startDate, LocalDate endDate) {
- // 1. 获取收入统计
- List<CategoryStatisticsVO> incomeStats =
- calculateCategoryStatistics(TransactionType.INCOME, startDate, endDate);
-
- // 2. 获取支出统计
- List<CategoryStatisticsVO> expenseStats =
- calculateCategoryStatistics(TransactionType.EXPENSE, startDate, endDate);
-
- // 3. 获取支付方式统计
- List<PaymentMethodStatisticsVO> paymentStats =
- calculatePaymentMethodStatistics(startDate, endDate);
-
- return TransactionStatisticsResponse.builder()
- .incomeStatistics(incomeStats)
- .expenseStatistics(expenseStats)
- .paymentMethodStatistics(paymentStats)
- .build();
- }
-
- private void updateStatistics(FinancialTransaction transaction) {
- // 1. 更新日统计
- updateDailyStatistics(transaction);
-
- // 2. 更新月统计
- updateMonthlyStatistics(transaction);
-
- // 3. 更新类别统计
- updateCategoryStatistics(transaction);
- }
- }
复制代码 4. 营收报表服务实现
- @Service
- public class RevenueReportService {
-
- @Autowired
- private FinancialTransactionRepository transactionRepository;
-
- public RevenueReportResponse generateMonthlyReport(String month) {
- // 1. 获取收入汇总
- RevenueSummaryVO summary = calculateRevenueSummary(month);
-
- // 2. 获取收入趋势
- List<DailyRevenueVO> dailyTrend = calculateDailyRevenue(month);
-
- // 3. 获取收入构成
- List<RevenueCategoryVO> categoryDistribution =
- calculateCategoryDistribution(month);
-
- // 4. 获取同比环比数据
- ComparisonDataVO comparison = calculateComparison(month);
-
- return RevenueReportResponse.builder()
- .summary(summary)
- .dailyTrend(dailyTrend)
- .categoryDistribution(categoryDistribution)
- .comparison(comparison)
- .build();
- }
-
- private RevenueSummaryVO calculateRevenueSummary(String month) {
- // 1. 计算总收入
- BigDecimal totalRevenue = transactionRepository
- .sumByTypeAndMonth(TransactionType.INCOME, month);
-
- // 2. 计算服务收入
- BigDecimal serviceRevenue = transactionRepository
- .sumByCategoryAndMonth(Arrays.asList(1L, 2L), month);
-
- // 3. 计算配件收入
- BigDecimal partsRevenue = transactionRepository
- .sumByCategoryAndMonth(Arrays.asList(3L), month);
-
- // 4. 计算其他收入
- BigDecimal otherRevenue = totalRevenue
- .subtract(serviceRevenue)
- .subtract(partsRevenue);
-
- return RevenueSummaryVO.builder()
- .totalRevenue(totalRevenue)
- .serviceRevenue(serviceRevenue)
- .partsRevenue(partsRevenue)
- .otherRevenue(otherRevenue)
- .build();
- }
- }
复制代码 5. 成本分析服务实现
- @Service
- public class CostAnalysisService {
-
- @Autowired
- private CostRecordRepository costRecordRepository;
-
- public CostAnalysisResponse analyzeMonthlyCost(String month) {
- // 1. 获取成本汇总
- CostSummaryVO summary = calculateCostSummary(month);
-
- // 2. 获取成本构成
- List<CostCategoryVO> categoryAnalysis = analyzeCostCategory(month);
-
- // 3. 获取成本趋势
- List<MonthlyCostTrendVO> costTrend = analyzeCostTrend(month);
-
- // 4. 计算成本比率
- List<CostRatioVO> costRatios = calculateCostRatios(month);
-
- return CostAnalysisResponse.builder()
- .summary(summary)
- .categoryAnalysis(categoryAnalysis)
- .costTrend(costTrend)
- .costRatios(costRatios)
- .build();
- }
-
- private List<CostRatioVO> calculateCostRatios(String month) {
- List<CostRatioVO> ratios = new ArrayList<>();
-
- // 1. 获取总收入
- BigDecimal totalRevenue = revenueService.calculateMonthlyRevenue(month);
-
- // 2. 获取各类成本
- Map<String, BigDecimal> costMap = costRecordRepository
- .getCostsByTypeAndMonth(month);
-
- // 3. 计算各项成本比率
- for (Map.Entry<String, BigDecimal> entry : costMap.entrySet()) {
- BigDecimal ratio = BigDecimal.ZERO;
- if (totalRevenue.compareTo(BigDecimal.ZERO) > 0) {
- ratio = entry.getValue()
- .divide(totalRevenue, 4, RoundingMode.HALF_UP)
- .multiply(BigDecimal.valueOf(100));
- }
-
- ratios.add(new CostRatioVO(
- entry.getKey(),
- entry.getValue(),
- ratio
- ));
- }
-
- return ratios;
- }
- }
复制代码 6. 利润核算服务实现
- @Service
- @Transactional
- public class ProfitStatementService {
-
- @Autowired
- private ProfitStatementRepository statementRepository;
-
- @Autowired
- private RevenueReportService revenueService;
-
- @Autowired
- private CostAnalysisService costService;
-
- public void generateMonthlyStatement(String month) {
- // 1. 验证月份是否已生成报表
- validateMonth(month);
-
- // 2. 创建利润表
- ProfitStatement statement = new ProfitStatement();
- statement.setStatementMonth(month);
- statement.setStatus(StatementStatus.DRAFT);
- statement.setCreatedBy(SecurityUtils.getCurrentUserId());
-
- // 3. 计算收入数据
- calculateRevenue(statement);
-
- // 4. 计算成本数据
- calculateCost(statement);
-
- // 5. 计算利润数据
- calculateProfit(statement);
-
- // 6. 保存利润表
- statement = statementRepository.save(statement);
-
- // 7. 生成明细数据
- generateDetails(statement);
- }
-
- public void approveStatement(Long id) {
- ProfitStatement statement = statementRepository.findById(id)
- .orElseThrow(() -> new BusinessException("利润表不存在"));
-
- // 1. 验证状态
- if (statement.getStatus() != StatementStatus.DRAFT) {
- throw new BusinessException("只有草稿状态的利润表可以审批");
- }
-
- // 2. 更新状态
- statement.setStatus(StatementStatus.APPROVED);
- statementRepository.save(statement);
-
- // 3. 生成财务凭证
- generateVoucher(statement);
- }
-
- public ProfitAnalysisResponse analyzeProfitTrend(
- String startMonth, String endMonth) {
- // 1. 获取利润趋势
- List<MonthlyProfitVO> profitTrend =
- calculateProfitTrend(startMonth, endMonth);
-
- // 2. 计算利润率
- List<ProfitRatioVO> profitRatios =
- calculateProfitRatios(startMonth, endMonth);
-
- // 3. 计算同比数据
- List<YearOverYearVO> yearOverYear =
- calculateYearOverYear(startMonth, endMonth);
-
- return ProfitAnalysisResponse.builder()
- .profitTrend(profitTrend)
- .profitRatios(profitRatios)
- .yearOverYear(yearOverYear)
- .build();
- }
-
- private void calculateProfit(ProfitStatement statement) {
- // 1. 计算毛利润
- BigDecimal grossProfit = statement.getTotalRevenue()
- .subtract(statement.getTotalCost());
- statement.setGrossProfit(grossProfit);
-
- // 2. 计算净利润
- BigDecimal netProfit = grossProfit
- .subtract(statement.getOperatingExpenses());
- statement.setNetProfit(netProfit);
- }
- }
复制代码 7. 财务报表接口实现
- @RestController
- @RequestMapping("/api/finance")
- public class FinanceController {
-
- @Autowired
- private FinancialTransactionService transactionService;
-
- @Autowired
- private RevenueReportService revenueService;
-
- @Autowired
- private CostAnalysisService costService;
-
- @Autowired
- private ProfitStatementService profitService;
-
- @PostMapping("/transactions")
- public Result<TransactionResponse> recordTransaction(
- @RequestBody @Valid TransactionDTO dto) {
- TransactionResponse response = transactionService.recordTransaction(dto);
- return Result.success(response);
- }
-
- @GetMapping("/transactions/statistics")
- public Result<TransactionStatisticsResponse> getTransactionStatistics(
- @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
- @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
- TransactionStatisticsResponse statistics =
- transactionService.getStatistics(startDate, endDate);
- return Result.success(statistics);
- }
-
- @GetMapping("/revenue/monthly-report")
- public Result<RevenueReportResponse> getMonthlyRevenueReport(
- @RequestParam String month) {
- RevenueReportResponse report = revenueService.generateMonthlyReport(month);
- return Result.success(report);
- }
-
- @GetMapping("/cost/analysis")
- public Result<CostAnalysisResponse> getCostAnalysis(
- @RequestParam String month) {
- CostAnalysisResponse analysis = costService.analyzeMonthlyCost(month);
- return Result.success(analysis);
- }
-
- @PostMapping("/profit-statements")
- public Result<Void> generateProfitStatement(@RequestParam String month) {
- profitService.generateMonthlyStatement(month);
- return Result.success();
- }
-
- @PostMapping("/profit-statements/{id}/approve")
- public Result<Void> approveProfitStatement(@PathVariable Long id) {
- profitService.approveStatement(id);
- return Result.success();
- }
-
- @GetMapping("/profit/analysis")
- public Result<ProfitAnalysisResponse> getProfitAnalysis(
- @RequestParam String startMonth,
- @RequestParam String endMonth) {
- ProfitAnalysisResponse analysis =
- profitService.analyzeProfitTrend(startMonth, endMonth);
- return Result.success(analysis);
- }
- }
复制代码 这些代码实现了财务管理的核心功能,包罗:
关键特点:
- 完整的财务买卖业务记录
- 多维度的营收分析
- 具体的成本核算
- 自动化的利润盘算
- 完满的报表功能
- 支持同比环比分析
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |