diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApi.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApi.java new file mode 100644 index 000000000..c1b4c97e2 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApi.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.executor.api.datasource; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.module.executor.api.datasource.dto.OrderDTO; +import com.cf.imes.module.executor.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * @author Gqr + * @since 2024/7/22 17:56 + */ +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 订单报表数据源") +public interface OrderDatasourceApi { + String PREFIX = ApiConstants.PREFIX + "/order"; + + @GetMapping(PREFIX +"/info") + @Operation(summary = "获取生产单信息") + @Parameter(name = "orderId", description = "生产单id", required = true, example = "1") + CommonResult getOrderInfo(@RequestParam("orderId") Long orderId); +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApi.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApi.java new file mode 100644 index 000000000..e482d683a --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApi.java @@ -0,0 +1,28 @@ +package com.cf.imes.module.executor.api.datasource; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.module.executor.api.datasource.dto.PlateGoodsRespDTO; +import com.cf.imes.module.executor.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +/** + * @author Gqr + * @since 2024/7/19 12:00 + */ +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 板材报表数据源") +public interface OrderPlateDatasourceApi { + String PREFIX = ApiConstants.PREFIX + "/order-plate"; + + @GetMapping(PREFIX + "/summary/byPlate") + @Operation(summary = "按板材汇总板材数据") + @Parameter(name = "orderId", description = "生产单id", required = true, example = "1") + CommonResult> selectPlateGoodsListSummary(@RequestParam("orderId") Long orderId); +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/OrderDTO.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/OrderDTO.java new file mode 100644 index 000000000..b7fa64aec --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/OrderDTO.java @@ -0,0 +1,78 @@ +package com.cf.imes.module.executor.api.datasource.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author Gqr + * @since 2024/7/22 17:54 + */ +@Schema(description = "管理后台 - 生产单表 RPC Response DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OrderDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 3574973837176279383L; + + @Schema(description = "生产单号") + private Long id; + + @Schema(description = "父单号") + private Long parentNo; + + @Schema(description = "源生产单号") + private String apiOrderId; + + @Schema(description = "生产单日期", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime orderDate; + + @Schema(description = "交付日期", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime deliveryDate; + + @Schema(description = "生产单类型,1主单 2子单", example = "1") + private Integer orderType; + + @Schema(description = "生产单排序号") + private Integer orderSort; + + @Schema(description = "CAD数据类型,1CAD 2WebCAD 3Excel", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer dataType; + + @Schema(description = "订单状态,订单状态,0空订单1新单2生产中3生产完成", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "自定义单号") + private String customOrderNo; + + @Schema(description = "客户", requiredMode = Schema.RequiredMode.REQUIRED) + private String customer; + + @Schema(description = "客户地址", requiredMode = Schema.RequiredMode.REQUIRED) + private String address; + + @Schema(description = "客户电话", requiredMode = Schema.RequiredMode.REQUIRED) + private String phoneNumber; + + @Schema(description = "经销商", requiredMode = Schema.RequiredMode.REQUIRED) + private String dealer; + + @Schema(description = "经销商电话", requiredMode = Schema.RequiredMode.REQUIRED) + private String dealerPhoneNumber; + + @Schema(description = "业务员") + private String salesman; + + @Schema(description = "拆单员") + private String splitter; + + @Schema(description = "备注", example = "你猜") + private String remark; +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/PlateGoodsRespDTO.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/PlateGoodsRespDTO.java new file mode 100644 index 000000000..d77ec4f3c --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/PlateGoodsRespDTO.java @@ -0,0 +1,179 @@ +package com.cf.imes.module.executor.api.datasource.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "管理后台 - 板件对应板材信息 Response DTO") +public class PlateGoodsRespDTO { + + @Schema(description = "柜体号", example = "11087") + private Long bodyId; + + @Schema(description = "柜体名称", example = "11087") + private String bodyName; + + @Schema(description = "房间号", example = "11087") + private Long roomId; + + @Schema(description = "房间名称", example = "11087") + private String roomName; + + @Schema(description = "板id", example = "11087") + private Long id; + + @Schema(description = "板数量", example = "11087") + private Integer count = 1; + + @Schema(description = "生产单号", example = "11087") + private Long orderId; + + @Schema(description = "板名称", example = "晨丰") + private String name; + + @Schema(description = "自定义板编号,设计有板编号,则保留设计板编号;设计没有且在机台设置中设置了自定义板编号规则,则按规则自动生成") + private String plateNo; + + @Schema(description = "板类型,0 层板 1 立板 2 背板", example = "1") + private Integer type; + + @Schema(description = "商品 ID", example = "14195") + private String goodsId; + + @Schema(description = "商品名称", example = "西西") + private String goodsName; + + @Schema(description = "商品材质", example = "颗粒板") + private String material; + + @Schema(description = "商品颜色", example = "白色") + private String color; + + @Schema(description = "商品宽度", example = "14195") + private BigDecimal goodsWidth; + + @Schema(description = "商品高度", example = "14195") + private BigDecimal goodsHeight; + + @Schema(description = "商品厚度", example = "14195") + private BigDecimal goodsThickness; + + @Schema(description = "商品价格", example = "14195") + private BigDecimal price; + + @Schema(description = "商品品牌", example = "柏柏") + private String brand; + + @Schema(description = "商品规格", example = "14195*21") + private String spec; + + @Schema(description = "宽度") + private BigDecimal width; + + @Schema(description = "高度") + private BigDecimal height; + + @Schema(description = "厚度") + private BigDecimal thickness; + + @Schema(description = "拆单宽度") + private BigDecimal splitWidth; + + @Schema(description = "拆单高度") + private BigDecimal splitHeight; + + @Schema(description = "拆单厚度") + private BigDecimal splitThickness; + + @Schema(description = "左封边厚度") + private BigDecimal sealLeft; + + @Schema(description = "右封边厚度") + private BigDecimal sealRight; + + @Schema(description = "上封边厚度") + private BigDecimal sealUp; + + @Schema(description = "下封边厚度") + private BigDecimal sealDown; + + @Schema(description = "面积") + private BigDecimal area; + + @Schema(description = "纹路类型,0 正纹 1 可翻转 2 反纹") + private Integer texture; + + @Schema(description = "孔面类型,0 正面 1 反面 2 侧面") + private Integer holeFace; + + @Schema(description = "排孔类型,0 正纹 1 反面 2 随意面") + private Integer holeArrange; + + @Schema(description = "异型孔数量", example = "28477") + private Short unregularPointCount; + + @Schema(description = "正面孔数量", example = "20823") + private Short frontHoleCount; + + @Schema(description = "背面孔数量", example = "3441") + private Short backHoleCount; + + @Schema(description = "侧面孔数量", example = "25509") + private Short sideHoleCount; + + @Schema(description = "正面造型量", example = "31547") + private Short frontModelCount; + + @Schema(description = "背面造型量", example = "26725") + private Short backModelCount; + + @Schema(description = "是否门板") + private Boolean isDoor; + + @Schema(description = "开门类型,0 无 1 左 2 右 3 上 4 下", example = "2") + private Integer openDoorType; + + @Schema(description = "异型偏移 x") + private Double offsetX; + + @Schema(description = "异型偏移 y") + private Double offsetY; + + @Schema(description = "是否孤形对角") + private Boolean isArcAcross; + + @Schema(description = "是否异性") + private Boolean isSpecialShaped; + + @Schema(description = "是否造型") + private Boolean isSculpt; + + @Schema(description = "模块类型 ID", example = "12800") + private Long moduleTypeId; + + @Schema(description = "排单过滤类型,1 有挖穿造型 2 有挖穿孔 4 有二维刀路 8 可叠", example = "1") + private String filterType; + + @Schema(description = "备注", example = "你说的对") + private String remark; + + @Schema(description = "是否作废") + private Boolean isCancel; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/pom.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/pom.xml index 5f090cde7..7f93d1641 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/pom.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/pom.xml @@ -151,7 +151,11 @@ uk.co.jemos.podam podam - + + com.cf.imes + cf-module-report-api + ${revision} + diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApiImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApiImpl.java new file mode 100644 index 000000000..583533207 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApiImpl.java @@ -0,0 +1,32 @@ +package com.cf.imes.module.executor.api.datasource; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.organ.core.context.OrganContextHolder; +import com.cf.imes.module.executor.api.datasource.dto.OrderDTO; +import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; +import com.cf.imes.module.executor.dal.mysql.order.OrderMapper; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @author Gqr + * @since 2024/7/22 17:57 + */ +@RestController // 提供 RESTful API 接口,给 Feign 调用 +@Validated +public class OrderDatasourceApiImpl implements OrderDatasourceApi { + + @Resource + private OrderMapper orderMapper; + + @Override + public CommonResult getOrderInfo(Long orderId) { + // 查询生产单 + OrderDO orderDO = orderMapper.selectOrderOne(orderId, OrganContextHolder.getOrganId()); + OrderDTO orderDTO = BeanUtils.toBean(orderDO, OrderDTO.class); + return CommonResult.success(orderDTO); + } +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApiImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApiImpl.java new file mode 100644 index 000000000..d27d79569 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApiImpl.java @@ -0,0 +1,34 @@ +package com.cf.imes.module.executor.api.datasource; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; +import com.cf.imes.module.executor.api.datasource.dto.PlateGoodsRespDTO; +import com.cf.imes.module.executor.controller.admin.plate.vo.PlateGoodsRespVO; +import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper; +import com.cf.imes.module.executor.enums.OrderDeletedEnum; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author Gqr + * @since 2024/7/19 14:26 + */ +@RestController // 提供 RESTful API 接口,给 Feign 调用 +@Validated +public class OrderPlateDatasourceApiImpl implements OrderPlateDatasourceApi { + @Resource + private PlateMapper plateMapper; + + + @Override + public CommonResult> selectPlateGoodsListSummary(Long orderId) { + // 查询分组统计 + Integer notDeletedStatus = OrderDeletedEnum.NOT_DELETED.getStatus(); + List plateGoodsRespVOS = plateMapper.selectPlateGoodsListSummary(orderId, SecurityFrameworkUtils.getLoginUser().getOrganId(), notDeletedStatus); + return CommonResult.success(BeanUtils.toBean(plateGoodsRespVOS, PlateGoodsRespDTO.class)); + } +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java index bed2ea5be..81998298b 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java @@ -1,6 +1,7 @@ package com.cf.imes.module.executor.framework.rpc.config; import com.cf.imes.module.infra.api.file.FileApi; +import com.cf.imes.module.report.api.template.ReportTemplateApi; import com.cf.imes.module.system.api.application.ApplicationApi; import com.cf.imes.module.system.api.dataSource.DataSourceApi; import com.cf.imes.module.system.api.machine.MachineApi; @@ -16,6 +17,6 @@ import org.springframework.context.annotation.Configuration; */ @Configuration(proxyBeanMethods = false) @EnableFeignClients(clients = {AdminUserApi.class, MachineApi.class, DictDataApi.class, - FileApi.class, ProcessGroupApi.class, FileApi.class, DataSourceApi.class, ApplicationApi.class, ProcessApi.class}) + FileApi.class, ProcessGroupApi.class, FileApi.class, DataSourceApi.class, ApplicationApi.class, ProcessApi.class, ReportTemplateApi.class}) public class RpcConfiguration { } diff --git a/cf-module-report/cf-module-report-api/pom.xml b/cf-module-report/cf-module-report-api/pom.xml index bdcf4798e..78758b2bd 100644 --- a/cf-module-report/cf-module-report-api/pom.xml +++ b/cf-module-report/cf-module-report-api/pom.xml @@ -22,5 +22,26 @@ com.cf.imes cf-common + + + + org.springdoc + springdoc-openapi-ui + provided + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + true + diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/ReportTemplateApi.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/ReportTemplateApi.java new file mode 100644 index 000000000..da559c190 --- /dev/null +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/ReportTemplateApi.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.report.api.template; + +import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; +import com.cf.imes.module.report.enums.ApiConstants; +import feign.Response; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +/** + * 报表模板feign service + * + * @author Gqr + * @since 2024/7/19 11:31 + */ +@FeignClient(name = ApiConstants.NAME) // TODO 晨丰:fallbackFactory = +@Tag(name = "RPC 服务 - 报表模板") +public interface ReportTemplateApi { + String PREFIX = ApiConstants.PREFIX + "/template"; + + @PostMapping(value = PREFIX + "/excel") + @Operation(summary = "下载模板excel") + Response excel(@RequestBody ReportTemplateGenerateReqDTO reqDTO); +} diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/dto/ReportTemplateGenerateReqDTO.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/dto/ReportTemplateGenerateReqDTO.java new file mode 100644 index 000000000..0297253d4 --- /dev/null +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/dto/ReportTemplateGenerateReqDTO.java @@ -0,0 +1,22 @@ +package com.cf.imes.module.report.api.template.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.Map; + +/** + * @author Gqr + * @since 2024/7/19 15:03 + */ +@Schema(description = "RPC 服务 - 报表模板生成 Request DTO") +@Data +public class ReportTemplateGenerateReqDTO { + @Schema(description = "模板id") + @NotNull(message = "模板id不能为空") + private Long templateId; + + @Schema(description = "参数集合") + private Map params; +} diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ApiConstants.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ApiConstants.java new file mode 100644 index 000000000..c6fb3a77f --- /dev/null +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ApiConstants.java @@ -0,0 +1,21 @@ +package com.cf.imes.module.report.enums; + +/** + * API 相关的枚举 + * + * @author 晨丰科技 + */ +public class ApiConstants { + + /** + * 服务名 + * + * 注意,需要保证和 spring.application.name 保持一致 + */ + public static final String NAME = "report-server"; + + public static final String PREFIX = "/admin-api/report"; + + public static final String VERSION = "1.0.0"; + +} diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java index 5085ebbea..540412f57 100644 --- a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java @@ -5,18 +5,23 @@ import com.cf.imes.framework.common.exception.ErrorCode; /** * Report 错误码枚举类 - * + *

* report 系统,使用 1-003-000-000 段 */ public interface ErrorCodeConstants { - // ========== UREPORT 模块 1-003-001-000 ========== + // ========== UREPORT template模块 1-003-001-000 ========== ErrorCode TEMPLATE_NOT_EXISTS = new ErrorCode(1_003_001_001, "报表模板信息不存在"); - ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_001_002, "报表数据源不存在"); - ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_001_003, "报表数据源连接失败"); - ErrorCode DATASET_NOT_EXISTS = new ErrorCode(1_003_001_004, "报表数据集不存在"); - ErrorCode DATASET_SQL_INJECTION_RISK = new ErrorCode(1_003_001_005, "存在SQL注入风险"); - ErrorCode DATASET_SQL_REQUIRED = new ErrorCode(1_003_001_006, "SQL语句不能为空"); - ErrorCode DATASET_SQL_ILLEGAL = new ErrorCode(1_003_001_007, "SQL语句非法"); - ErrorCode DATASET_GET_FIELDS_ERROR = new ErrorCode(1_003_001_008, "获取表字段"); + ErrorCode TEMPLATE_GENERATE_EXCEL_ERROR = new ErrorCode(1_003_001_002, "模板excel生成异常"); + + // ========== UREPORT datasource模块 1-003-002-000 ========== + ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_002_001, "报表数据源不存在"); + ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_002_001, "报表数据源连接失败"); + + // ========== UREPORT dataset模块 1-003-003-000 ========== + ErrorCode DATASET_NOT_EXISTS = new ErrorCode(1_003_003_001, "报表数据集不存在"); + ErrorCode DATASET_SQL_INJECTION_RISK = new ErrorCode(1_003_003_002, "存在SQL注入风险"); + ErrorCode DATASET_SQL_REQUIRED = new ErrorCode(1_003_003_003, "SQL语句不能为空"); + ErrorCode DATASET_SQL_ILLEGAL = new ErrorCode(1_003_003_004, "SQL语句非法"); + ErrorCode DATASET_GET_FIELDS_ERROR = new ErrorCode(1_003_003_005, "获取表字段"); } diff --git a/cf-module-report/cf-module-report-biz/pom.xml b/cf-module-report/cf-module-report-biz/pom.xml index 84ad88f49..e52949f46 100644 --- a/cf-module-report/cf-module-report-biz/pom.xml +++ b/cf-module-report/cf-module-report-biz/pom.xml @@ -130,6 +130,35 @@ commons-text ${commons-text.version} + + + com.cf.imes + cf-module-prod-executor-api + ${revision} + + + + org.apache.poi + poi-ooxml-full + ${poi-ooxml-full.version} + + + org.apache.poi + poi-ooxml + + + org.apache.poi + poi-ooxml-lite + + + ${poi-ooxml.version} + + + com.itextpdf + itextpdf + ${itextpdf.version} + + diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/ReportServerApplication.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/ReportServerApplication.java index bb7be9dd6..ebae14f18 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/ReportServerApplication.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/ReportServerApplication.java @@ -1,7 +1,9 @@ package com.cf.imes.module.report; +import com.bstek.common.config.DataSourceConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Import; /** * 项目的启动类 @@ -9,6 +11,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * @author 晨丰 */ @SpringBootApplication +@Import({DataSourceConfig.class}) public class ReportServerApplication { public static void main(String[] args) { diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java index 882e94e09..12e14ef09 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java @@ -6,7 +6,6 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; @@ -32,12 +31,14 @@ public class ReportDatasetSaveReqVO implements Serializable { private String name; @Schema(description = "数据源id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "数据源id不能为空") private Long datasourceId; @Schema(description = "动态查询SQL") private String sql; + @Schema(description = "bean数据源方法名") + private String method; + @Schema(description = "参数列表") private List parameters = new ArrayList<>(); diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java index 883d9c02d..f0ad81190 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java @@ -31,7 +31,6 @@ public class ReportDatasourceSaveReqVO implements Serializable { private Long id; @Schema(description = "模板id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "模板id不能为空") private Long templateId; @Schema(description = "数据源名称", example = "测试库") diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java index 209a0cd3c..877aafd5d 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java @@ -1,9 +1,13 @@ package com.cf.imes.module.report.controller.admin.template; import com.bstek.designer.bean.ReportDefinitionWrapper; +import com.bstek.ureport.export.ExportUtils; +import com.bstek.ureport.export.ProducerEnum; import com.bstek.ureport.export.html.HtmlReport; +import com.bstek.ureport.model.Report; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplatePreviewPageParametersVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateRespVO; @@ -12,13 +16,17 @@ import com.cf.imes.module.report.service.template.ReportTemplateService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import java.io.OutputStream; import java.util.List; import static com.cf.imes.framework.common.pojo.CommonResult.success; @@ -33,6 +41,7 @@ import static com.cf.imes.framework.common.pojo.CommonResult.success; @RestController @RequestMapping("/report") @Validated +@Slf4j public class ReportTemplateController { @Autowired private ReportTemplateService templateService; @@ -62,7 +71,7 @@ public class ReportTemplateController { } @GetMapping("/template/{id}") - @Operation(summary = "获得报表模板信息") + @Operation(summary = "获取报表模板信息") @Parameter(name = "id", description = "编号", required = true, example = "1") @PreAuthorize("@ss.hasPermission('report:template:query')") public CommonResult getReportTemplate(@PathVariable("id") Long id) { @@ -70,7 +79,7 @@ public class ReportTemplateController { } @GetMapping("/templates") - @Operation(summary = "获得报表模板信息列表") + @Operation(summary = "获取报表模板信息列表") @PreAuthorize("@ss.hasPermission('report:template:query')") public CommonResult> getTemplatePage(@RequestParam(value = "name", required = false) String name) { ReportTemplateReqVO reqVO = new ReportTemplateReqVO(name, null); @@ -83,4 +92,20 @@ public class ReportTemplateController { public CommonResult preview(@Valid @RequestBody ReportTemplatePreviewPageParametersVO pageParametersVO) { return success(templateService.preview(pageParametersVO)); } + + @PostMapping("/template/excel") + @Operation(summary = "模板导出") + @PreAuthorize("@ss.hasPermission('report:template:query')") + public void generateExcel(@RequestBody ReportTemplateGenerateReqDTO reqDTO, HttpServletResponse response) { + OutputStream out = null; + try { + Report report = templateService.generateReport(reqDTO); + out = response.getOutputStream(); + ExportUtils.export(out, report, ProducerEnum.EXCEL); + } catch (Exception ex) { + log.error("[generateExcel] 报表模板生成excel异常", ex); + } finally { + IOUtils.closeQuietly(out); + } + } } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/rpc/config/RpcConfiguration.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/rpc/config/RpcConfiguration.java new file mode 100644 index 000000000..03a4b3da0 --- /dev/null +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/rpc/config/RpcConfiguration.java @@ -0,0 +1,11 @@ +package com.cf.imes.module.report.framework.rpc.config; + +import com.cf.imes.module.executor.api.datasource.OrderDatasourceApi; +import com.cf.imes.module.executor.api.datasource.OrderPlateDatasourceApi; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +@EnableFeignClients(clients = {OrderPlateDatasourceApi.class, OrderDatasourceApi.class}) +public class RpcConfiguration { +} diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java new file mode 100644 index 000000000..005f58364 --- /dev/null +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java @@ -0,0 +1,113 @@ +package com.cf.imes.module.report.framework.ureport.bean; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.module.executor.api.datasource.OrderDatasourceApi; +import com.cf.imes.module.executor.api.datasource.OrderPlateDatasourceApi; +import com.cf.imes.module.executor.api.datasource.dto.OrderDTO; +import com.cf.imes.module.executor.api.datasource.dto.PlateGoodsRespDTO; +import com.cf.imes.module.report.framework.ureport.annotation.CfReportSpringbeanDatasource; +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Gqr + * @since 2024/7/19 14:41 + */ +@CfReportSpringbeanDatasource(value = "OrderSummaryBeanDatasource", name = "生产单导出统计数据源") +@Slf4j +public class OrderSummaryBeanDatasource { + + @Resource + private OrderPlateDatasourceApi orderPlateDatasourceApi; + + @Resource + private OrderDatasourceApi orderDatasourceApi; + + /** + * 生产单信息 + * + * @param dsName + * @param datasetName + * @param parameters + * @return + */ + public List> orderInfo(String dsName, String datasetName, Map parameters) { + List> resultList = new ArrayList<>(); + + Object orderId = parameters.get("orderId"); + if (ObjectUtil.isNull(orderId)) { + + return resultList; + } + + CommonResult commonResult = orderDatasourceApi.getOrderInfo(Long.parseLong(orderId.toString())); + OrderDTO orderDTO = commonResult.getData(); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + if (orderDTO != null) { + // 把orderInfo转map并put到resultList中 + resultList.add(new HashMap<>() {{ + // 构造报表所需结构 + put("orderId", orderDTO.getId()); + put("customOrderNo", orderDTO.getCustomOrderNo()); + put("dealer", orderDTO.getDealer()); + LocalDateTime orderDate = orderDTO.getOrderDate(); + put("orderDate", ObjectUtil.isNotNull(orderDate) ? formatter.format(orderDate) : null); + LocalDateTime deliveryDate = orderDTO.getDeliveryDate(); + put("deliveryDate", ObjectUtil.isNotNull(deliveryDate) ? formatter.format(deliveryDate) : null); + put("customer", orderDTO.getCustomer()); + put("phoneNumber", orderDTO.getPhoneNumber()); + }}); + } + return resultList; + } + + /** + * 板材汇总-按板材 + * + * @param dsName + * @param datasetName + * @param parameters + * @return + */ + public List> orderPlateSummaryByPlate(String dsName, String datasetName, Map parameters) { + List> resultList = new ArrayList<>(); + + Object orderId = parameters.get("orderId"); + // 查询统计信息 + CommonResult> commonResult = orderPlateDatasourceApi.selectPlateGoodsListSummary(Long.parseLong(orderId.toString())); + List plateGoodsRespDTOS = commonResult.getData(); + + if (CollUtil.isNotEmpty(plateGoodsRespDTOS)) { + plateGoodsRespDTOS.forEach(p -> { + resultList.add(new HashMap<>() {{ + BigDecimal area = p.getArea(); + Integer count = p.getCount(); + // 构造报表所需结构 + put("roomName", p.getRoomName()); + put("bodyName", p.getBodyName()); + put("thickness", p.getThickness()); + put("name", p.getName()); + put("height", p.getHeight()); + put("width", p.getWidth()); + put("count", count); + put("area", area); + put("openDoorType", p.getOpenDoorType()); + put("remark", p.getRemark()); + put("areaAll", area.multiply(BigDecimal.valueOf(count))); + }}); + }); + } + return resultList; + } +} diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java index 907477896..4854d7d04 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java @@ -35,10 +35,16 @@ public class CfReportSpringbeanRegistrar implements ImportBeanDefinitionRegistra AnnotatedBeanDefinition beanDef = (AnnotatedBeanDefinition) candidate; Map attributes = beanDef.getMetadata().getAnnotationAttributes(CfReportSpringbeanDatasource.class.getName()); if (attributes != null) { + // 校验注解上的value String value = (String) attributes.get("value"); if (!StringUtils.hasText(value)) { throw new IllegalArgumentException("@CfReportSpringbean requires a non-empty 'value' attribute."); } + // 校验注解上的name + String name = (String) attributes.get("name"); + if (!StringUtils.hasText(name)) { + throw new IllegalArgumentException("@CfReportSpringbean requires a non-empty 'name' attribute."); + } BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(candidate.getBeanClassName()); registry.registerBeanDefinition(value, builder.getBeanDefinition()); } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java index dbf45136f..f7b652091 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java @@ -2,6 +2,8 @@ package com.cf.imes.module.report.service.template; import com.bstek.designer.bean.ReportDefinitionWrapper; import com.bstek.ureport.export.html.HtmlReport; +import com.bstek.ureport.model.Report; +import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplatePreviewPageParametersVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateSaveReqVO; @@ -56,7 +58,7 @@ public interface ReportTemplateService { ReportDefinitionWrapper getReportTemplateDefinition(Long id); /** - * 获得报表模板信息列表 + * 获取报表模板信息列表 * * @param pageReqVO 查询参数 * @return 报表模板信息列表 @@ -70,4 +72,13 @@ public interface ReportTemplateService { * @return */ HtmlReport preview(ReportTemplatePreviewPageParametersVO pageParametersVO); + + + /** + * 构造生成报表report对象 + * + * @param dto + * @return + */ + Report generateReport(ReportTemplateGenerateReqDTO dto); } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java index c696a9e4f..e7b15fdce 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java @@ -26,6 +26,7 @@ import com.bstek.ureport.model.Report; import com.bstek.ureport.parser.ReportParser; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetReqVO; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetSaveReqVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceReqVO; @@ -99,14 +100,14 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { private void analyzeDatasource(List datasource, Long templateId) { datasource.forEach(ds -> { // 更新/新增数据源 + Long datasourceId; if (ObjectUtil.isNotNull(ds.getId())) { + datasourceId = ds.getId(); datasourceService.updateDatasource(ds); } else { ds.setTemplateId(templateId); - datasourceService.createDatasource(ds); + datasourceId = datasourceService.createDatasource(ds); } - // 获取自增数据源主键 - Long datasourceId = ds.getId(); List datasets = ds.getDatasets(); List batchInsertDataset = new ArrayList<>(); List batchupdateDataset = new ArrayList<>(); @@ -239,7 +240,7 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { HtmlReport htmlReport = new HtmlReport(); // 转换ureport参数 - PreviewPageParameters pageParameters = BeanUtils.toBean(pageParametersVO,PreviewPageParameters.class); + PreviewPageParameters pageParameters = BeanUtils.toBean(pageParametersVO, PreviewPageParameters.class); PreviewParameters params = pageParameters.getParams(); // 解析xml @@ -270,7 +271,7 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { htmlReport.setChartDatas(report.getContext().getChartDataMap().values()); htmlReport.setContent(html); htmlReport.setStyle(reportDefinition.getStyle()); - SearchFormData searchFormData = reportDefinition.buildSearchFormData(report.getContext().getDatasetMap(),parameters); + SearchFormData searchFormData = reportDefinition.buildSearchFormData(report.getContext().getDatasetMap(), parameters); htmlReport.setSearchFormData(searchFormData); htmlReport.setReportAlign(report.getPaper().getHtmlReportAlign().name()); htmlReport.setBgImage(report.getPaper().getBgImage()); @@ -278,4 +279,19 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { htmlReport.setFloatImages(reportDefinition.getFloatImages()); return htmlReport; } + + @Override + public Report generateReport(ReportTemplateGenerateReqDTO reqDTO) { + // 查询模板 + ReportTemplateDO template = templateMapper.selectById(reqDTO.getTemplateId()); + String xmlContent = template.getContent(); + ReportRender reportRender = new ReportRender(); + // 解析xml + ReportDefinition reportDefinition = reportRender.getReportDefinition(xmlContent, CharsetUtil.UTF_8); + // 设置参数 + PreviewParameters previewParameters = new PreviewParameters(); + previewParameters.setQuery(reqDTO.getParams()); + + return reportRender.render(reportDefinition, previewParameters.getQuery()); + } } diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar index 7f66b483d..e3b1628bb 100644 Binary files a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar and b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar differ diff --git a/cf-module-report/pom.xml b/cf-module-report/pom.xml index 24f2451e9..ce5fbbcd4 100644 --- a/cf-module-report/pom.xml +++ b/cf-module-report/pom.xml @@ -26,5 +26,8 @@ 2.11.0 4.5.3 1.10.0 + 5.2.0 + 5.2.2 + 5.5.13