diff --git a/cf-module-infra/cf-module-infra-api/src/main/java/com/cf/imes/module/infra/api/file/FileApi.java b/cf-module-infra/cf-module-infra-api/src/main/java/com/cf/imes/module/infra/api/file/FileApi.java index f88602000..9987d8a1f 100644 --- a/cf-module-infra/cf-module-infra-api/src/main/java/com/cf/imes/module/infra/api/file/FileApi.java +++ b/cf-module-infra/cf-module-infra-api/src/main/java/com/cf/imes/module/infra/api/file/FileApi.java @@ -30,6 +30,17 @@ public interface FileApi { return createFile(null, null, content); } + /** + * 保存文件,并返回文件的访问路径 + * + * @param content 文件内容 + * @param fileName 文件名称 + * @return 文件路径 + */ + default String createFile(byte[] content, String fileName) { + return createFile(fileName, null, content); + } + /** * 保存文件,并返回文件的访问路径 * diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java index 2ddac23a3..eb7b74b78 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java @@ -418,9 +418,9 @@ public class ErrorCodeConstants { public static final ErrorCode INVOICE_FILE_UPLOAD_FAILED = new ErrorCode(1_002_043_005, "发票附件上传失败,请重新上传"); public static final ErrorCode INVOICE_FILE_IS_NULL_NOT_DOWNLOAD = new ErrorCode(1_002_043_006, "发票附件不存在,无法下载"); public static final ErrorCode INVOICE_FILE_DATA_ERROR = new ErrorCode(1_002_043_007, "发票附件下载失败,请重新下载或稍等重试"); - public static final ErrorCode PURCHASE_RECORD_NO_EXIST = new ErrorCode(1_002_043_008, "当前发票对应的购买记录有误,请删除重新创建发票"); + public static final ErrorCode PURCHASE_RECORD_NO_EXIST = new ErrorCode(1_002_043_008, "当前发票对应的购买记录有误,请退回组织后重新申请开票"); public static final ErrorCode INVOICE_TITLE_NO_EXIST = new ErrorCode(1_002_043_009, "发票抬头信息有误,请进行查看"); - public static final ErrorCode THIS_INVOICE_IS_FAIL = new ErrorCode(1_002_043_010, "当前发票以开票,无法再次进行开票"); + public static final ErrorCode THIS_INVOICE_IS_FAIL = new ErrorCode(1_002_043_010, "当前发票已开票,无法再次进行开票"); public static final ErrorCode THIS_INVOICE_IS_SUCCESS = new ErrorCode(1_002_043_011, "当前发票已经开票,无法再次进行开票"); public static final ErrorCode PRODUCTS_IS_EXIST = new ErrorCode(1_002_043_012, "产品【{}】已存在,请修改产品名称后再次操作"); public static final ErrorCode PRODUCTS_NO_DELETE = new ErrorCode(1_002_043_013, "当前产品已上架,无法删除,请下架后再删除"); @@ -439,6 +439,7 @@ public class ErrorCodeConstants { public static final ErrorCode PAY_RECHARGE_ACTIVITY_EXPIRE_ERROR = new ErrorCode(1_002_043_027, "充值活动已结束,请选择其他充值活动!"); public static final ErrorCode INVOICE_TITLE_NOT_EXISTS_ERROR = new ErrorCode(1_002_043_028, "发票抬头不存在,请先创建发票抬头"); public static final ErrorCode ORG_INVOICE_PURCHASE_RECORD_UPDATE_NUM_NOT_MATCH_ERROR = new ErrorCode(1_002_043_029, "当前勾选的购买记录中部分可能已开票,请查询后重新勾选提交开票"); + public static final ErrorCode ORG_INVOICE_AGREE_FILE_NULL_ERROR = new ErrorCode(1_002_043_030, "确认开票发票附件不能为空,请上传后再提交"); //=========== 支付相关 1-002-048-000 ============ public static final ErrorCode PAY_CHANNEL_NOT_SUPPORT = new ErrorCode(1_002_048_000, "暂不支持的支付渠道,请使用其他支付渠道"); diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/InvoiceController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/InvoiceController.java index 69b132d65..f1d8e115a 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/InvoiceController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/InvoiceController.java @@ -1,26 +1,34 @@ package com.cf.imes.module.system.controller.admin.funds.invoice; - import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageReqVO; -import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageRespVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountRespVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceConfirmReqVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsRespVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceRecordsReqVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceRecordsRespVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceTitleReqVO; +import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO; import com.cf.imes.module.system.service.funds.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.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import jakarta.annotation.Resource; import jakarta.validation.Valid; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; import static com.cf.imes.framework.common.pojo.CommonResult.success; @@ -34,7 +42,6 @@ import static com.cf.imes.framework.common.pojo.CommonResult.success; @Validated public class InvoiceController { - @Resource private InvoiceService invoiceService; @@ -46,15 +53,27 @@ public class InvoiceController { return success(Boolean.TRUE); } - @GetMapping("/available/info") + @GetMapping("/org/amount") @Operation(summary = "获取组织的开票金额信息") - public CommonResult getInvoiceAmountAndAvailablePage(@Valid InvoiceAmountAndAvailablePageReqVO pageReqVO) { - return success(invoiceService.getInvoiceAmountAndAvailablePage(pageReqVO)); + public CommonResult getInvoiceAmount(@Valid InvoiceAmountAndAvailablePageReqVO pageReqVO) { + return success(invoiceService.getInvoiceAmount(pageReqVO)); + } + + @GetMapping("/available") + @Operation(summary = "获取组织可开票购买记录") + public CommonResult> getAvailablePage(@Valid InvoiceAmountAndAvailablePageReqVO pageReqVO) { + return success(invoiceService.getAvailablePage(pageReqVO)); + } + + @GetMapping("/manage/amount") + @Operation(summary = "获取管理端开票金额信息") + public CommonResult getManageEndPointInvoiceAmount(@Valid InvoiceAmountAndAvailablePageReqVO pageReqVO) { + return success(invoiceService.getManageInvoiceAmount(pageReqVO)); } @PostMapping("") @Operation(summary = "组织申请开票") - public CommonResult insetInvoiceRecords(@Valid @RequestBody InvoiceRecordsReqVO reqVO) { + public CommonResult applyInvoiceRecords(@Valid @RequestBody InvoiceRecordsReqVO reqVO) { invoiceService.applyInvoice(reqVO); return success(Boolean.TRUE); } @@ -64,4 +83,19 @@ public class InvoiceController { public CommonResult> getInvoiceRecords(@Valid InvoiceDetailsPageReqVO pageReqVO) { return success(invoiceService.getInvoiceRecords(pageReqVO)); } + + @GetMapping("/record/{recordId}") + @Parameter(name = "recordId", description = "发票申请记录ID", required = true) + @Operation(summary = "获取开票记录对应的购买记录和抬头信息") + public CommonResult getInvoiceRecordDetail(@PathVariable("recordId") Long recordId) { + return success(invoiceService.getInvoiceRecordDetail(recordId)); + } + + @PostMapping("/confirm") + @Operation(summary = "确认发票") + public CommonResult confirmInvoice(@Valid @RequestPart("invoiceConfirmInfo") InvoiceConfirmReqVO reqVO, + @RequestPart(value = "file", required = false) MultipartFile file) throws IOException { + invoiceService.confirmInvoice(reqVO, file); + return success(Boolean.TRUE); + } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountRespVO.java index 856689072..4a81324aa 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountRespVO.java @@ -6,17 +6,18 @@ import lombok.Data; import java.math.BigDecimal; @Data +@Schema(description = "组织开票金额信息 Resp VO") public class InvoiceAmountRespVO { - @Schema(description = "可开票") private BigDecimal invocable; + @Schema(description = "待开票") + private BigDecimal pendingInvoice; @Schema(description = "开票中") private BigDecimal inTheInvoice; - @Schema(description = "已开票") private BigDecimal invoiced; diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceConfirmReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceConfirmReqVO.java new file mode 100644 index 000000000..e466814bd --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceConfirmReqVO.java @@ -0,0 +1,29 @@ +package com.cf.imes.module.system.controller.admin.funds.invoice.vo; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +@Data +@Schema(description = "管理后台 - 发票确认请求 Request VO") +public class InvoiceConfirmReqVO { + + + @Schema(description = "发票抬头ID") + private Long id; + + + @Schema(description = "是否开票") + private boolean agree; + + + @Schema(description = "发票号") + @Length(max = 32, message = "发票号长度不能超过 32 个字符") + private String invoiceNo; + + + @Schema(description = "备注") + @Length(max = 1024, message = "备注1长度不能超过 1024 个字符") + private String remark; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsRespVO.java index 9a34be0e1..ed988ba7a 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsRespVO.java @@ -7,6 +7,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; import java.util.List; @@ -14,15 +15,22 @@ import java.util.List; @Builder @NoArgsConstructor @AllArgsConstructor +@Schema(description = "发票申请详情 Response VO") public class InvoiceDetailsRespVO { @Schema(description = "发票对应的购买记录") private List invoicePurchaseRecords; - @Schema(description = "发票抬头信息") private InvoiceTitleInfo invoiceTitleInfo; + @Schema(description = "申请人") + private String applicant; + @Schema(description = "申请组织") + private String orgName; + + @Schema(description = "申请时间") + private LocalDateTime applyTime; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoicePurchaseRecord.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoicePurchaseRecord.java index 1ac449833..9cd28f971 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoicePurchaseRecord.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoicePurchaseRecord.java @@ -1,14 +1,13 @@ package com.cf.imes.module.system.controller.admin.funds.invoice.vo; - import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; - @Data +@Schema(description = "发票购买记录信息") public class InvoicePurchaseRecord { @@ -29,7 +28,7 @@ public class InvoicePurchaseRecord { @Schema(description = "可开票金额") - private BigDecimal rechargeAmount; + private BigDecimal invoicableAmount; @Schema(description = "交易时间") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/invoice/InvoiceRecordsMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/invoice/InvoiceRecordsMapper.java index 69010402b..979467b3b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/invoice/InvoiceRecordsMapper.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/invoice/InvoiceRecordsMapper.java @@ -5,6 +5,7 @@ import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountRespVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsPageReqVO; import com.cf.imes.module.system.dal.dataobject.funds.invoice.InvoiceRecordsDO; import org.apache.ibatis.annotations.Mapper; @@ -25,4 +26,11 @@ public interface InvoiceRecordsMapper extends BaseMapperX { .betweenIfPresent(InvoiceRecordsDO::getCreateTime,pageReqVO.getCreateTime()) .betweenIfPresent(InvoiceRecordsDO::getInvoiceTime,pageReqVO.getInvoiceTime())); } + + /** + * 查询管理端开票金额统计:待开票、已开票 + * + * @return + */ + InvoiceAmountRespVO getManageInvoiceAmountStatistics(); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceService.java index 852fc9037..6eeb170aa 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceService.java @@ -1,13 +1,18 @@ package com.cf.imes.module.system.service.funds.invoice; - import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageReqVO; -import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageRespVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountRespVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceConfirmReqVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsRespVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceRecordsReqVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceRecordsRespVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceTitleReqVO; +import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; /** * @author 发票管理接口 @@ -22,12 +27,29 @@ public interface InvoiceService { void insetInvoiceTitle(InvoiceTitleReqVO reqVO); /** - * 查询组织开票金额和可开票列表 + * 查询组织开票金额 * * @param invoiceAmountAndAvailablePageReqVO * @return */ - InvoiceAmountAndAvailablePageRespVO getInvoiceAmountAndAvailablePage(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO); + InvoiceAmountRespVO getInvoiceAmount(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO); + + /** + * 查询管理端开票金额 + * + * @param invoiceAmountAndAvailablePageReqVO + * @return + */ + InvoiceAmountRespVO getManageInvoiceAmount(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO); + + + /** + * 查询组织可开票购买记录 + * + * @param invoiceAmountAndAvailablePageReqVO + * @return + */ + PageResult getAvailablePage(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO); /** * 组织申请发票 @@ -43,4 +65,19 @@ public interface InvoiceService { * @return */ PageResult getInvoiceRecords(InvoiceDetailsPageReqVO pageReqVO); + + /** + * 获取开票记录明细 + * + * @param recordId + * @return + */ + InvoiceDetailsRespVO getInvoiceRecordDetail(Long recordId); + + /** + * 确认发票 + * + * @param reqVO + */ + void confirmInvoice(InvoiceConfirmReqVO reqVO, MultipartFile file) throws IOException; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java index db6484bf8..34d7e7143 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java @@ -1,6 +1,9 @@ package com.cf.imes.module.system.service.funds.invoice; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.common.exception.ServiceException; @@ -11,11 +14,16 @@ import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.security.core.LoginUser; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; +import com.cf.imes.module.infra.api.file.FileApi; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageReqVO; -import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageRespVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountRespVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceConfirmReqVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsRespVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoicePurchaseRecord; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceRecordsReqVO; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceRecordsRespVO; +import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceTitleInfo; import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceTitleReqVO; import com.cf.imes.module.system.dal.dataobject.funds.invoice.InvoiceRecordsDO; import com.cf.imes.module.system.dal.dataobject.funds.invoice.InvoiceTitleInfoDO; @@ -25,19 +33,33 @@ import com.cf.imes.module.system.dal.mysql.funds.invoice.InvoiceRecordsMapper; import com.cf.imes.module.system.dal.mysql.funds.invoice.InvoiceTitleInfoMapper; import com.cf.imes.module.system.dal.mysql.funds.purchase.PurchaseRecordMapper; import com.cf.imes.module.system.enums.pay.InvoiceStatusEnum; +import com.cf.imes.module.system.enums.pay.TradeTypeEnum; import com.cf.imes.module.system.service.organ.OrganService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import jakarta.annotation.Resource; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; +import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.cf.imes.framework.common.util.json.JsonUtils.parseObject; import static com.cf.imes.framework.common.util.json.JsonUtils.toJsonString; +import static com.cf.imes.framework.common.util.json.JsonUtils.unzipString; import static com.cf.imes.framework.common.util.json.JsonUtils.zipString; +import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.INVOICE_NO_EXIST; import static com.cf.imes.module.system.enums.ErrorCodeConstants.INVOICE_TITLE_NOT_EXISTS_ERROR; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.INVOICING_REJECT_REASON; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORG_INVOICE_AGREE_FILE_NULL_ERROR; import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORG_INVOICE_PURCHASE_RECORD_UPDATE_NUM_NOT_MATCH_ERROR; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.PURCHASE_RECORD_NO_EXIST; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.THIS_INVOICE_IS_FAIL; /** @@ -60,6 +82,9 @@ public class InvoiceServiceImpl implements InvoiceService { @Resource private OrganService organService; + @Resource + private FileApi fileApi; + @Override public void insetInvoiceTitle(InvoiceTitleReqVO reqVO) { @@ -101,15 +126,18 @@ public class InvoiceServiceImpl implements InvoiceService { } @Override - public InvoiceAmountAndAvailablePageRespVO getInvoiceAmountAndAvailablePage(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO) { - InvoiceAmountAndAvailablePageRespVO invoiceAmountAndAvailablePageRespVO = new InvoiceAmountAndAvailablePageRespVO(); - // 开票金额 - invoiceAmountAndAvailablePageRespVO.setInvoiceAmountRespVO(purchaseRecordMapper.getOrgInvoiceAmountStatistics(SecurityFrameworkUtils.getUserOrganId())); + public InvoiceAmountRespVO getInvoiceAmount(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO) { + return purchaseRecordMapper.getOrgInvoiceAmountStatistics(SecurityFrameworkUtils.getUserOrganId()); + } - // 可开票记录查询 - invoiceAmountAndAvailablePageRespVO.setAvailableInvoicePurchaseRecords(purchaseRecordMapper.selectPage(invoiceAmountAndAvailablePageReqVO)); + @Override + public InvoiceAmountRespVO getManageInvoiceAmount(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO) { + return invoiceRecordsMapper.getManageInvoiceAmountStatistics(); + } - return invoiceAmountAndAvailablePageRespVO; + @Override + public PageResult getAvailablePage(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO) { + return purchaseRecordMapper.selectPage(invoiceAmountAndAvailablePageReqVO); } @Override @@ -168,4 +196,118 @@ public class InvoiceServiceImpl implements InvoiceService { List recordsRespVOS = BeanUtils.toBean(resultList, InvoiceRecordsRespVO.class); return new PageResult<>(recordsRespVOS, pageResult.getTotal()); } + + @Override + public InvoiceDetailsRespVO getInvoiceRecordDetail(Long recordId) { + InvoiceRecordsDO invoiceRecordsDO = invoiceRecordsMapper.selectById(recordId); + AssertUtils.notEmpty(invoiceRecordsDO,INVOICE_NO_EXIST); + + // 记录中的购买记录id数组转list + String purchaseIds = Optional.ofNullable(invoiceRecordsDO.getPurchaseIds()).orElse("[]"); + List purchaseIdList = JSON.parseArray(purchaseIds).toJavaList(Long.class).stream().distinct().toList(); + + // 查询关联的购买记录 + List purchaseRecordDOS = purchaseRecordMapper.selectList(new LambdaQueryWrapper() + .eq(PurchaseRecordDO::getOrganId, getUserOrganId()) + .in(PurchaseRecordDO::getId, purchaseIdList)); + + List invoicePurchaseRecords = new ArrayList<>(); + if (CollUtil.isNotEmpty(purchaseRecordDOS)) { + for (PurchaseRecordDO purchaseRecordDO : purchaseRecordDOS) { + InvoicePurchaseRecord invoicePurchaseRecord = new InvoicePurchaseRecord(); + invoicePurchaseRecord.setPurchaseRecordId(purchaseRecordDO.getId()); + invoicePurchaseRecord.setProductName(purchaseRecordDO.getProductName()); + invoicePurchaseRecord.setTradeType(TradeTypeEnum.PRODUCT.getCode()); + invoicePurchaseRecord.setInvoicableAmount(purchaseRecordDO.getTotalAmount().subtract(purchaseRecordDO.getGiftMoneySpent())); + invoicePurchaseRecord.setCreateTime(purchaseRecordDO.getCreateTime()); + invoicePurchaseRecords.add(invoicePurchaseRecord); + } + } + + // 解压发票抬头 + InvoiceTitleInfo invoiceTitleInfo = parseObject(unzipString(invoiceRecordsDO.getInvoiceTitleInfo()), InvoiceTitleInfo.class); + + return InvoiceDetailsRespVO.builder() + .invoicePurchaseRecords(invoicePurchaseRecords) + .invoiceTitleInfo(invoiceTitleInfo) + .applicant(invoiceRecordsDO.getCreator()) + .orgName(invoiceRecordsDO.getOrganName()) + .applyTime(invoiceRecordsDO.getCreateTime()) + .build(); + } + + @Override + public void confirmInvoice(InvoiceConfirmReqVO reqVO, MultipartFile file) throws IOException { + // 校验发票申请记录是否存在 + InvoiceRecordsDO invoiceRecordsDO = validateInvoiceExists(reqVO.getId()); + + if (invoiceRecordsDO.getStatus().equals(InvoiceStatusEnum.INVOICINGFAILED.getStatus()) + || invoiceRecordsDO.getStatus().equals(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getStatus())) { + throw exception(THIS_INVOICE_IS_FAIL); + } + + // 校验发票记录下的购买记录是否存在 + String purchaseIds = Optional.ofNullable(invoiceRecordsDO.getPurchaseIds()).orElse("[]"); + List purchaseIdList = JSON.parseArray(purchaseIds).toJavaList(Long.class).stream().distinct().toList(); + List purchaseRecordDOS = validatePurchaseRecordExists(purchaseIdList); + + if (reqVO.isAgree()) { + // 同意开票 + // 更新发票申请记录状态 + invoiceRecordsDO.setStatus(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getStatus()); + invoiceRecordsDO.setRemark(reqVO.getRemark()); + // 更新购买记录状态 + purchaseRecordDOS.forEach(f -> f.setIsInvocing(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getStatus())); + + // 发票文件入库 + if (ObjectUtil.isNull(file) || file.isEmpty()) { + throw new ServiceException(ORG_INVOICE_AGREE_FILE_NULL_ERROR); + } + String filePath = fileApi.createFile(IoUtil.readBytes(file.getInputStream()), file.getOriginalFilename()); + invoiceRecordsDO.setInvoiceAttachmentPath(filePath); + invoiceRecordsDO.setInvoiceNo(reqVO.getInvoiceNo()); + } else { + // 拒绝开票 + // 更新发票申请记录状态 + invoiceRecordsDO.setStatus(InvoiceStatusEnum.INVOICINGFAILED.getStatus()); + String remark = Optional.ofNullable(reqVO.getRemark()).orElseThrow(() -> new ServiceException(INVOICING_REJECT_REASON)); + invoiceRecordsDO.setRemark(remark); + + // 更新购买记录状态 + purchaseRecordDOS.forEach(f -> f.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getStatus())); + + } + + invoiceRecordsMapper.updateById(invoiceRecordsDO); + + purchaseRecordMapper.updateBatch(purchaseRecordDOS); + } + + /** + * 校验发票申请记录 + * + * @param invoiceId + * @return + */ + private InvoiceRecordsDO validateInvoiceExists(Long invoiceId) { + InvoiceRecordsDO invoiceRecordsDO = invoiceRecordsMapper.selectById(invoiceId); + if (ObjectUtil.isNull(invoiceRecordsDO)) { + throw exception(INVOICE_NO_EXIST); + } + return invoiceRecordsDO; + } + + /** + * 校验发票记录下的购买记录 + * + * @param purchaseId + * @return + */ + private List validatePurchaseRecordExists(List purchaseId) { + List purchaseRecordDOS = purchaseRecordMapper.selectBatchIds(purchaseId); + if (CollUtil.isEmpty(purchaseRecordDOS)) { + throw exception(PURCHASE_RECORD_NO_EXIST); + } + return purchaseRecordDOS; + } } diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/invoice/InvoiceRecordsMapper.xml b/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/invoice/InvoiceRecordsMapper.xml new file mode 100644 index 000000000..2c7feecf7 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/invoice/InvoiceRecordsMapper.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/purchase/PurchaseMapper.xml b/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/purchase/PurchaseMapper.xml index cba3bdc7c..41944092c 100644 --- a/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/purchase/PurchaseMapper.xml +++ b/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/purchase/PurchaseMapper.xml @@ -8,8 +8,7 @@