diff --git a/module-mdm/src/main/java/com/ether/pms/mdm/service/SparePartService.java b/module-mdm/src/main/java/com/ether/pms/mdm/service/SparePartService.java new file mode 100644 index 0000000..77c366b --- /dev/null +++ b/module-mdm/src/main/java/com/ether/pms/mdm/service/SparePartService.java @@ -0,0 +1,27 @@ +package com.ether.pms.mdm.service; + +import com.ether.pms.mdm.entity.SparePart; +import com.ether.pms.mdm.entity.SparePartCategory; +import com.ether.pms.mdm.entity.SparePartRecord; +import java.util.List; +import java.util.UUID; + +public interface SparePartService { + // 分类管理 + List getCategories(); + SparePartCategory createCategory(SparePartCategory category); + + // 备件管理 + SparePart createSparePart(SparePart sparePart); + SparePart updateSparePart(UUID id, SparePart sparePart); + void deleteSparePart(UUID id); + SparePart getSparePartById(UUID id); + List getSparePartsByProject(UUID projectId); + List getSparePartsByCategory(UUID categoryId); + List getLowStockParts(UUID projectId); + + // 库存管理 + SparePartRecord inStock(UUID sparePartId, Integer quantity, UUID recordedBy, String remarks); + SparePartRecord outStock(UUID sparePartId, Integer quantity, UUID relatedOrderId, UUID recordedBy, String remarks); + List getSparePartRecords(UUID sparePartId); +} \ No newline at end of file diff --git a/module-mdm/src/main/java/com/ether/pms/mdm/service/impl/SparePartServiceImpl.java b/module-mdm/src/main/java/com/ether/pms/mdm/service/impl/SparePartServiceImpl.java new file mode 100644 index 0000000..700078f --- /dev/null +++ b/module-mdm/src/main/java/com/ether/pms/mdm/service/impl/SparePartServiceImpl.java @@ -0,0 +1,270 @@ +package com.ether.pms.mdm.service.impl; + +import com.ether.pms.common.BusinessException; +import com.ether.pms.mdm.entity.SparePart; +import com.ether.pms.mdm.entity.SparePartCategory; +import com.ether.pms.mdm.entity.SparePartRecord; +import com.ether.pms.mdm.repository.SparePartCategoryRepository; +import com.ether.pms.mdm.repository.SparePartRecordRepository; +import com.ether.pms.mdm.repository.SparePartRepository; +import com.ether.pms.mdm.service.SparePartService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class SparePartServiceImpl implements SparePartService { + + private final SparePartRepository sparePartRepository; + private final SparePartCategoryRepository sparePartCategoryRepository; + private final SparePartRecordRepository sparePartRecordRepository; + + private static final DateTimeFormatter CODE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + + // ==================== 分类管理 ==================== + + @Override + public List getCategories() { + return sparePartCategoryRepository.findAll(); + } + + @Override + @Transactional + public SparePartCategory createCategory(SparePartCategory category) { + // 生成分类编码 CC + 时间戳 + String categoryCode = generateCategoryCode(); + category.setCategoryCode(categoryCode); + return sparePartCategoryRepository.save(category); + } + + // ==================== 备件管理 ==================== + + @Override + @Transactional + public SparePart createSparePart(SparePart sparePart) { + // 生成备件编码 SP + 时间戳 + String sparePartCode = generateSparePartCode(); + sparePart.setSparePartCode(sparePartCode); + + // 设置默认状态为ACTIVE + if (sparePart.getStatus() == null) { + sparePart.setStatus(SparePart.Status.ACTIVE); + } + + // 初始化库存为0 + if (sparePart.getCurrentStock() == null) { + sparePart.setCurrentStock(0); + } + + return sparePartRepository.save(sparePart); + } + + @Override + @Transactional + public SparePart updateSparePart(UUID id, SparePart sparePart) { + SparePart existing = getSparePartById(id); + + if (sparePart.getSparePartName() != null) { + existing.setSparePartName(sparePart.getSparePartName()); + } + if (sparePart.getCategoryId() != null) { + existing.setCategoryId(sparePart.getCategoryId()); + } + if (sparePart.getSpecification() != null) { + existing.setSpecification(sparePart.getSpecification()); + } + if (sparePart.getUnit() != null) { + existing.setUnit(sparePart.getUnit()); + } + if (sparePart.getSafeStock() != null) { + existing.setSafeStock(sparePart.getSafeStock()); + } + if (sparePart.getUnitPrice() != null) { + existing.setUnitPrice(sparePart.getUnitPrice()); + } + if (sparePart.getSupplier() != null) { + existing.setSupplier(sparePart.getSupplier()); + } + if (sparePart.getSupplierContact() != null) { + existing.setSupplierContact(sparePart.getSupplierContact()); + } + if (sparePart.getLocation() != null) { + existing.setLocation(sparePart.getLocation()); + } + if (sparePart.getRemarks() != null) { + existing.setRemarks(sparePart.getRemarks()); + } + if (sparePart.getStatus() != null) { + existing.setStatus(sparePart.getStatus()); + } + + return sparePartRepository.save(existing); + } + + @Override + @Transactional + public void deleteSparePart(UUID id) { + SparePart sparePart = getSparePartById(id); + sparePart.setStatus(SparePart.Status.INACTIVE); + sparePartRepository.save(sparePart); + } + + @Override + public SparePart getSparePartById(UUID id) { + return sparePartRepository.findById(id) + .orElseThrow(() -> new BusinessException(6101, "备件不存在")); + } + + @Override + public List getSparePartsByProject(UUID projectId) { + return sparePartRepository.findByProjectIdAndStatus(projectId, SparePart.Status.ACTIVE); + } + + @Override + public List getSparePartsByCategory(UUID categoryId) { + return sparePartRepository.findByCategoryId(categoryId); + } + + @Override + public List getLowStockParts(UUID projectId) { + return sparePartRepository.findLowStockParts(projectId); + } + + // ==================== 库存管理 ==================== + + @Override + @Transactional + public SparePartRecord inStock(UUID sparePartId, Integer quantity, UUID recordedBy, String remarks) { + if (quantity == null || quantity <= 0) { + throw new BusinessException(6102, "入库数量必须大于0"); + } + + SparePart sparePart = getSparePartById(sparePartId); + + // 更新库存 + sparePart.setCurrentStock(sparePart.getCurrentStock() + quantity); + sparePartRepository.save(sparePart); + + // 创建入库记录 + return createSparePartRecord(sparePartId, SparePartRecord.RecordType.IN, quantity, recordedBy, remarks); + } + + @Override + @Transactional + public SparePartRecord outStock(UUID sparePartId, Integer quantity, UUID relatedOrderId, UUID recordedBy, String remarks) { + if (quantity == null || quantity <= 0) { + throw new BusinessException(6103, "出库数量必须大于0"); + } + + SparePart sparePart = getSparePartById(sparePartId); + + // 校验库存是否充足 + if (sparePart.getCurrentStock() < quantity) { + throw new BusinessException(6104, "库存不足,当前库存:" + sparePart.getCurrentStock() + ",需要出库:" + quantity); + } + + // 更新库存 + sparePart.setCurrentStock(sparePart.getCurrentStock() - quantity); + sparePartRepository.save(sparePart); + + // 创建出库记录 + return createSparePartRecordWithOrder(sparePartId, SparePartRecord.RecordType.OUT, quantity, relatedOrderId, recordedBy, remarks); + } + + @Override + public List getSparePartRecords(UUID sparePartId) { + return sparePartRecordRepository.findBySparePartIdOrderByRecordDateDesc(sparePartId); + } + + // ==================== 私有方法 ==================== + + /** + * 生成备件编码:SP + yyyyMMddHHmmss + */ + private String generateSparePartCode() { + String timestamp = LocalDateTime.now().format(CODE_FORMATTER); + String sparePartCode = "SP" + timestamp; + + // 确保编码唯一 + int suffix = 1; + while (sparePartRepository.existsBySparePartCode(sparePartCode)) { + sparePartCode = "SP" + timestamp + "_" + suffix; + suffix++; + } + + return sparePartCode; + } + + /** + * 生成分类编码:CC + yyyyMMddHHmmss + */ + private String generateCategoryCode() { + String timestamp = LocalDateTime.now().format(CODE_FORMATTER); + String categoryCode = "CC" + timestamp; + + // 检查编码是否存在 + int suffix = 1; + while (sparePartCategoryRepository.findByCategoryCode(categoryCode).isPresent()) { + categoryCode = "CC" + timestamp + "_" + suffix; + suffix++; + } + + return categoryCode; + } + + /** + * 创建库存记录 + */ + private SparePartRecord createSparePartRecord(UUID sparePartId, SparePartRecord.RecordType recordType, + Integer quantity, UUID recordedBy, String remarks) { + SparePart sparePart = getSparePartById(sparePartId); + + SparePartRecord record = new SparePartRecord(); + record.setRecordCode(generateRecordCode(recordType)); + record.setRecordType(recordType); + record.setSparePartId(sparePartId); + record.setQuantity(quantity); + record.setBalance(sparePart.getCurrentStock()); + record.setRecordedBy(recordedBy); + record.setRemarks(remarks); + record.setRecordDate(LocalDateTime.now()); + + return sparePartRecordRepository.save(record); + } + + /** + * 创建带订单信息的库存记录 + */ + private SparePartRecord createSparePartRecordWithOrder(UUID sparePartId, SparePartRecord.RecordType recordType, + Integer quantity, UUID relatedOrderId, UUID recordedBy, String remarks) { + SparePart sparePart = getSparePartById(sparePartId); + + SparePartRecord record = new SparePartRecord(); + record.setRecordCode(generateRecordCode(recordType)); + record.setRecordType(recordType); + record.setSparePartId(sparePartId); + record.setQuantity(quantity); + record.setBalance(sparePart.getCurrentStock()); + record.setRelatedOrderId(relatedOrderId); + record.setRecordedBy(recordedBy); + record.setRemarks(remarks); + record.setRecordDate(LocalDateTime.now()); + + return sparePartRecordRepository.save(record); + } + + /** + * 生成记录编码:REC + 类型 + 时间戳 + */ + private String generateRecordCode(SparePartRecord.RecordType recordType) { + String typeCode = recordType.name(); + String timestamp = LocalDateTime.now().format(CODE_FORMATTER); + return "REC" + typeCode + timestamp; + } +} \ No newline at end of file