diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/controller/AmsDisposalDetailReportController.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/controller/AmsDisposalDetailReportController.java new file mode 100644 index 0000000..6c0f6c3 --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/controller/AmsDisposalDetailReportController.java @@ -0,0 +1,86 @@ +package com.ruoyi.asset.controller; + +import java.util.List; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import com.ruoyi.asset.domain.AmsAssetCategory; +import com.ruoyi.asset.domain.AmsDisposalDetailReport; +import com.ruoyi.asset.service.IAmsAssetCategoryService; +import com.ruoyi.asset.service.IAmsDisposalDetailReportService; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; + +/** + * 报废明细报表Controller + * + * @author Yangk + */ +@Controller +@RequestMapping("/asset/report/disposal") +public class AmsDisposalDetailReportController extends BaseController +{ + private static final String ENABLED_YES = "Y"; + + private String prefix = "asset/report"; + + @Autowired + private IAmsDisposalDetailReportService amsDisposalDetailReportService; + + @Autowired + private IAmsAssetCategoryService amsAssetCategoryService; + + @RequiresPermissions("asset:report:disposal:view") + @GetMapping() + public String disposal(ModelMap mmap) + { + mmap.put("categoryList", selectEnabledCategoryList()); + return prefix + "/disposal"; + } + + /** + * 查询报废明细报表列表。 + */ + @RequiresPermissions("asset:report:disposal:list") + @PostMapping("/list") + @ResponseBody + public TableDataInfo list(AmsDisposalDetailReport amsDisposalDetailReport) + { + startPage(); + List list = amsDisposalDetailReportService + .selectDisposalDetailReportList(amsDisposalDetailReport); + return getDataTable(list); + } + + /** + * 导出报废明细报表。 + */ + @RequiresPermissions("asset:report:disposal:export") + @Log(title = "报废明细报表", businessType = BusinessType.EXPORT) + @PostMapping("/export") + @ResponseBody + public AjaxResult export(AmsDisposalDetailReport amsDisposalDetailReport) + { + List list = amsDisposalDetailReportService + .selectDisposalDetailReportList(amsDisposalDetailReport); + ExcelUtil util = new ExcelUtil( + AmsDisposalDetailReport.class); + return util.exportExcel(list, "报废明细报表数据"); + } + + private List selectEnabledCategoryList() + { + AmsAssetCategory category = new AmsAssetCategory(); + category.setEnabled(ENABLED_YES); + return amsAssetCategoryService.selectAmsAssetCategoryList(category); + } +} diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/domain/AmsDisposalDetailReport.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/domain/AmsDisposalDetailReport.java new file mode 100644 index 0000000..c433d0c --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/domain/AmsDisposalDetailReport.java @@ -0,0 +1,235 @@ +package com.ruoyi.asset.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 报废明细报表对象 + * + * @author Yangk + */ +public class AmsDisposalDetailReport extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 报废单号 */ + @Excel(name = "报废单号") + private String disposalNo; + + /** 报废日期 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @Excel(name = "报废日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date disposalTime; + + /** 申请人 */ + @Excel(name = "申请人") + private String applicantName; + + /** 申请部门 */ + @Excel(name = "申请部门") + private String applyDeptName; + + /** 处置方式 */ + @Excel(name = "处置方式") + private String disposalMethod; + + /** 确认人 */ + @Excel(name = "确认人") + private String confirmUserName; + + /** 资产编码 */ + @Excel(name = "资产编码") + private String assetCode; + + /** 资产名称 */ + @Excel(name = "资产名称") + private String assetName; + + /** 资产类别ID */ + private Long categoryId; + + /** 资产类别 */ + @Excel(name = "资产类别") + private String categoryName; + + /** 规格型号 */ + @Excel(name = "规格型号") + private String specModel; + + /** 品牌 */ + @Excel(name = "品牌") + private String brand; + + /** 报废原因 */ + @Excel(name = "报废原因") + private String disposalReason; + + /** 处置备注 */ + @Excel(name = "处置备注") + private String disposalRemark; + + public void setDisposalNo(String disposalNo) + { + this.disposalNo = disposalNo; + } + + public String getDisposalNo() + { + return disposalNo; + } + + public void setDisposalTime(Date disposalTime) + { + this.disposalTime = disposalTime; + } + + public Date getDisposalTime() + { + return disposalTime; + } + + public void setApplicantName(String applicantName) + { + this.applicantName = applicantName; + } + + public String getApplicantName() + { + return applicantName; + } + + public void setApplyDeptName(String applyDeptName) + { + this.applyDeptName = applyDeptName; + } + + public String getApplyDeptName() + { + return applyDeptName; + } + + public void setDisposalMethod(String disposalMethod) + { + this.disposalMethod = disposalMethod; + } + + public String getDisposalMethod() + { + return disposalMethod; + } + + public void setConfirmUserName(String confirmUserName) + { + this.confirmUserName = confirmUserName; + } + + public String getConfirmUserName() + { + return confirmUserName; + } + + public void setAssetCode(String assetCode) + { + this.assetCode = assetCode; + } + + public String getAssetCode() + { + return assetCode; + } + + public void setAssetName(String assetName) + { + this.assetName = assetName; + } + + public String getAssetName() + { + return assetName; + } + + public void setCategoryId(Long categoryId) + { + this.categoryId = categoryId; + } + + public Long getCategoryId() + { + return categoryId; + } + + public void setCategoryName(String categoryName) + { + this.categoryName = categoryName; + } + + public String getCategoryName() + { + return categoryName; + } + + public void setSpecModel(String specModel) + { + this.specModel = specModel; + } + + public String getSpecModel() + { + return specModel; + } + + public void setBrand(String brand) + { + this.brand = brand; + } + + public String getBrand() + { + return brand; + } + + public void setDisposalReason(String disposalReason) + { + this.disposalReason = disposalReason; + } + + public String getDisposalReason() + { + return disposalReason; + } + + public void setDisposalRemark(String disposalRemark) + { + this.disposalRemark = disposalRemark; + } + + public String getDisposalRemark() + { + return disposalRemark; + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("disposalNo", getDisposalNo()) + .append("disposalTime", getDisposalTime()) + .append("applicantName", getApplicantName()) + .append("applyDeptName", getApplyDeptName()) + .append("disposalMethod", getDisposalMethod()) + .append("confirmUserName", getConfirmUserName()) + .append("assetCode", getAssetCode()) + .append("assetName", getAssetName()) + .append("categoryId", getCategoryId()) + .append("categoryName", getCategoryName()) + .append("specModel", getSpecModel()) + .append("brand", getBrand()) + .append("disposalReason", getDisposalReason()) + .append("disposalRemark", getDisposalRemark()) + .toString(); + } +} diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsDisposalDetailReportMapper.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsDisposalDetailReportMapper.java new file mode 100644 index 0000000..d5f917a --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsDisposalDetailReportMapper.java @@ -0,0 +1,23 @@ +package com.ruoyi.asset.mapper; + +import java.util.List; +import com.ruoyi.asset.domain.AmsDisposalDetailReport; +import org.apache.ibatis.annotations.Param; + +/** + * 报废明细报表Mapper接口 + * + * @author Yangk + */ +public interface AmsDisposalDetailReportMapper +{ + /** + * 查询报废明细报表列表。 + * + * @param report 查询条件 + * @param doneStatus 已报废状态 + * @return 报废明细报表集合 + */ + public List selectDisposalDetailReportList( + @Param("report") AmsDisposalDetailReport report, @Param("doneStatus") String doneStatus); +} diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAmsDisposalDetailReportService.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAmsDisposalDetailReportService.java new file mode 100644 index 0000000..c83389a --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAmsDisposalDetailReportService.java @@ -0,0 +1,21 @@ +package com.ruoyi.asset.service; + +import java.util.List; +import com.ruoyi.asset.domain.AmsDisposalDetailReport; + +/** + * 报废明细报表Service接口 + * + * @author Yangk + */ +public interface IAmsDisposalDetailReportService +{ + /** + * 查询报废明细报表列表。 + * + * @param amsDisposalDetailReport 报废明细报表查询条件 + * @return 报废明细报表集合 + */ + public List selectDisposalDetailReportList( + AmsDisposalDetailReport amsDisposalDetailReport); +} diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsDisposalDetailReportServiceImpl.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsDisposalDetailReportServiceImpl.java new file mode 100644 index 0000000..4d16999 --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsDisposalDetailReportServiceImpl.java @@ -0,0 +1,35 @@ +package com.ruoyi.asset.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.asset.constant.DisposalOrderStatus; +import com.ruoyi.asset.domain.AmsDisposalDetailReport; +import com.ruoyi.asset.mapper.AmsDisposalDetailReportMapper; +import com.ruoyi.asset.service.IAmsDisposalDetailReportService; + +/** + * 报废明细报表Service业务层处理 + * + * @author Yangk + */ +@Service +public class AmsDisposalDetailReportServiceImpl implements IAmsDisposalDetailReportService +{ + @Autowired + private AmsDisposalDetailReportMapper amsDisposalDetailReportMapper; + + /** + * 查询报废明细报表列表。 + */ + @Override + public List selectDisposalDetailReportList( + AmsDisposalDetailReport amsDisposalDetailReport) + { + AmsDisposalDetailReport query = amsDisposalDetailReport == null ? new AmsDisposalDetailReport() + : amsDisposalDetailReport; + // 报表只统计已确认报废事实,状态口径固定在服务端,避免草稿、待确认或驳回单据进入历史报表。 + return amsDisposalDetailReportMapper.selectDisposalDetailReportList(query, + DisposalOrderStatus.DISPOSED_DONE); + } +} diff --git a/ruoyi-asset/src/main/resources/mapper/asset/AmsDisposalDetailReportMapper.xml b/ruoyi-asset/src/main/resources/mapper/asset/AmsDisposalDetailReportMapper.xml new file mode 100644 index 0000000..a41cb1c --- /dev/null +++ b/ruoyi-asset/src/main/resources/mapper/asset/AmsDisposalDetailReportMapper.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + o.disposal_no, + o.disposal_time, + o.applicant_name, + o.apply_dept_name, + o.disposal_method, + o.confirm_user_name, + i.asset_code, + i.asset_name, + i.category_id, + i.category_name, + i.spec_model, + i.brand, + i.disposal_reason, + i.disposal_remark + + + + + o.del_flag = '0' + and i.del_flag = '0' + and o.order_status = #{doneStatus} + + and o.disposal_no like concat(#{report.disposalNo}, '%') + + + and o.disposal_method like concat('%', #{report.disposalMethod}, '%') + + + and i.category_id = #{report.categoryId} + + + and o.apply_dept_name like concat('%', #{report.applyDeptName}, '%') + + + and i.asset_code like concat(#{report.assetCode}, '%') + + + and o.disposal_time >= #{report.params.beginDisposalTime} + + + and o.disposal_time < date_add(#{report.params.endDisposalTime}, interval 1 day) + + + + + + diff --git a/ruoyi-asset/src/main/resources/templates/asset/report/disposal.html b/ruoyi-asset/src/main/resources/templates/asset/report/disposal.html new file mode 100644 index 0000000..8da7909 --- /dev/null +++ b/ruoyi-asset/src/main/resources/templates/asset/report/disposal.html @@ -0,0 +1,133 @@ + + + + + + + + +
+
+
+
+
+
    +
  • + + +
  • +
  • + + + - + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + +  搜索 + + +  重置 + +
  • +
+
+
+
+ + +
+
+
+
+
+ + + + + + diff --git a/ruoyi-asset/src/test/java/com/ruoyi/asset/service/impl/AmsDisposalDetailReportServiceImplTest.java b/ruoyi-asset/src/test/java/com/ruoyi/asset/service/impl/AmsDisposalDetailReportServiceImplTest.java new file mode 100644 index 0000000..26f37a7 --- /dev/null +++ b/ruoyi-asset/src/test/java/com/ruoyi/asset/service/impl/AmsDisposalDetailReportServiceImplTest.java @@ -0,0 +1,79 @@ +package com.ruoyi.asset.service.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import com.ruoyi.asset.constant.DisposalOrderStatus; +import com.ruoyi.asset.domain.AmsDisposalDetailReport; +import com.ruoyi.asset.mapper.AmsDisposalDetailReportMapper; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class AmsDisposalDetailReportServiceImplTest +{ + @Mock + private AmsDisposalDetailReportMapper amsDisposalDetailReportMapper; + + @InjectMocks + private AmsDisposalDetailReportServiceImpl service; + + /** 报表只展示已确认报废事实,避免草稿、待确认、驳回明细污染历史统计口径。 */ + @Test + void selectDisposalDetailReportListShouldAlwaysUseDisposedDoneStatus() + { + AmsDisposalDetailReport query = new AmsDisposalDetailReport(); + query.setApplyDeptName("设备部"); + query.setCategoryId(5L); + when(amsDisposalDetailReportMapper.selectDisposalDetailReportList(query, + DisposalOrderStatus.DISPOSED_DONE)).thenReturn(List.of()); + + service.selectDisposalDetailReportList(query); + + ArgumentCaptor reportCaptor = ArgumentCaptor + .forClass(AmsDisposalDetailReport.class); + verify(amsDisposalDetailReportMapper).selectDisposalDetailReportList(reportCaptor.capture(), + eq(DisposalOrderStatus.DISPOSED_DONE)); + assertEquals("设备部", reportCaptor.getValue().getApplyDeptName()); + assertEquals(5L, reportCaptor.getValue().getCategoryId()); + } + + @Test + void selectDisposalDetailReportListShouldHandleNullQuery() + { + when(amsDisposalDetailReportMapper.selectDisposalDetailReportList(any(AmsDisposalDetailReport.class), + eq(DisposalOrderStatus.DISPOSED_DONE))).thenReturn(List.of()); + + service.selectDisposalDetailReportList(null); + + verify(amsDisposalDetailReportMapper).selectDisposalDetailReportList(any(AmsDisposalDetailReport.class), + eq(DisposalOrderStatus.DISPOSED_DONE)); + } + + @Test + void selectDisposalDetailReportListShouldReturnMapperRows() + { + AmsDisposalDetailReport row = new AmsDisposalDetailReport(); + row.setDisposalNo("BF202606180002"); + row.setAssetCode("TEST-ASSET-009"); + row.setDisposalReason("无法使用"); + when(amsDisposalDetailReportMapper.selectDisposalDetailReportList(any(AmsDisposalDetailReport.class), + eq(DisposalOrderStatus.DISPOSED_DONE))).thenReturn(List.of(row)); + + List result = service + .selectDisposalDetailReportList(new AmsDisposalDetailReport()); + + assertEquals(1, result.size()); + assertEquals("BF202606180002", result.get(0).getDisposalNo()); + assertEquals("TEST-ASSET-009", result.get(0).getAssetCode()); + assertEquals("无法使用", result.get(0).getDisposalReason()); + } +}