diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/controller/AmsTransferDetailReportController.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/controller/AmsTransferDetailReportController.java new file mode 100644 index 0000000..006ef7b --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/controller/AmsTransferDetailReportController.java @@ -0,0 +1,104 @@ +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.AmsTransferDetailReport; +import com.ruoyi.asset.domain.AmsWarehouse; +import com.ruoyi.asset.service.IAmsAssetCategoryService; +import com.ruoyi.asset.service.IAmsTransferDetailReportService; +import com.ruoyi.asset.service.IAmsWarehouseService; +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/transfer") +public class AmsTransferDetailReportController extends BaseController +{ + private static final String ENABLED_YES = "Y"; + + private String prefix = "asset/report"; + + @Autowired + private IAmsTransferDetailReportService amsTransferDetailReportService; + + @Autowired + private IAmsAssetCategoryService amsAssetCategoryService; + + @Autowired + private IAmsWarehouseService amsWarehouseService; + + @RequiresPermissions("asset:report:transfer:view") + @GetMapping() + public String transfer(ModelMap mmap) + { + putReportOptions(mmap); + return prefix + "/transfer"; + } + + /** + * 查询调拨明细报表列表。 + */ + @RequiresPermissions("asset:report:transfer:list") + @PostMapping("/list") + @ResponseBody + public TableDataInfo list(AmsTransferDetailReport amsTransferDetailReport) + { + startPage(); + List list = amsTransferDetailReportService + .selectTransferDetailReportList(amsTransferDetailReport); + return getDataTable(list); + } + + /** + * 导出调拨明细报表。 + */ + @RequiresPermissions("asset:report:transfer:export") + @Log(title = "调拨明细报表", businessType = BusinessType.EXPORT) + @PostMapping("/export") + @ResponseBody + public AjaxResult export(AmsTransferDetailReport amsTransferDetailReport) + { + List list = amsTransferDetailReportService + .selectTransferDetailReportList(amsTransferDetailReport); + ExcelUtil util = new ExcelUtil( + AmsTransferDetailReport.class); + return util.exportExcel(list, "调拨明细报表数据"); + } + + private void putReportOptions(ModelMap mmap) + { + mmap.put("warehouseList", selectEnabledWarehouseList()); + mmap.put("categoryList", selectEnabledCategoryList()); + } + + private List selectEnabledWarehouseList() + { + AmsWarehouse warehouse = new AmsWarehouse(); + warehouse.setEnabled(ENABLED_YES); + return amsWarehouseService.selectAmsWarehouseList(warehouse); + } + + 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/AmsTransferDetailReport.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/domain/AmsTransferDetailReport.java new file mode 100644 index 0000000..34f2131 --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/domain/AmsTransferDetailReport.java @@ -0,0 +1,293 @@ +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 AmsTransferDetailReport extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 调拨单号 */ + @Excel(name = "调拨单号") + private String transferNo; + + /** 调拨确认时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @Excel(name = "调拨日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date confirmTime; + + /** 申请人 */ + @Excel(name = "申请人") + private String applicantName; + + /** 确认人 */ + @Excel(name = "确认人") + private String confirmUserName; + + /** 调拨原因 */ + @Excel(name = "调拨原因") + private String transferReason; + + /** 资产编码 */ + @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; + + /** 调拨前仓库ID */ + private Long oldWarehouseId; + + /** 调拨前仓库 */ + @Excel(name = "调拨前仓库") + private String oldWarehouseName; + + /** 调拨前位置 */ + @Excel(name = "调拨前位置") + private String oldLocationName; + + /** 调拨后仓库ID */ + private Long newWarehouseId; + + /** 调拨后仓库 */ + @Excel(name = "调拨后仓库") + private String newWarehouseName; + + /** 调拨后位置 */ + @Excel(name = "调拨后位置") + private String newLocationName; + + /** 明细备注 */ + @Excel(name = "备注") + private String remark; + + public void setTransferNo(String transferNo) + { + this.transferNo = transferNo; + } + + public String getTransferNo() + { + return transferNo; + } + + public void setConfirmTime(Date confirmTime) + { + this.confirmTime = confirmTime; + } + + public Date getConfirmTime() + { + return confirmTime; + } + + public void setApplicantName(String applicantName) + { + this.applicantName = applicantName; + } + + public String getApplicantName() + { + return applicantName; + } + + public void setConfirmUserName(String confirmUserName) + { + this.confirmUserName = confirmUserName; + } + + public String getConfirmUserName() + { + return confirmUserName; + } + + public void setTransferReason(String transferReason) + { + this.transferReason = transferReason; + } + + public String getTransferReason() + { + return transferReason; + } + + 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 setOldWarehouseId(Long oldWarehouseId) + { + this.oldWarehouseId = oldWarehouseId; + } + + public Long getOldWarehouseId() + { + return oldWarehouseId; + } + + public void setOldWarehouseName(String oldWarehouseName) + { + this.oldWarehouseName = oldWarehouseName; + } + + public String getOldWarehouseName() + { + return oldWarehouseName; + } + + public void setOldLocationName(String oldLocationName) + { + this.oldLocationName = oldLocationName; + } + + public String getOldLocationName() + { + return oldLocationName; + } + + public void setNewWarehouseId(Long newWarehouseId) + { + this.newWarehouseId = newWarehouseId; + } + + public Long getNewWarehouseId() + { + return newWarehouseId; + } + + public void setNewWarehouseName(String newWarehouseName) + { + this.newWarehouseName = newWarehouseName; + } + + public String getNewWarehouseName() + { + return newWarehouseName; + } + + public void setNewLocationName(String newLocationName) + { + this.newLocationName = newLocationName; + } + + public String getNewLocationName() + { + return newLocationName; + } + + public void setRemark(String remark) + { + this.remark = remark; + } + + public String getRemark() + { + return remark; + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("transferNo", getTransferNo()) + .append("confirmTime", getConfirmTime()) + .append("applicantName", getApplicantName()) + .append("confirmUserName", getConfirmUserName()) + .append("transferReason", getTransferReason()) + .append("assetCode", getAssetCode()) + .append("assetName", getAssetName()) + .append("categoryId", getCategoryId()) + .append("categoryName", getCategoryName()) + .append("specModel", getSpecModel()) + .append("brand", getBrand()) + .append("oldWarehouseId", getOldWarehouseId()) + .append("oldWarehouseName", getOldWarehouseName()) + .append("oldLocationName", getOldLocationName()) + .append("newWarehouseId", getNewWarehouseId()) + .append("newWarehouseName", getNewWarehouseName()) + .append("newLocationName", getNewLocationName()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsTransferDetailReportMapper.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsTransferDetailReportMapper.java new file mode 100644 index 0000000..817263d --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsTransferDetailReportMapper.java @@ -0,0 +1,23 @@ +package com.ruoyi.asset.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.asset.domain.AmsTransferDetailReport; + +/** + * 调拨明细报表Mapper接口 + * + * @author Yangk + */ +public interface AmsTransferDetailReportMapper +{ + /** + * 查询调拨明细报表列表。 + * + * @param report 查询条件 + * @param transferredStatus 已调拨状态 + * @return 调拨明细报表集合 + */ + List selectTransferDetailReportList(@Param("report") AmsTransferDetailReport report, + @Param("transferredStatus") String transferredStatus); +} diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAmsTransferDetailReportService.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAmsTransferDetailReportService.java new file mode 100644 index 0000000..2b0bbcd --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAmsTransferDetailReportService.java @@ -0,0 +1,21 @@ +package com.ruoyi.asset.service; + +import java.util.List; +import com.ruoyi.asset.domain.AmsTransferDetailReport; + +/** + * 调拨明细报表Service接口 + * + * @author Yangk + */ +public interface IAmsTransferDetailReportService +{ + /** + * 查询调拨明细报表列表。 + * + * @param amsTransferDetailReport 查询条件 + * @return 调拨明细报表集合 + */ + List selectTransferDetailReportList( + AmsTransferDetailReport amsTransferDetailReport); +} diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsTransferDetailReportServiceImpl.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsTransferDetailReportServiceImpl.java new file mode 100644 index 0000000..8adf85d --- /dev/null +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsTransferDetailReportServiceImpl.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.TransferOrderStatus; +import com.ruoyi.asset.domain.AmsTransferDetailReport; +import com.ruoyi.asset.mapper.AmsTransferDetailReportMapper; +import com.ruoyi.asset.service.IAmsTransferDetailReportService; + +/** + * 调拨明细报表Service业务层处理 + * + * @author Yangk + */ +@Service +public class AmsTransferDetailReportServiceImpl implements IAmsTransferDetailReportService +{ + @Autowired + private AmsTransferDetailReportMapper amsTransferDetailReportMapper; + + /** + * 查询调拨明细报表列表。 + */ + @Override + public List selectTransferDetailReportList( + AmsTransferDetailReport amsTransferDetailReport) + { + AmsTransferDetailReport query = amsTransferDetailReport == null ? new AmsTransferDetailReport() + : amsTransferDetailReport; + // 报表只统计已确认完成的调拨事实,状态由服务端固定,避免前端把草稿或待确认单混入统计。 + return amsTransferDetailReportMapper.selectTransferDetailReportList(query, + TransferOrderStatus.TRANSFERRED); + } +} diff --git a/ruoyi-asset/src/main/resources/mapper/asset/AmsTransferDetailReportMapper.xml b/ruoyi-asset/src/main/resources/mapper/asset/AmsTransferDetailReportMapper.xml new file mode 100644 index 0000000..43f874b --- /dev/null +++ b/ruoyi-asset/src/main/resources/mapper/asset/AmsTransferDetailReportMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + o.transfer_no, + o.confirm_time, + o.applicant_name, + o.confirm_user_name, + o.transfer_reason, + i.asset_code, + i.asset_name, + i.category_id, + i.category_name, + i.spec_model, + i.brand, + i.old_warehouse_id, + i.old_warehouse_name, + i.old_location_name, + i.new_warehouse_id, + i.new_warehouse_name, + i.new_location_name, + i.remark + + + + + o.del_flag = '0' + and i.del_flag = '0' + and o.order_status = #{transferredStatus} + + and o.transfer_no like concat(#{report.transferNo}, '%') + + + and o.applicant_name like concat('%', #{report.applicantName}, '%') + + + and i.category_id = #{report.categoryId} + + + and i.asset_code like concat(#{report.assetCode}, '%') + + + and i.old_warehouse_id = #{report.oldWarehouseId} + + + and i.new_warehouse_id = #{report.newWarehouseId} + + + and o.confirm_time >= #{report.params.beginConfirmTime} + + + and o.confirm_time < date_add(#{report.params.endConfirmTime}, interval 1 day) + + + + + + diff --git a/ruoyi-asset/src/main/resources/templates/asset/report/transfer.html b/ruoyi-asset/src/main/resources/templates/asset/report/transfer.html new file mode 100644 index 0000000..c2a98a8 --- /dev/null +++ b/ruoyi-asset/src/main/resources/templates/asset/report/transfer.html @@ -0,0 +1,151 @@ + + + + + + + + +
+
+
+
+
+
    +
  • + + +
  • +
  • + + + - + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + +  搜索 + + +  重置 + +
  • +
+
+
+
+ + +
+
+
+
+
+ + + + + + diff --git a/ruoyi-asset/src/test/java/com/ruoyi/asset/service/impl/AmsTransferDetailReportServiceImplTest.java b/ruoyi-asset/src/test/java/com/ruoyi/asset/service/impl/AmsTransferDetailReportServiceImplTest.java new file mode 100644 index 0000000..b77238a --- /dev/null +++ b/ruoyi-asset/src/test/java/com/ruoyi/asset/service/impl/AmsTransferDetailReportServiceImplTest.java @@ -0,0 +1,87 @@ +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.TransferOrderStatus; +import com.ruoyi.asset.domain.AmsTransferDetailReport; +import com.ruoyi.asset.mapper.AmsTransferDetailReportMapper; +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 AmsTransferDetailReportServiceImplTest +{ + @Mock + private AmsTransferDetailReportMapper amsTransferDetailReportMapper; + + @InjectMocks + private AmsTransferDetailReportServiceImpl service; + + /** 报表只能看已确认调拨,防止草稿和待确认单据影响正式统计口径。 */ + @Test + void selectTransferDetailReportListShouldAlwaysUseTransferredStatus() + { + AmsTransferDetailReport query = new AmsTransferDetailReport(); + query.setTransferNo("DB202606"); + query.setApplicantName("若依"); + query.setAssetCode("ASSET-001"); + query.setCategoryId(1L); + query.setOldWarehouseId(10L); + query.setNewWarehouseId(20L); + when(amsTransferDetailReportMapper.selectTransferDetailReportList(query, + TransferOrderStatus.TRANSFERRED)).thenReturn(List.of()); + + service.selectTransferDetailReportList(query); + + ArgumentCaptor reportCaptor = ArgumentCaptor + .forClass(AmsTransferDetailReport.class); + verify(amsTransferDetailReportMapper).selectTransferDetailReportList(reportCaptor.capture(), + eq(TransferOrderStatus.TRANSFERRED)); + assertEquals("DB202606", reportCaptor.getValue().getTransferNo()); + assertEquals("若依", reportCaptor.getValue().getApplicantName()); + assertEquals("ASSET-001", reportCaptor.getValue().getAssetCode()); + assertEquals(1L, reportCaptor.getValue().getCategoryId()); + assertEquals(10L, reportCaptor.getValue().getOldWarehouseId()); + assertEquals(20L, reportCaptor.getValue().getNewWarehouseId()); + } + + @Test + void selectTransferDetailReportListShouldHandleNullQuery() + { + when(amsTransferDetailReportMapper.selectTransferDetailReportList(any(AmsTransferDetailReport.class), + eq(TransferOrderStatus.TRANSFERRED))).thenReturn(List.of()); + + service.selectTransferDetailReportList(null); + + verify(amsTransferDetailReportMapper).selectTransferDetailReportList(any(AmsTransferDetailReport.class), + eq(TransferOrderStatus.TRANSFERRED)); + } + + @Test + void selectTransferDetailReportListShouldReturnMapperRows() + { + AmsTransferDetailReport row = new AmsTransferDetailReport(); + row.setTransferNo("DB202606120001"); + row.setAssetCode("ASSET-001"); + row.setNewWarehouseName("二号仓"); + when(amsTransferDetailReportMapper.selectTransferDetailReportList(any(AmsTransferDetailReport.class), + eq(TransferOrderStatus.TRANSFERRED))).thenReturn(List.of(row)); + + List result = service + .selectTransferDetailReportList(new AmsTransferDetailReport()); + + assertEquals(1, result.size()); + assertEquals("DB202606120001", result.get(0).getTransferNo()); + assertEquals("ASSET-001", result.get(0).getAssetCode()); + assertEquals("二号仓", result.get(0).getNewWarehouseName()); + } +}