Commit 4355cf03 by Jony.L

发票功能1.0

parent 5251136f
package com.luhu.computility.framework.common.exception;
import cn.hutool.core.util.StrUtil;
import com.luhu.computility.framework.common.exception.enums.ServiceErrorCodeRange;
import lombok.Data;
import lombok.EqualsAndHashCode;
......@@ -33,6 +34,11 @@ public final class ServiceException extends RuntimeException {
this.message = errorCode.getMsg();
}
public ServiceException(String message, Object... param) {
this.code = 500;
this.message = StrUtil.format(message, param);
}
public ServiceException(Integer code, String message) {
this.code = code;
this.message = message;
......
package com.luhu.computility.module.trade.enums.order;
import com.luhu.computility.framework.common.core.ArrayValuable;
import lombok.Getter;
import java.util.Arrays;
/**
* @Author: jony
* @Date : 2025/9/9 15:15
* @VERSION v1.0
*/
@Getter
public enum TradeOrderInvoiceStatusEnum implements ArrayValuable<Integer> {
UNINVOICE(0,"未开票"),
INVOICING(1,"开票中"),
INVOICED(2,"已开票");
@Override
public Integer[] array() {
// 遍历所有枚举常量,提取 status 组成数组
return Arrays.stream(values()).map(TradeOrderInvoiceStatusEnum::getStatus).toArray(Integer[]::new);
}
TradeOrderInvoiceStatusEnum(Integer status, String description){
this.status = status;
this.description = description;
}
private final Integer status;
private final String description;
}
package com.luhu.computility.module.trade.controller.admin.order;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.luhu.computility.framework.common.exception.ServiceException;
import com.luhu.computility.framework.common.pojo.CommonResult;
import com.luhu.computility.framework.common.pojo.PageResult;
import com.luhu.computility.module.member.api.user.MemberUserApi;
......@@ -34,6 +36,7 @@ import static com.luhu.computility.framework.common.pojo.CommonResult.success;
import static com.luhu.computility.framework.common.util.collection.CollectionUtils.convertList;
import static com.luhu.computility.framework.common.util.collection.CollectionUtils.convertSet;
import static com.luhu.computility.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static com.luhu.computility.module.trade.enums.order.TradeOrderInvoiceStatusEnum.INVOICED;
@Tag(name = "管理后台 - 交易订单")
@RestController
......@@ -55,6 +58,19 @@ public class TradeOrderController {
@Resource
private TradeOrderToResourceService tradeOrderToResourceService;
@PutMapping("/issue-invoice")
@Operation(summary = "开具发票")
public CommonResult<Boolean> issueInvoice(@RequestBody TradeOrderInvoiceSaveVO saveVO){
if(ObjectUtil.isEmpty(saveVO.getInvoiceUrl())){
throw new ServiceException("发票图片出错!");
}
if(saveVO.getInvoiceStatus().equals(INVOICED.getStatus())){
throw new ServiceException("该订单已经开具发票");
}
return success(tradeOrderUpdateService.updateInvoice(saveVO));
}
@GetMapping("/page")
@Operation(summary = "获得交易订单分页")
@PreAuthorize("@ss.hasPermission('trade:order:query')")
......
......@@ -131,6 +131,17 @@ public class TradeOrderBaseVO {
@Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer refundPrice;
// ========== 发票基本信息 ==========
/**
* 发票图片链接
*/
private String invoiceUrl;
/**
* 开票状态(0:未开票 1:已开票)
*/
private Integer invoiceStatus;
// ========== 营销基本信息 ==========
@Schema(description = "优惠劵编号", example = "1024")
......
package com.luhu.computility.module.trade.controller.admin.order.vo;
import lombok.Data;
/**
* @Author: jony
* @Date : 2025/9/9 15:04
* @VERSION v1.0
*/
@Data
public class TradeOrderInvoiceSaveVO {
private Long id;
private String invoiceUrl;
private Integer invoiceStatus;
}
......@@ -64,4 +64,12 @@ public class TradeOrderItemBaseVO {
@Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer afterSaleStatus;
// ========== 发票基本信息 ==========
@Schema(description = "发票链接", example = "https://fapiao")
private String invoiceUrl;
@Schema(description = "开票状态", example = "0")
private Integer invoiceStatus;
}
package com.luhu.computility.module.trade.controller.app.order;
import cn.hutool.core.collection.CollectionUtil;
import com.luhu.computility.framework.common.exception.ServiceException;
import com.luhu.computility.framework.common.pojo.CommonResult;
import com.luhu.computility.framework.common.pojo.PageResult;
import com.luhu.computility.framework.common.util.object.BeanUtils;
......@@ -39,10 +40,13 @@ import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.luhu.computility.framework.common.pojo.CommonResult.success;
import static com.luhu.computility.framework.common.util.collection.CollectionUtils.convertSet;
import static com.luhu.computility.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static com.luhu.computility.module.trade.enums.order.TradeOrderInvoiceStatusEnum.INVOICED;
import static com.luhu.computility.module.trade.enums.order.TradeOrderInvoiceStatusEnum.INVOICING;
@Tag(name = "用户 App - 交易订单")
@RestController
......@@ -66,6 +70,18 @@ public class AppTradeOrderController {
@Resource
private TradeOrderProperties tradeOrderProperties;
@PostMapping("/invoiceRequest")
@Operation(summary = "申请开票")
public CommonResult<Boolean> invoiceRequest(@RequestBody AppTradeOrderInvoiceReqVO reqVO){
Integer invoiceStatus = reqVO.getInvoiceStatus();
if(invoiceStatus.equals(INVOICING.getStatus())){
throw new ServiceException("该订单已申请开票,请耐心等待");
}
if(invoiceStatus.equals(INVOICED.getStatus())){
throw new ServiceException("该订单已开票,请勿重复申请");
}
return success(tradeOrderUpdateService.updateRequestInvoice(reqVO));
}
@GetMapping("/settlement")
@Operation(summary = "获得订单结算信息")
......@@ -159,6 +175,14 @@ public class AppTradeOrderController {
PageResult<AppTradeOrderPageRespVO> targetPageResult = new PageResult<>();
List<AppTradeOrderPageRespVO> appTradeOrders = new ArrayList<>();
Map<Long, AppTradeOrderItemInvoiceInfoRespVO> invoiceCollet = pageResult.getList().stream()
.collect(Collectors.toMap(
TradeOrderDO::getId,
item -> new AppTradeOrderItemInvoiceInfoRespVO(
item.getInvoiceUrl(),
item.getInvoiceStatus()
)
));
if (!CollectionUtil.isEmpty(sourcePageResult.getList())) {
for (AppTradeOrderPageItemRespVO item : sourcePageResult.getList()) {
AppTradeOrderPageRespVO appTradeOrder = new AppTradeOrderPageRespVO();
......@@ -173,6 +197,8 @@ public class AppTradeOrderController {
appTradeOrder.setStatus(item.getStatus());
appTradeOrder.setStatusName(TradeOrderStatusEnum.getNameByStatus(item.getStatus()));
appTradeOrder.setProperties(item.getItems().get(0).getProperties());
appTradeOrder.setInvoiceUrl(invoiceCollet.get(item.getId()).getInvoiceUrl());
appTradeOrder.setInvoiceStatus(invoiceCollet.get(item.getId()).getInvoiceStatus());
appTradeOrders.add(appTradeOrder);
}
}
......
package com.luhu.computility.module.trade.controller.app.order.vo;
import lombok.Data;
/**
* @Author: jony
* @Date : 2025/9/10 09:53
* @VERSION v1.0
*/
@Data
public class AppTradeOrderInvoiceReqVO {
private Long id;
//发票图片链接
private String invoiceUrl;
//开票状态
private Integer invoiceStatus;
}
package com.luhu.computility.module.trade.controller.app.order.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: jony
* @Date : 2025/9/9 09:27
* @VERSION v1.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AppTradeOrderItemInvoiceInfoRespVO {
//发票图片链接
private String invoiceUrl;
//开票状态
private Integer invoiceStatus;
}
......@@ -36,6 +36,12 @@ public class AppTradeOrderPageRespVO {
@Schema(description = "商品类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String categoryName;
@Schema(description = "发票链接", example = "https://fapiao")
private String invoiceUrl;
@Schema(description = "开票状态", example = "0")
private Integer invoiceStatus;
private List<AppProductPropertyValueDetailRespVO> properties;
@Schema(description = "应付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
......
......@@ -127,6 +127,10 @@ public interface TradeOrderConvert {
orderVO.setUser(convertUser(memberUserMap.get(orderVO.getUserId())));
// 增加推广人信息
orderVO.setBrokerageUser(convertUser(memberUserMap.get(orderVO.getBrokerageUserId())));
// 增加发票信息
orderVO.setInvoiceStatus(order.getInvoiceStatus());
orderVO.setInvoiceUrl(order.getInvoiceUrl());
return orderVO;
});
return new PageResult<>(orderVOs, pageResult.getTotal());
......
......@@ -262,6 +262,16 @@ public class TradeOrderDO extends BaseDO {
*/
private Integer refundPrice;
// ========== 发票基本信息 ==========
/**
* 发票图片链接
*/
private String invoiceUrl;
/**
* 开票状态(0:未开票 1:已开票)
*/
private Integer invoiceStatus;
// ========== 营销基本信息 ==========
/**
* 优惠劵编号
......
package com.luhu.computility.module.trade.service.order;
import com.luhu.computility.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
import com.luhu.computility.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
import com.luhu.computility.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
import com.luhu.computility.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO;
import com.luhu.computility.module.trade.controller.admin.order.vo.*;
import com.luhu.computility.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
import com.luhu.computility.module.trade.controller.app.order.vo.AppTradeOrderInvoiceReqVO;
import com.luhu.computility.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
import com.luhu.computility.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
import com.luhu.computility.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
......@@ -149,6 +147,21 @@ public interface TradeOrderUpdateService {
*/
TradeOrderDO getByPickUpVerifyCode(String pickUpVerifyCode);
/**
* 【管理员】开具发票
*
* @param saveVO
* @return
*/
boolean updateInvoice(TradeOrderInvoiceSaveVO saveVO);
/**
* 【会员】 申请开票
*
* @param reqVO
* @return
*/
boolean updateRequestInvoice(AppTradeOrderInvoiceReqVO reqVO);
// =================== Order Item ===================
/**
......
......@@ -11,6 +11,7 @@ import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.luhu.computility.framework.common.enums.UserTypeEnum;
import com.luhu.computility.framework.common.exception.ServiceException;
import com.luhu.computility.framework.common.util.json.JsonUtils;
import com.luhu.computility.framework.common.util.number.MoneyUtils;
import com.luhu.computility.module.member.api.address.MemberAddressApi;
......@@ -31,11 +32,9 @@ import com.luhu.computility.module.product.api.spu.ProductSpuApi;
import com.luhu.computility.module.product.api.spu.dto.ProductSpuRespDTO;
import com.luhu.computility.module.system.api.social.SocialClientApi;
import com.luhu.computility.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO;
import com.luhu.computility.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
import com.luhu.computility.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
import com.luhu.computility.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
import com.luhu.computility.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO;
import com.luhu.computility.module.trade.controller.admin.order.vo.*;
import com.luhu.computility.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
import com.luhu.computility.module.trade.controller.app.order.vo.AppTradeOrderInvoiceReqVO;
import com.luhu.computility.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
import com.luhu.computility.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
import com.luhu.computility.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
......@@ -83,6 +82,10 @@ import static com.luhu.computility.framework.common.util.servlet.ServletUtils.ge
import static com.luhu.computility.framework.web.core.util.WebFrameworkUtils.getTerminal;
import static com.luhu.computility.module.trade.enums.ErrorCodeConstants.*;
import static com.luhu.computility.module.trade.enums.MessageTemplateConstants.WXA_ORDER_DELIVERY;
import static com.luhu.computility.module.trade.enums.order.TradeOrderInvoiceStatusEnum.INVOICED;
import static com.luhu.computility.module.trade.enums.order.TradeOrderInvoiceStatusEnum.INVOICING;
import static com.luhu.computility.module.trade.enums.order.TradeOrderStatusEnum.CANCELED;
import static com.luhu.computility.module.trade.enums.order.TradeOrderStatusEnum.UNPAID;
/**
* 交易订单【写】Service 实现类
......@@ -211,7 +214,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, createReqVO, calculateRespBO);
order.setType(calculateRespBO.getType());
order.setNo(tradeNoRedisDAO.generate(TradeNoRedisDAO.TRADE_ORDER_NO_PREFIX));
order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus());
order.setStatus(UNPAID.getStatus());
order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum));
order.setUserIp(getClientIP()).setTerminal(getTerminal());
......@@ -571,7 +574,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
throw exception(ORDER_NOT_FOUND);
}
// 1.2 校验状态
if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) {
if (ObjectUtil.notEqual(order.getStatus(), UNPAID.getStatus())) {
throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
}
// 1.3 校验是否支持延迟(不允许取消)
......@@ -592,7 +595,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
// 1. 查询过期的待支付订单
LocalDateTime expireTime = minusTime(tradeOrderProperties.getPayExpireTime());
List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndCreateTimeLt(
TradeOrderStatusEnum.UNPAID.getStatus(), expireTime);
UNPAID.getStatus(), expireTime);
if (CollUtil.isEmpty(orders)) {
return 0;
}
......@@ -784,6 +787,29 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
return tradeOrderMapper.selectOneByPickUpVerifyCode(pickUpVerifyCode);
}
@Override
public boolean updateInvoice(TradeOrderInvoiceSaveVO saveVO) {
TradeOrderDO order = tradeOrderMapper.selectById(saveVO.getId());
order.setInvoiceStatus(INVOICED.getStatus());
order.setInvoiceUrl(saveVO.getInvoiceUrl());
tradeOrderMapper.updateById(order);
return true;
}
@Override
public boolean updateRequestInvoice(AppTradeOrderInvoiceReqVO reqVO) {
TradeOrderDO tradeOrderDO = tradeOrderMapper.selectById(reqVO.getId());
Integer status = tradeOrderDO.getStatus();//订单状态
if(status.equals(UNPAID.getStatus())){
throw new ServiceException("未支付的订单不能申请开票");
} else if (status.equals(CANCELED.getStatus())) {
throw new ServiceException("已取消的订单不能申请开票!");
}
tradeOrderDO.setInvoiceStatus(INVOICING.getStatus());
tradeOrderMapper.updateById(tradeOrderDO);
return true;
}
@Transactional(rollbackFor = Exception.class)
public void pickUpOrder(Long userId, TradeOrderDO order) {
if (order == null) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment