Bläddra i källkod

Merge branch 'user_invoice'

zoujiajian 1 år sedan
förälder
incheckning
e6ef8a9006

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UserInvoiceApplyRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserInvoiceApplyRecord;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceApplyRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/12/12 17:24
+ */
+public interface UserInvoiceApplyRecordMapper extends BaseMapper<UserInvoiceApplyRecord> {
+}

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UserInvoiceOrderRelateMapper.java

@@ -0,0 +1,17 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserInvoiceOrderRelate;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceOrderRelateMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/12/12 17:24
+ */
+public interface UserInvoiceOrderRelateMapper extends BaseMapper<UserInvoiceOrderRelate> {
+	void batchInsert(@Param("recordId") Long recordId, @Param("userId") Long userId, @Param("orderIds") List<Long> orderIds);
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/ShopConfig.java

@@ -69,4 +69,9 @@ public class ShopConfig extends BaseEntity{
      * 是否需要携带证书
      */
     private Boolean isCert;
+
+    /**
+     * 支付主体
+     */
+    private String payment;
 }

+ 58 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserInvoiceApplyRecord.java

@@ -0,0 +1,58 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceApplyRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/12/12 17:21
+ */
+@Getter
+@Setter
+public class UserInvoiceApplyRecord extends BaseEntity{
+
+	private Long userId;
+
+	private BigDecimal money;
+
+	/**
+	 * 支付宝支付主体
+	 */
+	private String zfbPayment;
+
+	/**
+	 * 发票头部信息
+	 */
+	private String head;
+
+	/**
+	 * 税号
+	 */
+	private String taxNo;
+
+	/**
+	 * 银行
+	 */
+	private String bank;
+
+	/**
+	 * 银行账号
+	 */
+	private String bankNo;
+
+	private String email;
+
+	/**
+	 * 发票
+	 */
+	private String invoiceImg;
+
+	/**
+	 * 0待开票 1已上传 2已发送
+	 */
+	private Integer status;
+}

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserInvoiceOrderRelate.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceOrderRelate
+ * 创建者: JavaZou
+ * 创建时间:2024/12/12 17:23
+ */
+@Getter
+@Setter
+public class UserInvoiceOrderRelate extends BaseEntity{
+
+	private Long userId;
+
+	/**
+	 * 用户发票记录id
+	 */
+	private Long recordId;
+
+	/**
+	 * 订单id
+	 */
+	private Long orderId;
+}

+ 42 - 0
netflix-dao/src/main/java/com/cyksj/model/request/UserInvoiceOrderReq.java

@@ -0,0 +1,42 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceOrderReq
+ * 创建者: JavaZou
+ * 创建时间:2024/12/13 16:48
+ */
+@Getter
+@Setter
+public class UserInvoiceOrderReq {
+	private List<Long> orderIds;
+
+	private Long userId;
+
+	/**
+	 * 发票头部信息
+	 */
+	private String head;
+
+	/**
+	 * 税号
+	 */
+	private String taxNo;
+
+	/**
+	 * 银行
+	 */
+	private String bank;
+
+	/**
+	 * 银行账号
+	 */
+	private String bankNo;
+
+	private String email;
+}

+ 86 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserInvoiceApplyRecordView.java

@@ -0,0 +1,86 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceApplyRecordView
+ * 创建者: JavaZou
+ * 创建时间:2024/12/13 15:45
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user_invoice_apply_record uar inner join user_invoice_order_relate uor on uor.record_id = uar.id" +
+		" inner join order_don o on o.id = uor.order_id"
+		, groupBy = "uar.id,uar.user_id,uar.money,uar.zfb_payment,uar.head,uar.tax_no,uar.bank,uar.bank_no,uar.email,uar.status,uar.invoice_img,uar.created_time,uar.update_time")
+public class UserInvoiceApplyRecordView {
+
+	@DbField("uar.id")
+	private Long id;
+
+	@DbField("uar.user_id")
+	private Long userId;
+
+	@DbField("uar.money")
+	private BigDecimal money;
+
+	/**
+	 * 支付宝支付主体
+	 */
+	@DbField("uar.zfb_payment")
+	private String zfbPayment;
+
+	/**
+	 * 发票头部信息
+	 */
+	@DbField("uar.head")
+	private String head;
+
+	/**
+	 * 税号
+	 */
+	@DbField("uar.tax_no")
+	private String taxNo;
+
+	/**
+	 * 银行
+	 */
+	@DbField("uar.bank")
+	private String bank;
+
+	/**
+	 * 银行
+	 */
+	@DbField("uar.bank_no")
+	private String bankNo;
+
+	@DbField("uar.email")
+	private String email;
+
+	/**
+	 * 0待开票 1已上传 2已发送
+	 */
+	@DbField("uar.status")
+	private Integer status;
+
+	/**
+	 * 发票
+	 */
+	@DbField("uar.invoice_img")
+	private String invoiceImg;
+
+	@DbField("group_concat(o.order_no)")
+	private String orderNoStr;
+
+	@DbField("uar.created_time")
+	private Date createdTime;
+
+	@DbField("uar.update_time")
+	private Date updateTime;
+}

+ 53 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserInvoiceChoseOrderViews.java

@@ -0,0 +1,53 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceChosseOrderViews
+ * 创建者: JavaZou
+ * 创建时间:2024/12/13 16:24
+ */
+@Getter
+@Setter
+@SearchBean(tables = " order_don o left join user_invoice_order_relate uor on uor.order_id = o.id" +
+		" inner join goods_don g on g.id = o.goods_id" +
+		" inner join goods_don_sku sku on sku.id = o.sku_id and sku.is_mirror is true" +
+		" inner join shop_config sc on sc.app_id = o.shop_id",
+		where = "o.money > 0 and uor.id is null and o.status not in ('close','noPayment','refund')",
+		orderBy = "o.id desc")
+public class UserInvoiceChoseOrderViews {
+
+	@DbField("o.id")
+	private Long orderId;
+
+	@DbField("o.order_no")
+	private String orderNo;
+
+	@DbField("o.money")
+	private BigDecimal money;
+
+	@DbField("o.user_id")
+	private Long userId;
+
+	@DbField("g.logo")
+	private String logo;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("sc.payment")
+	private String zfbPayment;
+
+	@DbField("o.pay_time")
+	private Date payTime;
+}

+ 88 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserInvoiceFrontView.java

@@ -0,0 +1,88 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceFrontView
+ * 创建者: JavaZou
+ * 创建时间:2024/12/13 17:13
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user_invoice_apply_record uar")
+public class UserInvoiceFrontView {
+
+	@DbField("uar.id")
+	private Long id;
+
+	@DbField("uar.user_id")
+	@JsonIgnore
+	private Long userId;
+
+	@DbField("uar.money")
+	private BigDecimal money;
+
+	/**
+	 * 支付宝支付主体
+	 */
+	@DbField("uar.zfb_payment")
+	private String zfbPayment;
+
+	/**
+	 * 发票头部信息
+	 */
+	@DbField("uar.head")
+	private String head;
+
+	/**
+	 * 税号
+	 */
+	@DbField("uar.tax_no")
+	private String taxNo;
+
+	/**
+	 * 银行
+	 */
+	@DbField("uar.bank")
+	private String bank;
+
+	/**
+	 * 银行卡号
+	 */
+	@DbField("uar.bank_no")
+	private String bankNo;
+
+	@DbField("uar.email")
+	private String email;
+
+	/**
+	 * 0待开票 1已上传 2已发送
+	 */
+	@DbField("uar.status")
+	private Integer status;
+
+	/**
+	 * 发票
+	 */
+	@DbField("uar.invoice_img")
+	private String invoiceImg;
+
+	@DbField("uar.created_time")
+	private Date createdTime;
+
+	@DbField("uar.update_time")
+	private Date updateTime;
+
+	@DbIgnore
+	private List<UserInvoiceOrderViews> orderViews;
+}

+ 44 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserInvoiceOrderViews.java

@@ -0,0 +1,44 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceOrderViews
+ * 创建者: JavaZou
+ * 创建时间:2024/12/13 17:23
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user_invoice_order_relate uor inner join order_don o on o.id = uor.order_id" +
+		" inner join goods_don g on g.id = o.goods_id" +
+		" inner join goods_don_sku sku on sku.id = o.sku_id")
+public class UserInvoiceOrderViews {
+
+	@DbField("uor.record_id")
+	private Long recordId;
+
+	@DbField("o.order_no")
+	private String orderNo;
+
+	@DbField("o.money")
+	private BigDecimal money;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("g.logo")
+	private String logo;
+
+	@DbField("o.pay_time")
+	private Date payTime;
+}

+ 14 - 0
netflix-dao/src/main/resources/mapper/UserInvoiceOrderRelateMapper.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.UserInvoiceOrderRelateMapper">
+
+
+    <insert id="batchInsert">
+        insert into user_invoice_order_relate(`user_id`,`record_id`,`order_id`,`created_time`,`update_time`) values
+        <foreach collection="orderIds" item="orderId" separator=",">
+            (#{userId},#{recordId},#{orderId},now(),now())
+        </foreach>
+    </insert>
+
+</mapper>

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/invoice/UserInvoiceApplyRecordService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.invoice;
+
+import com.cyksj.model.request.UserInvoiceOrderReq;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceService
+ * 创建者: JavaZou
+ * 创建时间:2024/12/13 15:26
+ */
+public interface UserInvoiceApplyRecordService {
+	Long applyOrderInvoice(UserInvoiceOrderReq req);
+}

+ 120 - 0
netflix-service/src/main/java/com/cyksj/service/invoice/impl/UserInvoiceApplyRecordServiceImpl.java

@@ -0,0 +1,120 @@
+package com.cyksj.service.invoice.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.mapper.UserInvoiceApplyRecordMapper;
+import com.cyksj.mapper.UserInvoiceOrderRelateMapper;
+import com.cyksj.mapper.channel.ShopConfigMapper;
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.ShopConfig;
+import com.cyksj.model.entity.UserInvoiceApplyRecord;
+import com.cyksj.model.entity.UserInvoiceOrderRelate;
+import com.cyksj.model.request.UserInvoiceOrderReq;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.invoice.UserInvoiceApplyRecordService;
+import com.cyksj.service.user.UserBindRelationService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/12/13 15:28
+ */
+@Service
+@RequiredArgsConstructor
+public class UserInvoiceApplyRecordServiceImpl implements UserInvoiceApplyRecordService {
+	private final UserInvoiceApplyRecordMapper userInvoiceApplyRecordMapper;
+
+	private final UserInvoiceOrderRelateMapper userInvoiceOrderRelateMapper;
+
+	private final OrderDonMapper orderDonMapper;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final ShopConfigMapper shopConfigMapper;
+
+	private final RedisService redisService;
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public Long applyOrderInvoice(UserInvoiceOrderReq req) {
+		Long userId = req.getUserId();
+		String key = "invoice:key:" + userId;
+		try {
+			List<Long> orderIds = req.getOrderIds();
+			if (CollUtil.isEmpty(orderIds)) {
+				throw BusinessRuntimeException.getInstance("请选择对应订单");
+			}
+			String head = req.getHead();
+			String taxNo = req.getTaxNo();
+			String email = req.getEmail();
+			String bank = req.getBank();
+			String bankNo = req.getBankNo();
+			if (StrUtil.hasEmpty(head, taxNo, email)) {
+				throw BusinessRuntimeException.getInstance("请完成必填项");
+			}
+			if (!redisService.setNx(key, userId, 30l)) {
+				throw BusinessRuntimeException.getInstance("正在提交中,请勿重复提交");
+			}
+			List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+			//订单里是否存在开过发票
+			Integer selectCount = userInvoiceOrderRelateMapper.selectCount(Wrappers.lambdaQuery(UserInvoiceOrderRelate.class)
+					.in(UserInvoiceOrderRelate::getOrderId, orderIds));
+			if (selectCount > 0) {
+				throw BusinessRuntimeException.getInstance("您选择的订单存在开过发票,请刷新页面重新选择");
+			}
+			//是否是自己订单
+			List<OrderDon> orderDonList = orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class)
+					.in(OrderDon::getId, orderIds)
+					.in(OrderDon::getUserId, userIdList)
+					.select(OrderDon::getId, OrderDon::getMoney, OrderDon::getShopId));
+			if (orderDonList.size() != orderIds.size()) {
+				throw BusinessRuntimeException.getInstance("订单选择错误,请刷新页面重新选择");
+			}
+			Set<String> shopIdSet = new HashSet<>();
+			BigDecimal money = BigDecimal.ZERO;
+			for (OrderDon orderDon : orderDonList) {
+				shopIdSet.add(orderDon.getShopId());
+				money = money.add(orderDon.getMoney());
+			}
+			//是否是统一主体
+			if (shopIdSet.size() > 1) {
+				throw BusinessRuntimeException.getInstance("所选订单的支付主体不一致,请重新选择)");
+			}
+			UserInvoiceApplyRecord invoiceApplyRecord = new UserInvoiceApplyRecord();
+			invoiceApplyRecord.setHead(head);
+			invoiceApplyRecord.setTaxNo(taxNo);
+			invoiceApplyRecord.setUserId(userId);
+			invoiceApplyRecord.setBank(bank);
+			invoiceApplyRecord.setBankNo(bankNo);
+			ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class)
+					.in(ShopConfig::getAppId, shopIdSet)
+					.last("limit 1"));
+			if (shopConfig == null) {
+				throw BusinessRuntimeException.getInstance("申请发票错误,请联系客服处理");
+			}
+			invoiceApplyRecord.setZfbPayment(shopConfig.getPayment());
+			invoiceApplyRecord.setMoney(money);
+			invoiceApplyRecord.setEmail(email);
+			userInvoiceApplyRecordMapper.insert(invoiceApplyRecord);
+
+			//关联记录id
+			Long recordId = invoiceApplyRecord.getId();
+			userInvoiceOrderRelateMapper.batchInsert(recordId, userId, orderIds);
+			return invoiceApplyRecord.getId();
+		} finally {
+			redisService.del(key);
+		}
+	}
+}

+ 80 - 0
netflix-web/src/main/java/com/cyksj/web/controller/invoice/UserInvoiceFrontController.java

@@ -0,0 +1,80 @@
+package com.cyksj.web.controller.invoice;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.request.UserInvoiceOrderReq;
+import com.cyksj.model.views.UserInvoiceChoseOrderViews;
+import com.cyksj.model.views.UserInvoiceFrontView;
+import com.cyksj.model.views.UserInvoiceOrderViews;
+import com.cyksj.service.invoice.UserInvoiceApplyRecordService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.cyksj.web.util.StpUserUtil;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceFrontController
+ * 创建者: JavaZou
+ * 创建时间:2024/12/13 16:22
+ */
+@RestController
+@RequestMapping("/applets/invoice")
+@RequiredArgsConstructor
+public class UserInvoiceFrontController {
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final UserInvoiceApplyRecordService userInvoiceApplyRecordService;
+
+	private final UserBindRelationService userBindRelationService;
+
+	/**
+	 * 发票 用户可选AI车票订单
+	 */
+	@GetMapping("/get/orders")
+	public Result<SearchResult<UserInvoiceChoseOrderViews>> getOrders() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		SearchResult<UserInvoiceChoseOrderViews> search = beanSearcher.search(UserInvoiceChoseOrderViews.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(UserInvoiceChoseOrderViews::getUserId, userIdList).op(Operator.InList)
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 提交发票申请
+	 */
+	@PostMapping("/apply")
+	public Result<Long> apply(@RequestBody UserInvoiceOrderReq req) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		req.setUserId(userId);
+		Long recordId = userInvoiceApplyRecordService.applyOrderInvoice(req);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(recordId);
+	}
+
+	/**
+	 * 用户发票申请列表
+	 */
+	@GetMapping("/get")
+	public Result<SearchResult<UserInvoiceFrontView>> get() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		SearchResult<UserInvoiceFrontView> search = beanSearcher.search(UserInvoiceFrontView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(UserInvoiceFrontView::getUserId, userIdList).op(Operator.InList)
+				.orderBy(UserInvoiceFrontView::getId).desc()
+				.build());
+		search.getDataList().forEach(data->{
+			data.setOrderViews(beanSearcher.searchAll(UserInvoiceOrderViews.class, MapUtils.builder().field(UserInvoiceOrderViews::getRecordId, data.getId()).build()));
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+}

+ 59 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/invoice/UserInvoiceController.java

@@ -0,0 +1,59 @@
+package com.cyksj.web.controller.manage.invoice;
+
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.UserInvoiceApplyRecordMapper;
+import com.cyksj.model.entity.UserInvoiceApplyRecord;
+import com.cyksj.model.views.UserInvoiceApplyRecordView;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * admin/发票管理
+ * 项目名: yhlxj
+ * 文件名: UserInvoiceController
+ * 创建者: JavaZou
+ * 创建时间:2024/12/13 15:43
+ */
+@RestController
+@RequestMapping("/manage/invoice")
+@RequiredArgsConstructor
+public class UserInvoiceController {
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final UserInvoiceApplyRecordMapper userInvoiceApplyRecordMapper;
+
+	/**
+	 * 用户发票申请记录
+	 */
+	@GetMapping("/get")
+	public Result<SearchResult<UserInvoiceApplyRecordView>> get() {
+		SearchResult<UserInvoiceApplyRecordView> search = beanSearcher.search(UserInvoiceApplyRecordView.class, MapUtils.flatBuilder(request.getParameterMap()).orderBy(UserInvoiceApplyRecordView::getUpdateTime).desc().build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 配置发票
+	 */
+	@PutMapping("/set/invoiceImg")
+	public Result<String> setInvoiceImg(@RequestBody UserInvoiceApplyRecord userInvoiceApplyRecord) {
+		String invoiceImg = userInvoiceApplyRecord.getInvoiceImg();
+		Long id = userInvoiceApplyRecord.getId();
+		UserInvoiceApplyRecord invoiceApplyRecord = userInvoiceApplyRecordMapper.selectById(id);
+		if (invoiceApplyRecord.getStatus() == 2) {
+			throw BusinessRuntimeException.getInstance("发票已发送");
+		}
+		invoiceApplyRecord.setStatus(1);
+		invoiceApplyRecord.setInvoiceImg(invoiceImg);
+		userInvoiceApplyRecordMapper.updateById(invoiceApplyRecord);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+}