From d5716bec52d7f701ddd9eb5d70bde7093b40b9ce Mon Sep 17 00:00:00 2001
From: chenqp <965586934@qq.com>
Date: Wed, 26 Jul 2023 23:53:44 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=8A=A5=E9=94=80?=
=?UTF-8?q?=E7=B3=BB=E7=BB=9F=E4=B8=9A=E5=8A=A1bs=E6=A8=A1=E5=9D=97?=
=?UTF-8?q?=E3=80=82=E5=8F=91=E7=A5=A8=E4=BB=A3=E7=A0=81=E5=88=9D=E5=A7=8B?=
=?UTF-8?q?=E5=8C=96=E6=8F=90=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 1 +
yudao-module-bs/pom.xml | 23 ++
yudao-module-bs/yudao-module-bs-api/pom.xml | 34 +++
.../module/bs/enums/ErrorCodeConstants.java | 14 +
yudao-module-bs/yudao-module-bs-biz/pom.xml | 62 +++++
.../admin/invoice/InvoiceController.java | 99 +++++++
.../admin/invoice/vo/InvoiceBaseVO.java | 58 ++++
.../admin/invoice/vo/InvoiceCreateReqVO.java | 14 +
.../admin/invoice/vo/InvoiceExcelVO.java | 68 +++++
.../admin/invoice/vo/InvoiceExportReqVO.java | 63 +++++
.../admin/invoice/vo/InvoicePageReqVO.java | 68 +++++
.../admin/invoice/vo/InvoiceRespVO.java | 34 +++
.../admin/invoice/vo/InvoiceUpdateReqVO.java | 24 ++
.../bs/convert/invoice/InvoiceConvert.java | 36 +++
.../bs/dal/dataobject/invoice/InvoiceDO.java | 90 ++++++
.../bs/dal/mysql/invoice/InvoiceMapper.java | 61 ++++
.../bs/service/invoice/InvoiceService.java | 75 +++++
.../service/invoice/InvoiceServiceImpl.java | 84 ++++++
.../module/bs/web/config/BsConfiguration.java | 24 ++
.../yudao/module/bs/web/package-info.java | 4 +
.../mapper/invoice/InvoiceMapper.xml | 12 +
.../invoice/InvoiceServiceImplTest.java | 263 ++++++++++++++++++
.../application-integration-test.yaml | 2 +-
yudao-server/pom.xml | 6 +
.../src/main/resources/application.yaml | 1 +
25 files changed, 1219 insertions(+), 1 deletion(-)
create mode 100644 yudao-module-bs/pom.xml
create mode 100644 yudao-module-bs/yudao-module-bs-api/pom.xml
create mode 100644 yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ErrorCodeConstants.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/pom.xml
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/InvoiceController.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceBaseVO.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceCreateReqVO.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceExcelVO.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceExportReqVO.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoicePageReqVO.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceRespVO.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceUpdateReqVO.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/convert/invoice/InvoiceConvert.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/invoice/InvoiceDO.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/invoice/InvoiceMapper.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceService.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceServiceImpl.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/web/config/BsConfiguration.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/web/package-info.java
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/invoice/InvoiceMapper.xml
create mode 100644 yudao-module-bs/yudao-module-bs-biz/src/test/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceServiceImplTest.java
diff --git a/pom.xml b/pom.xml
index 53a708d4..2c35b79c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,6 +23,7 @@
+ yudao-module-bs
${project.artifactId}
diff --git a/yudao-module-bs/pom.xml b/yudao-module-bs/pom.xml
new file mode 100644
index 00000000..072be292
--- /dev/null
+++ b/yudao-module-bs/pom.xml
@@ -0,0 +1,23 @@
+
+
+
+ cn.iocoder.boot
+ yudao
+ ${revision}
+
+ 4.0.0
+
+ yudao-module-bs-api
+ yudao-module-bs-biz
+
+ yudao-module-bs
+ pom
+
+ ${project.artifactId}
+
+ 报销系统业务模块
+
+
+
diff --git a/yudao-module-bs/yudao-module-bs-api/pom.xml b/yudao-module-bs/yudao-module-bs-api/pom.xml
new file mode 100644
index 00000000..bad3412b
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-api/pom.xml
@@ -0,0 +1,34 @@
+
+
+ 4.0.0
+
+ cn.iocoder.boot
+ yudao-module-bs
+ ${revision}
+
+
+ yudao-module-bs-api
+ jar
+
+ ${project.artifactId}
+
+ bs 模块 API,暴露给其它模块调用
+
+
+
+
+ cn.iocoder.boot
+ yudao-common
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ true
+
+
+
+
diff --git a/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ErrorCodeConstants.java b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ErrorCodeConstants.java
new file mode 100644
index 00000000..65726454
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ErrorCodeConstants.java
@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.bs.enums;
+
+import cn.iocoder.yudao.framework.common.exception.ErrorCode;
+
+/**
+ * 工作流 错误码枚举类
+ *
+ * 工作流系统,使用 1-009-000-000 段
+ */
+public interface ErrorCodeConstants {
+
+ ErrorCode INVOICE_NOT_EXISTS = new ErrorCode(200100, "我的发票不存在");
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/pom.xml b/yudao-module-bs/yudao-module-bs-biz/pom.xml
new file mode 100644
index 00000000..808be241
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/pom.xml
@@ -0,0 +1,62 @@
+
+
+
+ cn.iocoder.boot
+ yudao-module-bs
+ ${revision}
+
+ 4.0.0
+ yudao-module-bs-biz
+ jar
+
+ ${project.artifactId}
+
+ product 模块,主要实现商品相关功能
+ 例如:品牌、商品分类、spu、sku等功能。
+
+
+
+
+ cn.iocoder.boot
+ yudao-module-bs-api
+ ${revision}
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-biz-operatelog
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-web
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-security
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-mybatis
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-test
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-excel
+
+
+
+
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/InvoiceController.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/InvoiceController.java
new file mode 100644
index 00000000..c8b3c24d
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/InvoiceController.java
@@ -0,0 +1,99 @@
+package cn.iocoder.yudao.module.bs.controller.admin.invoice;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.*;
+import cn.iocoder.yudao.module.bs.convert.invoice.InvoiceConvert;
+import cn.iocoder.yudao.module.bs.dal.dataobject.invoice.InvoiceDO;
+import cn.iocoder.yudao.module.bs.service.invoice.InvoiceService;
+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.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
+
+@Tag(name = "管理后台 - 我的发票")
+@RestController
+@RequestMapping("/bs/invoice")
+@Validated
+public class InvoiceController {
+
+ @Resource
+ private InvoiceService invoiceService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建我的发票")
+ @PreAuthorize("@ss.hasPermission('bs:invoice:create')")
+ public CommonResult createInvoice(@Valid @RequestBody InvoiceCreateReqVO createReqVO) {
+ return success(invoiceService.createInvoice(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新我的发票")
+ @PreAuthorize("@ss.hasPermission('bs:invoice:update')")
+ public CommonResult updateInvoice(@Valid @RequestBody InvoiceUpdateReqVO updateReqVO) {
+ invoiceService.updateInvoice(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除我的发票")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('bs:invoice:delete')")
+ public CommonResult deleteInvoice(@RequestParam("id") Long id) {
+ invoiceService.deleteInvoice(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得我的发票")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bs:invoice:query')")
+ public CommonResult getInvoice(@RequestParam("id") Long id) {
+ InvoiceDO invoice = invoiceService.getInvoice(id);
+ return success(InvoiceConvert.INSTANCE.convert(invoice));
+ }
+
+ @GetMapping("/list")
+ @Operation(summary = "获得我的发票列表")
+ @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
+ @PreAuthorize("@ss.hasPermission('bs:invoice:query')")
+ public CommonResult> getInvoiceList(@RequestParam("ids") Collection ids) {
+ List list = invoiceService.getInvoiceList(ids);
+ return success(InvoiceConvert.INSTANCE.convertList(list));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得我的发票分页")
+ @PreAuthorize("@ss.hasPermission('bs:invoice:query')")
+ public CommonResult> getInvoicePage(@Valid InvoicePageReqVO pageVO) {
+ PageResult pageResult = invoiceService.getInvoicePage(pageVO);
+ return success(InvoiceConvert.INSTANCE.convertPage(pageResult));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出我的发票 Excel")
+ @PreAuthorize("@ss.hasPermission('bs:invoice:export')")
+ @OperateLog(type = EXPORT)
+ public void exportInvoiceExcel(@Valid InvoiceExportReqVO exportReqVO,
+ HttpServletResponse response) throws IOException {
+ List list = invoiceService.getInvoiceList(exportReqVO);
+ // 导出 Excel
+ List datas = InvoiceConvert.INSTANCE.convertList02(list);
+ ExcelUtils.write(response, "我的发票.xls", "数据", InvoiceExcelVO.class, datas);
+ }
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceBaseVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceBaseVO.java
new file mode 100644
index 00000000..f0ea6359
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceBaseVO.java
@@ -0,0 +1,58 @@
+package cn.iocoder.yudao.module.bs.controller.admin.invoice.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 我的发票 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ */
+@Data
+public class InvoiceBaseVO {
+
+ @Schema(description = "发票类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "发票类型不能为空")
+ private String invoiceType;
+
+ @Schema(description = "发票代码", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "发票代码不能为空")
+ private String invoiceCode;
+
+ @Schema(description = " 发票号码", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = " 发票号码不能为空")
+ private String invoiceNum;
+
+ @Schema(description = "开票日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "开票日期不能为空")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime invoiceDate;
+
+ @Schema(description = "销售方")
+ private String seller;
+
+ @Schema(description = "税额")
+ private BigDecimal taxAmount;
+
+ @Schema(description = "不含税金额")
+ private BigDecimal excludingTaxAmount;
+
+ @Schema(description = "价税合计")
+ private BigDecimal totalAmount;
+
+ @Schema(description = "部门ID", example = "30681")
+ private Long deptId;
+
+ @Schema(description = "部门名称", example = "赵六")
+ private String deptName;
+
+ @Schema(description = "备注", example = "随便")
+ private String remark;
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceCreateReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceCreateReqVO.java
new file mode 100644
index 00000000..2b1a2537
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceCreateReqVO.java
@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.bs.controller.admin.invoice.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - 我的发票创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class InvoiceCreateReqVO extends InvoiceBaseVO {
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceExcelVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceExcelVO.java
new file mode 100644
index 00000000..29a42281
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceExcelVO.java
@@ -0,0 +1,68 @@
+package cn.iocoder.yudao.module.bs.controller.admin.invoice.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 我的发票 Excel VO
+ *
+ * @author chenqp
+ */
+@Data
+public class InvoiceExcelVO {
+
+ @ExcelProperty("id")
+ private Long id;
+
+ @ExcelProperty("附件")
+ private String files;
+
+ @ExcelProperty("创建者")
+ private String createBy;
+
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+ @ExcelProperty("更新者")
+ private String updateBy;
+
+ @ExcelProperty("更新时间")
+ private LocalDateTime updateTime;
+
+ @ExcelProperty("发票类型")
+ private String invoiceType;
+
+ @ExcelProperty("发票代码")
+ private String invoiceCode;
+
+ @ExcelProperty(" 发票号码")
+ private String invoiceNum;
+
+ @ExcelProperty("开票日期")
+ private LocalDateTime invoiceDate;
+
+ @ExcelProperty("销售方")
+ private String seller;
+
+ @ExcelProperty("税额")
+ private BigDecimal taxAmount;
+
+ @ExcelProperty("不含税金额")
+ private BigDecimal excludingTaxAmount;
+
+ @ExcelProperty("价税合计")
+ private BigDecimal totalAmount;
+
+ @ExcelProperty("部门ID")
+ private Long deptId;
+
+ @ExcelProperty("部门名称")
+ private String deptName;
+
+ @ExcelProperty("备注")
+ private String remark;
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceExportReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceExportReqVO.java
new file mode 100644
index 00000000..3dca983f
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceExportReqVO.java
@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.bs.controller.admin.invoice.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 我的发票 Excel 导出 Request VO,参数和 InvoicePageReqVO 是一致的")
+@Data
+public class InvoiceExportReqVO {
+
+ @Schema(description = "附件")
+ private String files;
+
+ @Schema(description = "创建者")
+ private String createBy;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+ @Schema(description = "更新者")
+ private String updateBy;
+
+ @Schema(description = "发票类型", example = "1")
+ private String invoiceType;
+
+ @Schema(description = "发票代码")
+ private String invoiceCode;
+
+ @Schema(description = " 发票号码")
+ private String invoiceNum;
+
+ @Schema(description = "开票日期")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] invoiceDate;
+
+ @Schema(description = "销售方")
+ private String seller;
+
+ @Schema(description = "税额")
+ private BigDecimal taxAmount;
+
+ @Schema(description = "不含税金额")
+ private BigDecimal excludingTaxAmount;
+
+ @Schema(description = "价税合计")
+ private BigDecimal totalAmount;
+
+ @Schema(description = "部门ID", example = "30681")
+ private Long deptId;
+
+ @Schema(description = "部门名称", example = "赵六")
+ private String deptName;
+
+ @Schema(description = "备注", example = "随便")
+ private String remark;
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoicePageReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoicePageReqVO.java
new file mode 100644
index 00000000..0ed3dfdf
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoicePageReqVO.java
@@ -0,0 +1,68 @@
+package cn.iocoder.yudao.module.bs.controller.admin.invoice.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 我的发票分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class InvoicePageReqVO extends PageParam {
+
+ @Schema(description = "附件")
+ private String files;
+
+ @Schema(description = "创建者")
+ private String createBy;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+ @Schema(description = "更新者")
+ private String updateBy;
+
+ @Schema(description = "发票类型", example = "1")
+ private String invoiceType;
+
+ @Schema(description = "发票代码")
+ private String invoiceCode;
+
+ @Schema(description = " 发票号码")
+ private String invoiceNum;
+
+ @Schema(description = "开票日期")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] invoiceDate;
+
+ @Schema(description = "销售方")
+ private String seller;
+
+ @Schema(description = "税额")
+ private BigDecimal taxAmount;
+
+ @Schema(description = "不含税金额")
+ private BigDecimal excludingTaxAmount;
+
+ @Schema(description = "价税合计")
+ private BigDecimal totalAmount;
+
+ @Schema(description = "部门ID", example = "30681")
+ private Long deptId;
+
+ @Schema(description = "部门名称", example = "赵六")
+ private String deptName;
+
+ @Schema(description = "备注", example = "随便")
+ private String remark;
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceRespVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceRespVO.java
new file mode 100644
index 00000000..1d975252
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceRespVO.java
@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.bs.controller.admin.invoice.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 我的发票 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class InvoiceRespVO extends InvoiceBaseVO {
+
+ @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "32435")
+ private Long id;
+
+ @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED)
+ private String files;
+
+ @Schema(description = "创建者")
+ private String createBy;
+
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+
+ @Schema(description = "更新者")
+ private String updateBy;
+
+ @Schema(description = "更新时间")
+ private LocalDateTime updateTime;
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceUpdateReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceUpdateReqVO.java
new file mode 100644
index 00000000..999922ee
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/invoice/vo/InvoiceUpdateReqVO.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.bs.controller.admin.invoice.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - 我的发票更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class InvoiceUpdateReqVO extends InvoiceBaseVO {
+
+ @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "32435")
+ @NotNull(message = "id不能为空")
+ private Long id;
+
+ @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "附件不能为空")
+ private String files;
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/convert/invoice/InvoiceConvert.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/convert/invoice/InvoiceConvert.java
new file mode 100644
index 00000000..f76d82cf
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/convert/invoice/InvoiceConvert.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.bs.convert.invoice;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceCreateReqVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceExcelVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceRespVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceUpdateReqVO;
+import cn.iocoder.yudao.module.bs.dal.dataobject.invoice.InvoiceDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 我的发票 Convert
+ *
+ * @author chenqp
+ */
+@Mapper
+public interface InvoiceConvert {
+
+ InvoiceConvert INSTANCE = Mappers.getMapper(InvoiceConvert.class);
+
+ InvoiceDO convert(InvoiceCreateReqVO bean);
+
+ InvoiceDO convert(InvoiceUpdateReqVO bean);
+
+ InvoiceRespVO convert(InvoiceDO bean);
+
+ List convertList(List list);
+
+ PageResult convertPage(PageResult page);
+
+ List convertList02(List list);
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/invoice/InvoiceDO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/invoice/InvoiceDO.java
new file mode 100644
index 00000000..ffd2e5c6
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/invoice/InvoiceDO.java
@@ -0,0 +1,90 @@
+package cn.iocoder.yudao.module.bs.dal.dataobject.invoice;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 我的发票 DO
+ *
+ * @author chenqp
+ */
+@TableName("bs_invoice")
+@KeySequence("bs_invoice_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class InvoiceDO extends BaseDO {
+
+ /**
+ * id
+ */
+ @TableId
+ private Long id;
+ /**
+ * 附件
+ */
+ private String files;
+ /**
+ * 创建者
+ */
+ private String createBy;
+ /**
+ * 更新者
+ */
+ private String updateBy;
+ /**
+ * 发票类型
+ */
+ private String invoiceType;
+ /**
+ * 发票代码
+ */
+ private String invoiceCode;
+ /**
+ * 发票号码
+ */
+ private String invoiceNum;
+ /**
+ * 开票日期
+ */
+ private LocalDateTime invoiceDate;
+ /**
+ * 销售方
+ */
+ private String seller;
+ /**
+ * 税额
+ */
+ private BigDecimal taxAmount;
+ /**
+ * 不含税金额
+ */
+ private BigDecimal excludingTaxAmount;
+ /**
+ * 价税合计
+ */
+ private BigDecimal totalAmount;
+ /**
+ * 部门ID
+ */
+ private Long deptId;
+ /**
+ * 部门名称
+ */
+ private String deptName;
+ /**
+ * 备注
+ */
+ private String remark;
+
+ @TableField(exist = false)
+ private Boolean deleted;
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/invoice/InvoiceMapper.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/invoice/InvoiceMapper.java
new file mode 100644
index 00000000..c4633ac7
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/invoice/InvoiceMapper.java
@@ -0,0 +1,61 @@
+package cn.iocoder.yudao.module.bs.dal.mysql.invoice;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceExportReqVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoicePageReqVO;
+import cn.iocoder.yudao.module.bs.dal.dataobject.invoice.InvoiceDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 我的发票 Mapper
+ *
+ * @author chenqp
+ */
+@Mapper
+public interface InvoiceMapper extends BaseMapperX {
+
+ default PageResult selectPage(InvoicePageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eqIfPresent(InvoiceDO::getFiles, reqVO.getFiles())
+ .eqIfPresent(InvoiceDO::getCreateBy, reqVO.getCreateBy())
+ .betweenIfPresent(InvoiceDO::getCreateTime, reqVO.getCreateTime())
+ .eqIfPresent(InvoiceDO::getUpdateBy, reqVO.getUpdateBy())
+ .eqIfPresent(InvoiceDO::getInvoiceType, reqVO.getInvoiceType())
+ .eqIfPresent(InvoiceDO::getInvoiceCode, reqVO.getInvoiceCode())
+ .eqIfPresent(InvoiceDO::getInvoiceNum, reqVO.getInvoiceNum())
+ .betweenIfPresent(InvoiceDO::getInvoiceDate, reqVO.getInvoiceDate())
+ .eqIfPresent(InvoiceDO::getSeller, reqVO.getSeller())
+ .eqIfPresent(InvoiceDO::getTaxAmount, reqVO.getTaxAmount())
+ .eqIfPresent(InvoiceDO::getExcludingTaxAmount, reqVO.getExcludingTaxAmount())
+ .eqIfPresent(InvoiceDO::getTotalAmount, reqVO.getTotalAmount())
+ .eqIfPresent(InvoiceDO::getDeptId, reqVO.getDeptId())
+ .likeIfPresent(InvoiceDO::getDeptName, reqVO.getDeptName())
+ .eqIfPresent(InvoiceDO::getRemark, reqVO.getRemark())
+ .orderByDesc(InvoiceDO::getId));
+ }
+
+ default List selectList(InvoiceExportReqVO reqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .eqIfPresent(InvoiceDO::getFiles, reqVO.getFiles())
+ .eqIfPresent(InvoiceDO::getCreateBy, reqVO.getCreateBy())
+ .betweenIfPresent(InvoiceDO::getCreateTime, reqVO.getCreateTime())
+ .eqIfPresent(InvoiceDO::getUpdateBy, reqVO.getUpdateBy())
+ .eqIfPresent(InvoiceDO::getInvoiceType, reqVO.getInvoiceType())
+ .eqIfPresent(InvoiceDO::getInvoiceCode, reqVO.getInvoiceCode())
+ .eqIfPresent(InvoiceDO::getInvoiceNum, reqVO.getInvoiceNum())
+ .betweenIfPresent(InvoiceDO::getInvoiceDate, reqVO.getInvoiceDate())
+ .eqIfPresent(InvoiceDO::getSeller, reqVO.getSeller())
+ .eqIfPresent(InvoiceDO::getTaxAmount, reqVO.getTaxAmount())
+ .eqIfPresent(InvoiceDO::getExcludingTaxAmount, reqVO.getExcludingTaxAmount())
+ .eqIfPresent(InvoiceDO::getTotalAmount, reqVO.getTotalAmount())
+ .eqIfPresent(InvoiceDO::getDeptId, reqVO.getDeptId())
+ .likeIfPresent(InvoiceDO::getDeptName, reqVO.getDeptName())
+ .eqIfPresent(InvoiceDO::getRemark, reqVO.getRemark())
+ .orderByDesc(InvoiceDO::getId));
+ }
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceService.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceService.java
new file mode 100644
index 00000000..2f33c2ae
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceService.java
@@ -0,0 +1,75 @@
+package cn.iocoder.yudao.module.bs.service.invoice;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceCreateReqVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceExportReqVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoicePageReqVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceUpdateReqVO;
+import cn.iocoder.yudao.module.bs.dal.dataobject.invoice.InvoiceDO;
+
+import javax.validation.Valid;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 我的发票 Service 接口
+ *
+ * @author chenqp
+ */
+public interface InvoiceService {
+
+ /**
+ * 创建我的发票
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createInvoice(@Valid InvoiceCreateReqVO createReqVO);
+
+ /**
+ * 更新我的发票
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateInvoice(@Valid InvoiceUpdateReqVO updateReqVO);
+
+ /**
+ * 删除我的发票
+ *
+ * @param id 编号
+ */
+ void deleteInvoice(Long id);
+
+ /**
+ * 获得我的发票
+ *
+ * @param id 编号
+ * @return 我的发票
+ */
+ InvoiceDO getInvoice(Long id);
+
+ /**
+ * 获得我的发票列表
+ *
+ * @param ids 编号
+ * @return 我的发票列表
+ */
+ List getInvoiceList(Collection ids);
+
+ /**
+ * 获得我的发票分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 我的发票分页
+ */
+ PageResult getInvoicePage(InvoicePageReqVO pageReqVO);
+
+ /**
+ * 获得我的发票列表, 用于 Excel 导出
+ *
+ * @param exportReqVO 查询条件
+ * @return 我的发票列表
+ */
+ List getInvoiceList(InvoiceExportReqVO exportReqVO);
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceServiceImpl.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceServiceImpl.java
new file mode 100644
index 00000000..e6d5618a
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceServiceImpl.java
@@ -0,0 +1,84 @@
+package cn.iocoder.yudao.module.bs.service.invoice;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceCreateReqVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceExportReqVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoicePageReqVO;
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.InvoiceUpdateReqVO;
+import cn.iocoder.yudao.module.bs.convert.invoice.InvoiceConvert;
+import cn.iocoder.yudao.module.bs.dal.dataobject.invoice.InvoiceDO;
+import cn.iocoder.yudao.module.bs.dal.mysql.invoice.InvoiceMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.bs.enums.ErrorCodeConstants.INVOICE_NOT_EXISTS;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 我的发票 Service 实现类
+ *
+ * @author chenqp
+ */
+@Service
+@Validated
+public class InvoiceServiceImpl implements InvoiceService {
+
+ @Resource
+ private InvoiceMapper invoiceMapper;
+
+ @Override
+ public Long createInvoice(InvoiceCreateReqVO createReqVO) {
+ // 插入
+ InvoiceDO invoice = InvoiceConvert.INSTANCE.convert(createReqVO);
+ invoiceMapper.insert(invoice);
+ // 返回
+ return invoice.getId();
+ }
+
+ @Override
+ public void updateInvoice(InvoiceUpdateReqVO updateReqVO) {
+ // 校验存在
+ validateInvoiceExists(updateReqVO.getId());
+ // 更新
+ InvoiceDO updateObj = InvoiceConvert.INSTANCE.convert(updateReqVO);
+ invoiceMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteInvoice(Long id) {
+ // 校验存在
+ validateInvoiceExists(id);
+ // 删除
+ invoiceMapper.deleteById(id);
+ }
+
+ private void validateInvoiceExists(Long id) {
+ if (invoiceMapper.selectById(id) == null) {
+ throw exception(INVOICE_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public InvoiceDO getInvoice(Long id) {
+ return invoiceMapper.selectById(id);
+ }
+
+ @Override
+ public List getInvoiceList(Collection ids) {
+ return invoiceMapper.selectBatchIds(ids);
+ }
+
+ @Override
+ public PageResult getInvoicePage(InvoicePageReqVO pageReqVO) {
+ return invoiceMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public List getInvoiceList(InvoiceExportReqVO exportReqVO) {
+ return invoiceMapper.selectList(exportReqVO);
+ }
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/web/config/BsConfiguration.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/web/config/BsConfiguration.java
new file mode 100644
index 00000000..bc0aa347
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/web/config/BsConfiguration.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.bs.web.config;
+
+import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration;
+import org.springdoc.core.GroupedOpenApi;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * system 模块的 web 组件的 Configuration
+ *
+ * @author 芋道源码
+ */
+@Configuration(proxyBeanMethods = false)
+public class BsConfiguration {
+
+ /**
+ * system 模块的 API 分组
+ */
+ @Bean
+ public GroupedOpenApi bsGroupedOpenApi() {
+ return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("bs");
+ }
+
+}
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/web/package-info.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/web/package-info.java
new file mode 100644
index 00000000..e8b3c97e
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/web/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * system 模块的 web 配置
+ */
+package cn.iocoder.yudao.module.bs.web;
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/invoice/InvoiceMapper.xml b/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/invoice/InvoiceMapper.xml
new file mode 100644
index 00000000..a7183e1a
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/invoice/InvoiceMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/yudao-module-bs/yudao-module-bs-biz/src/test/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceServiceImplTest.java b/yudao-module-bs/yudao-module-bs-biz/src/test/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceServiceImplTest.java
new file mode 100644
index 00000000..71d5c516
--- /dev/null
+++ b/yudao-module-bs/yudao-module-bs-biz/src/test/java/cn/iocoder/yudao/module/bs/service/invoice/InvoiceServiceImplTest.java
@@ -0,0 +1,263 @@
+package cn.iocoder.yudao.module.bs.service.invoice;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+import javax.annotation.Resource;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.iocoder.yudao.module.bs.controller.admin.invoice.vo.*;
+import cn.iocoder.yudao.module.bs.dal.dataobject.invoice.InvoiceDO;
+import cn.iocoder.yudao.module.bs.dal.mysql.invoice.InvoiceMapper;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import javax.annotation.Resource;
+import org.springframework.context.annotation.Import;
+import java.util.*;
+import java.time.LocalDateTime;
+
+import static cn.hutool.core.util.RandomUtil.*;
+import static cn.iocoder.yudao.module.bs.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link InvoiceServiceImpl} 的单元测试类
+ *
+ * @author chenqp
+ */
+@Import(InvoiceServiceImpl.class)
+public class InvoiceServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private InvoiceServiceImpl invoiceService;
+
+ @Resource
+ private InvoiceMapper invoiceMapper;
+
+ @Test
+ public void testCreateInvoice_success() {
+ // 准备参数
+ InvoiceCreateReqVO reqVO = randomPojo(InvoiceCreateReqVO.class);
+
+ // 调用
+ Long invoiceId = invoiceService.createInvoice(reqVO);
+ // 断言
+ assertNotNull(invoiceId);
+ // 校验记录的属性是否正确
+ InvoiceDO invoice = invoiceMapper.selectById(invoiceId);
+ assertPojoEquals(reqVO, invoice);
+ }
+
+ @Test
+ public void testUpdateInvoice_success() {
+ // mock 数据
+ InvoiceDO dbInvoice = randomPojo(InvoiceDO.class);
+ invoiceMapper.insert(dbInvoice);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ InvoiceUpdateReqVO reqVO = randomPojo(InvoiceUpdateReqVO.class, o -> {
+ o.setId(dbInvoice.getId()); // 设置更新的 ID
+ });
+
+ // 调用
+ invoiceService.updateInvoice(reqVO);
+ // 校验是否更新正确
+ InvoiceDO invoice = invoiceMapper.selectById(reqVO.getId()); // 获取最新的
+ assertPojoEquals(reqVO, invoice);
+ }
+
+ @Test
+ public void testUpdateInvoice_notExists() {
+ // 准备参数
+ InvoiceUpdateReqVO reqVO = randomPojo(InvoiceUpdateReqVO.class);
+
+ // 调用, 并断言异常
+ assertServiceException(() -> invoiceService.updateInvoice(reqVO), INVOICE_NOT_EXISTS);
+ }
+
+ @Test
+ public void testDeleteInvoice_success() {
+ // mock 数据
+ InvoiceDO dbInvoice = randomPojo(InvoiceDO.class);
+ invoiceMapper.insert(dbInvoice);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbInvoice.getId();
+
+ // 调用
+ invoiceService.deleteInvoice(id);
+ // 校验数据不存在了
+ assertNull(invoiceMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteInvoice_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> invoiceService.deleteInvoice(id), INVOICE_NOT_EXISTS);
+ }
+
+ @Test
+ @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+ public void testGetInvoicePage() {
+ // mock 数据
+ InvoiceDO dbInvoice = randomPojo(InvoiceDO.class, o -> { // 等会查询到
+ o.setFiles(null);
+ o.setCreateBy(null);
+ o.setCreateTime(null);
+ o.setUpdateBy(null);
+ o.setInvoiceType(null);
+ o.setInvoiceCode(null);
+ o.setInvoiceNum(null);
+ o.setInvoiceDate(null);
+ o.setSeller(null);
+ o.setTaxAmount(null);
+ o.setExcludingTaxAmount(null);
+ o.setTotalAmount(null);
+ o.setDeptId(null);
+ o.setDeptName(null);
+ o.setRemark(null);
+ });
+ invoiceMapper.insert(dbInvoice);
+ // 测试 files 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setFiles(null)));
+ // 测试 createBy 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setCreateBy(null)));
+ // 测试 createTime 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setCreateTime(null)));
+ // 测试 updateBy 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setUpdateBy(null)));
+ // 测试 invoiceType 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setInvoiceType(null)));
+ // 测试 invoiceCode 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setInvoiceCode(null)));
+ // 测试 invoiceNum 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setInvoiceNum(null)));
+ // 测试 invoiceDate 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setInvoiceDate(null)));
+ // 测试 seller 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setSeller(null)));
+ // 测试 taxAmount 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setTaxAmount(null)));
+ // 测试 excludingTaxAmount 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setExcludingTaxAmount(null)));
+ // 测试 totalAmount 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setTotalAmount(null)));
+ // 测试 deptId 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setDeptId(null)));
+ // 测试 deptName 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setDeptName(null)));
+ // 测试 remark 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setRemark(null)));
+ // 准备参数
+ InvoicePageReqVO reqVO = new InvoicePageReqVO();
+ reqVO.setFiles(null);
+ reqVO.setCreateBy(null);
+ reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+ reqVO.setUpdateBy(null);
+ reqVO.setInvoiceType(null);
+ reqVO.setInvoiceCode(null);
+ reqVO.setInvoiceNum(null);
+ reqVO.setInvoiceDate(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+ reqVO.setSeller(null);
+ reqVO.setTaxAmount(null);
+ reqVO.setExcludingTaxAmount(null);
+ reqVO.setTotalAmount(null);
+ reqVO.setDeptId(null);
+ reqVO.setDeptName(null);
+ reqVO.setRemark(null);
+
+ // 调用
+ PageResult pageResult = invoiceService.getInvoicePage(reqVO);
+ // 断言
+ assertEquals(1, pageResult.getTotal());
+ assertEquals(1, pageResult.getList().size());
+ assertPojoEquals(dbInvoice, pageResult.getList().get(0));
+ }
+
+ @Test
+ @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+ public void testGetInvoiceList() {
+ // mock 数据
+ InvoiceDO dbInvoice = randomPojo(InvoiceDO.class, o -> { // 等会查询到
+ o.setFiles(null);
+ o.setCreateBy(null);
+ o.setCreateTime(null);
+ o.setUpdateBy(null);
+ o.setInvoiceType(null);
+ o.setInvoiceCode(null);
+ o.setInvoiceNum(null);
+ o.setInvoiceDate(null);
+ o.setSeller(null);
+ o.setTaxAmount(null);
+ o.setExcludingTaxAmount(null);
+ o.setTotalAmount(null);
+ o.setDeptId(null);
+ o.setDeptName(null);
+ o.setRemark(null);
+ });
+ invoiceMapper.insert(dbInvoice);
+ // 测试 files 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setFiles(null)));
+ // 测试 createBy 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setCreateBy(null)));
+ // 测试 createTime 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setCreateTime(null)));
+ // 测试 updateBy 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setUpdateBy(null)));
+ // 测试 invoiceType 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setInvoiceType(null)));
+ // 测试 invoiceCode 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setInvoiceCode(null)));
+ // 测试 invoiceNum 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setInvoiceNum(null)));
+ // 测试 invoiceDate 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setInvoiceDate(null)));
+ // 测试 seller 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setSeller(null)));
+ // 测试 taxAmount 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setTaxAmount(null)));
+ // 测试 excludingTaxAmount 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setExcludingTaxAmount(null)));
+ // 测试 totalAmount 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setTotalAmount(null)));
+ // 测试 deptId 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setDeptId(null)));
+ // 测试 deptName 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setDeptName(null)));
+ // 测试 remark 不匹配
+ invoiceMapper.insert(cloneIgnoreId(dbInvoice, o -> o.setRemark(null)));
+ // 准备参数
+ InvoiceExportReqVO reqVO = new InvoiceExportReqVO();
+ reqVO.setFiles(null);
+ reqVO.setCreateBy(null);
+ reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+ reqVO.setUpdateBy(null);
+ reqVO.setInvoiceType(null);
+ reqVO.setInvoiceCode(null);
+ reqVO.setInvoiceNum(null);
+ reqVO.setInvoiceDate(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+ reqVO.setSeller(null);
+ reqVO.setTaxAmount(null);
+ reqVO.setExcludingTaxAmount(null);
+ reqVO.setTotalAmount(null);
+ reqVO.setDeptId(null);
+ reqVO.setDeptName(null);
+ reqVO.setRemark(null);
+
+ // 调用
+ List list = invoiceService.getInvoiceList(reqVO);
+ // 断言
+ assertEquals(1, list.size());
+ assertPojoEquals(dbInvoice, list.get(0));
+ }
+
+}
diff --git a/yudao-module-system/yudao-module-system-biz/src/test-integration/resources/application-integration-test.yaml b/yudao-module-system/yudao-module-system-biz/src/test-integration/resources/application-integration-test.yaml
index d9612eee..a801d62d 100644
--- a/yudao-module-system/yudao-module-system-biz/src/test-integration/resources/application-integration-test.yaml
+++ b/yudao-module-system/yudao-module-system-biz/src/test-integration/resources/application-integration-test.yaml
@@ -92,7 +92,7 @@ resilience4j:
yudao:
security:
token-header: Authorization
- token-secret: abcdefghijklmnopqrstuvwxyz
+ token-secret: sabszefopxqrstgjyuzyupz
token-timeout: 1d
session-timeout: 30m
mock-enable: true
diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml
index e2e95b4e..01ade2aa 100644
--- a/yudao-server/pom.xml
+++ b/yudao-server/pom.xml
@@ -21,6 +21,12 @@
https://github.com/YunaiV/ruoyi-vue-pro
+
+
+ cn.iocoder.boot
+ yudao-module-bs-biz
+ ${revision}
+
cn.iocoder.boot
yudao-module-member-biz
diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml
index 8108af64..b4e917c8 100644
--- a/yudao-server/src/main/resources/application.yaml
+++ b/yudao-server/src/main/resources/application.yaml
@@ -134,6 +134,7 @@ yudao:
- cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants
- cn.iocoder.yudao.module.system.enums.ErrorCodeConstants
- cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants
+ - cn.iocoder.yudao.module.mp.bs.ErrorCodeConstants
tenant: # 多租户相关配置项
enable: true
ignore-urls: