mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-12 21:02:08 +08:00
1、移除无用post岗位代码;2、发票管理单元测试完善,优惠活动单测覆盖率异常修复;
This commit is contained in:
+2
@@ -21,4 +21,6 @@ public @interface WithMockLoginUser {
|
||||
long deptId() default 0L;
|
||||
|
||||
boolean isSuperAdmin() default false;
|
||||
|
||||
long organId() default 0L;
|
||||
}
|
||||
+6
-2
@@ -2,6 +2,7 @@ package com.cf.imes.framework.security.test;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.cf.imes.framework.security.core.LoginUser;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -23,10 +24,13 @@ public class WithMockLoginUserSecurityContextFactory implements WithSecurityCont
|
||||
|
||||
LoginUser loginUser = new LoginUser();
|
||||
long annotationUserId = annotation.userId();
|
||||
long annotationOrganId = annotation.organId();
|
||||
String username = annotation.username();
|
||||
|
||||
loginUser.setId(annotationUserId == 0L ? RandomUtil.randomLong() : annotationUserId);
|
||||
loginUser.setNickname(RandomUtil.randomString(10));
|
||||
loginUser.setNickname(StringUtils.isNotEmpty(username) ? username : RandomUtil.randomString(10));
|
||||
loginUser.setDeptId(RandomUtil.randomLong());
|
||||
loginUser.setOrganId(RandomUtil.randomLong());
|
||||
loginUser.setOrganId(annotationOrganId == 0L ? RandomUtil.randomLong() : annotationOrganId);
|
||||
loginUser.setIsSupAdmin(annotation.isSuperAdmin());
|
||||
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
|
||||
|
||||
+4
-3
@@ -28,6 +28,8 @@ import java.util.stream.Stream;
|
||||
* @author 晨丰科技
|
||||
*/
|
||||
public class RandomUtils {
|
||||
private RandomUtils() {
|
||||
}
|
||||
|
||||
private static final int RANDOM_STRING_LENGTH = 10;
|
||||
|
||||
@@ -51,7 +53,7 @@ public class RandomUtils {
|
||||
}
|
||||
// 如果是 type、status 结尾的字段,返回 tinyint 范围
|
||||
if (CharSequenceUtil.endWithAnyIgnoreCase(attributeMetadata.getAttributeName(),
|
||||
"type", "status", "category", "scope", "result", "sort", "unit")) {
|
||||
"type", "status", "category", "scope", "result", "sort", "unit", "currency")) {
|
||||
return RandomUtil.randomInt(0, TINYINT_MAX + 1);
|
||||
}
|
||||
return RandomUtil.randomInt();
|
||||
@@ -142,8 +144,7 @@ public class RandomUtils {
|
||||
@SafeVarargs
|
||||
public static <T> List<T> randomPojoList(Class<T> clazz, Consumer<T>... consumers) {
|
||||
int size = RandomUtil.randomInt(1, RANDOM_COLLECTION_LENGTH);
|
||||
return Stream.iterate(0, i -> i).limit(size).map(o -> randomPojo(clazz, consumers))
|
||||
.collect(Collectors.toList());
|
||||
return Stream.iterate(0, i -> i).limit(size).map(o -> randomPojo(clazz, consumers)).toList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ public class UserProfileController {
|
||||
DeptDO dept = user.getDeptId() != null ? deptService.getDept(user.getDeptId()) : null;
|
||||
// 获得社交用户信息
|
||||
List<SocialUserDO> socialUsers = socialService.getSocialUserList(user.getId(), UserTypeEnum.ADMIN.getValue());
|
||||
return success(UserConvert.INSTANCE.convert(user, userRoles, dept, null, socialUsers));
|
||||
return success(UserConvert.INSTANCE.convert(user, userRoles, dept, socialUsers));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
|
||||
+1
-3
@@ -10,7 +10,6 @@ import com.cf.imes.module.system.controller.admin.user.vo.user.UserExportRespVO;
|
||||
import com.cf.imes.module.system.controller.admin.user.vo.user.UserRespVO;
|
||||
import com.cf.imes.module.system.controller.admin.user.vo.user.UserSimpleRespVO;
|
||||
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.dept.PostDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.permission.RoleDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.social.SocialUserDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
||||
@@ -59,11 +58,10 @@ public interface UserConvert {
|
||||
}
|
||||
|
||||
default UserProfileRespVO convert(AdminUserDO user, List<RoleDO> userRoles,
|
||||
DeptDO dept, List<PostDO> posts, List<SocialUserDO> socialUsers) {
|
||||
DeptDO dept, List<SocialUserDO> socialUsers) {
|
||||
UserProfileRespVO userVO = BeanUtils.toBean(user, UserProfileRespVO.class);
|
||||
userVO.setRoles(BeanUtils.toBean(userRoles, RoleSimpleRespVO.class));
|
||||
userVO.setDept(BeanUtils.toBean(dept, DeptSimpleRespVO.class));
|
||||
// userVO.setPosts(BeanUtils.toBean(posts, PostSimpleRespVO.class));
|
||||
userVO.setSocialUsers(BeanUtils.toBean(socialUsers, UserProfileRespVO.SocialUser.class));
|
||||
return userVO;
|
||||
}
|
||||
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
package com.cf.imes.module.system.dal.dataobject.dept;
|
||||
|
||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.cf.imes.framework.organ.core.db.OrganBaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 岗位表
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_post")
|
||||
@KeySequence("system_post_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PostDO extends OrganBaseDO {
|
||||
|
||||
/**
|
||||
* 岗位序号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 岗位名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 岗位编码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 岗位排序
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
package com.cf.imes.module.system.dal.dataobject.dept;
|
||||
|
||||
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 用户和岗位关联
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_user_post")
|
||||
@KeySequence("system_user_post_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserPostDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 自增主键
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 用户 ID
|
||||
*
|
||||
* 关联 {@link AdminUserDO#getId()}
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 角色 ID
|
||||
*
|
||||
* 关联 {@link PostDO#getId()}
|
||||
*/
|
||||
private Long postId;
|
||||
|
||||
}
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
package com.cf.imes.module.system.dal.mysql.dept;
|
||||
|
||||
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.framework.organ.core.context.OrganContextHolder;
|
||||
import com.cf.imes.framework.security.core.LoginUser;
|
||||
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostPageReqVO;
|
||||
import com.cf.imes.module.system.dal.dataobject.dept.PostDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Mapper
|
||||
public interface PostMapper extends BaseMapperX<PostDO> {
|
||||
|
||||
default List<PostDO> selectList(Collection<Long> ids, Collection<Integer> statuses, Long organId) {
|
||||
return selectList(new LambdaQueryWrapperX<PostDO>()
|
||||
.eqIfPresent(PostDO::getOrganId, organId)
|
||||
.inIfPresent(PostDO::getId, ids)
|
||||
.inIfPresent(PostDO::getStatus, statuses));
|
||||
}
|
||||
|
||||
default PageResult<PostDO> selectPage(PostPageReqVO reqVO) {
|
||||
LambdaQueryWrapperX<PostDO> lambdaQueryWrapperX = new LambdaQueryWrapperX<>();
|
||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||
assert loginUser != null;
|
||||
Boolean isSupAdmin = loginUser.getIsSupAdmin();
|
||||
if(isSupAdmin && !Objects.isNull(reqVO.getOrganId())) {
|
||||
lambdaQueryWrapperX.eqIfPresent(PostDO::getOrganId, reqVO.getOrganId());
|
||||
}else{
|
||||
lambdaQueryWrapperX.eqIfPresent(PostDO::getOrganId, loginUser.getOrganId());
|
||||
}
|
||||
|
||||
lambdaQueryWrapperX.likeIfPresent(PostDO::getCode, reqVO.getCode())
|
||||
.likeIfPresent(PostDO::getName, reqVO.getName())
|
||||
.eqIfPresent(PostDO::getStatus, reqVO.getStatus());
|
||||
|
||||
|
||||
if (reqVO.getOrder() == null) {
|
||||
lambdaQueryWrapperX.orderByDesc(PostDO::getSort);
|
||||
} else {
|
||||
if (reqVO.getOrder().equals("ascend")) {
|
||||
switch (reqVO.getField()) {
|
||||
case "name" -> lambdaQueryWrapperX.orderByAsc(PostDO::getName);
|
||||
case "code" -> lambdaQueryWrapperX.orderByAsc(PostDO::getCode);
|
||||
case "sort" -> lambdaQueryWrapperX.orderByAsc(PostDO::getSort);
|
||||
case "status" -> lambdaQueryWrapperX.orderByAsc(PostDO::getStatus);
|
||||
case "create_time" -> lambdaQueryWrapperX.orderByAsc(PostDO::getCreateTime);
|
||||
default -> {
|
||||
// default不排序
|
||||
}
|
||||
}
|
||||
} else if (reqVO.getOrder().equals("descend")) {
|
||||
switch (reqVO.getField()) {
|
||||
case "name" -> lambdaQueryWrapperX.orderByDesc(PostDO::getName);
|
||||
case "code" -> lambdaQueryWrapperX.orderByDesc(PostDO::getCode);
|
||||
case "sort" -> lambdaQueryWrapperX.orderByDesc(PostDO::getSort);
|
||||
case "status" -> lambdaQueryWrapperX.orderByDesc(PostDO::getStatus);
|
||||
case "create_time" -> lambdaQueryWrapperX.orderByDesc(PostDO::getCreateTime);
|
||||
default -> {
|
||||
// default不排序
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selectPage(reqVO, lambdaQueryWrapperX);
|
||||
}
|
||||
|
||||
default PostDO selectByName(String name) {
|
||||
return selectOne(PostDO::getName, name, PostDO::getOrganId, OrganContextHolder.getOrganId());
|
||||
}
|
||||
|
||||
default PostDO selectByCode(String code) {
|
||||
return selectOne(PostDO::getCode, code, PostDO::getOrganId, OrganContextHolder.getOrganId());
|
||||
}
|
||||
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
package com.cf.imes.module.system.dal.mysql.dept;
|
||||
|
||||
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.cf.imes.module.system.dal.dataobject.dept.UserPostDO;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface UserPostMapper extends BaseMapperX<UserPostDO> {
|
||||
|
||||
default List<UserPostDO> selectListByUserId(Long userId) {
|
||||
return selectList(UserPostDO::getUserId, userId);
|
||||
}
|
||||
|
||||
default void deleteByUserIdAndPostId(Long userId, Collection<Long> postIds) {
|
||||
delete(new LambdaQueryWrapperX<UserPostDO>()
|
||||
.eq(UserPostDO::getUserId, userId)
|
||||
.in(UserPostDO::getPostId, postIds));
|
||||
}
|
||||
|
||||
default List<UserPostDO> selectListByPostIds(Collection<Long> postIds) {
|
||||
return selectList(UserPostDO::getPostId, postIds);
|
||||
}
|
||||
|
||||
default void deleteByUserId(Long userId) {
|
||||
delete(Wrappers.lambdaUpdate(UserPostDO.class).eq(UserPostDO::getUserId, userId));
|
||||
}
|
||||
}
|
||||
-4
@@ -2,7 +2,6 @@ package com.cf.imes.module.system.service.funds.incomeandexpense;
|
||||
|
||||
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
|
||||
import com.cf.imes.module.system.dal.mysql.incomeandexpense.IncomeExpenseDetailsMapper;
|
||||
import com.cf.imes.module.system.service.organ.OrganService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -17,9 +16,6 @@ public class IncomeExpenseServiceImpl implements IncomeExpenseService {
|
||||
@Resource
|
||||
private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper;
|
||||
|
||||
@Resource
|
||||
private OrganService organService;
|
||||
|
||||
@Override
|
||||
public Long createDetail(IncomeExpenseDetailsDO incomeExpenseDetailsDO) {
|
||||
incomeExpenseDetailsMapper.insert(incomeExpenseDetailsDO);
|
||||
|
||||
+12
-14
@@ -7,7 +7,6 @@ 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.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
@@ -220,11 +219,12 @@ public class InvoiceServiceImpl implements InvoiceService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void applyInvoice(InvoiceRecordsReqVO reqVO) {
|
||||
Long organId = SecurityFrameworkUtils.getUserOrganId();
|
||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
throw new ServiceException(GlobalErrorCodeConstants.UNAUTHORIZED);
|
||||
}
|
||||
Long organId = loginUser.getOrganId();
|
||||
|
||||
List<Long> purchaseRecordId = reqVO.getPurchaseRecordId();
|
||||
// 查询发票抬头
|
||||
InvoiceTitleInfoDO invoiceTitleInfoDO = invoiceTitleInfoMapper.selectOne(new LambdaQueryWrapper<InvoiceTitleInfoDO>()
|
||||
@@ -240,7 +240,7 @@ public class InvoiceServiceImpl implements InvoiceService {
|
||||
// 查询可开票金额:余额支付+扫码支付
|
||||
BigDecimal invoicableAmount = purchaseRecordMapper.getInvoicableAmount(organId, purchaseRecordId);
|
||||
// 可开票金额不能为0
|
||||
AssertUtils.isTrue(ObjectUtils.isNull(invoicableAmount) || invoicableAmount.compareTo(BigDecimal.ZERO) == 0, INVOICE_AMOUNT_ZERO_ERROR);
|
||||
AssertUtils.isTrue(invoicableAmount.compareTo(BigDecimal.ZERO) == 0, INVOICE_AMOUNT_ZERO_ERROR);
|
||||
|
||||
// 更新购买记录表的发票状态
|
||||
int update = purchaseRecordMapper.update(new LambdaUpdateWrapper<PurchaseRecordDO>()
|
||||
@@ -300,17 +300,15 @@ public class InvoiceServiceImpl implements InvoiceService {
|
||||
.in(PurchaseRecordDO::getId, purchaseIdList));
|
||||
|
||||
List<InvoicePurchaseRecord> 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());
|
||||
invoicePurchaseRecord.setTotalAmount(purchaseRecordDO.getTotalAmount());
|
||||
invoicePurchaseRecord.setCreateTime(purchaseRecordDO.getCreateTime());
|
||||
invoicePurchaseRecords.add(invoicePurchaseRecord);
|
||||
}
|
||||
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());
|
||||
invoicePurchaseRecord.setTotalAmount(purchaseRecordDO.getTotalAmount());
|
||||
invoicePurchaseRecord.setCreateTime(purchaseRecordDO.getCreateTime());
|
||||
invoicePurchaseRecords.add(invoicePurchaseRecord);
|
||||
}
|
||||
|
||||
// 解压发票抬头
|
||||
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
package com.cf.imes.module.system.controller.admin.funds.invoice;
|
||||
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
import com.cf.imes.framework.test.core.ut.BaseWebUnitTest;
|
||||
import com.cf.imes.module.system.controller.admin.funds.invoice.vo.*;
|
||||
import com.cf.imes.module.system.enums.pay.InvoiceIssueTypeEnum;
|
||||
import com.cf.imes.module.system.enums.pay.InvoiceTypeEnum;
|
||||
import com.cf.imes.module.system.service.funds.invoice.InvoiceService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* @author 发票管理 Controller 测试类
|
||||
*/
|
||||
@WebMvcTest(controllers = InvoiceController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
|
||||
class InvoiceControllerTest extends BaseWebUnitTest {
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockitoBean
|
||||
private InvoiceService invoiceService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Test
|
||||
void testGetOrgInvoiceTitle() throws Exception {
|
||||
InvoiceTitleInfo respVO = new InvoiceTitleInfo();
|
||||
respVO.setId(1L);
|
||||
respVO.setInvoiceTitle("测试公司");
|
||||
|
||||
when(invoiceService.getInvoiceTitle()).thenReturn(respVO);
|
||||
|
||||
mockMvc.perform(get("/system/invoice/title"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data.id").value(1L))
|
||||
.andExpect(jsonPath("$.data.invoiceTitle").value("测试公司"));
|
||||
|
||||
verify(invoiceService).getInvoiceTitle();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInsetInvoiceTitle() throws Exception {
|
||||
InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO();
|
||||
reqVO.setInvoiceTitle("测试公司");
|
||||
reqVO.setIssueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue());
|
||||
reqVO.setInvoiceType(InvoiceTypeEnum.VAT_GENERAL.getValue());
|
||||
reqVO.setEmail("test@test.com");
|
||||
|
||||
doNothing().when(invoiceService).insetInvoiceTitle(any());
|
||||
|
||||
mockMvc.perform(post("/system/invoice/title")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(reqVO)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data").value(true));
|
||||
|
||||
verify(invoiceService).insetInvoiceTitle(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetInvoiceAmount() throws Exception {
|
||||
InvoiceAmountRespVO respVO = new InvoiceAmountRespVO();
|
||||
respVO.setInvocable(new BigDecimal("100.00"));
|
||||
respVO.setPendingInvoice(new BigDecimal("50.00"));
|
||||
respVO.setInTheInvoice(new BigDecimal("30.00"));
|
||||
respVO.setInvoiced(new BigDecimal("200.00"));
|
||||
|
||||
when(invoiceService.getInvoiceAmount()).thenReturn(respVO);
|
||||
|
||||
mockMvc.perform(get("/system/invoice/org/amount"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data.invocable").value(100.00))
|
||||
.andExpect(jsonPath("$.data.pendingInvoice").value(50.00))
|
||||
.andExpect(jsonPath("$.data.inTheInvoice").value(30.00))
|
||||
.andExpect(jsonPath("$.data.invoiced").value(200.00));
|
||||
|
||||
verify(invoiceService).getInvoiceAmount();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetManageEndPointInvoiceAmount() throws Exception {
|
||||
InvoiceAmountRespVO respVO = new InvoiceAmountRespVO();
|
||||
respVO.setPendingInvoice(new BigDecimal("150.00"));
|
||||
respVO.setInvoiced(new BigDecimal("300.00"));
|
||||
|
||||
when(invoiceService.getManageInvoiceAmount()).thenReturn(respVO);
|
||||
|
||||
mockMvc.perform(get("/system/invoice/manage/amount"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data.pendingInvoice").value(150.00))
|
||||
.andExpect(jsonPath("$.data.invoiced").value(300.00));
|
||||
|
||||
verify(invoiceService).getManageInvoiceAmount();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAvailablePage() throws Exception {
|
||||
InvoiceAmountAndAvailablePageReqVO reqVO = new InvoiceAmountAndAvailablePageReqVO();
|
||||
PageResult<InvoiceAvailablePageRespVO> mockPage = new PageResult<>();
|
||||
mockPage.setTotal(1L);
|
||||
InvoiceAvailablePageRespVO pageRespVO = new InvoiceAvailablePageRespVO();
|
||||
pageRespVO.setId(1L);
|
||||
pageRespVO.setAvailableAmount(new BigDecimal("100.00"));
|
||||
mockPage.setList(List.of(pageRespVO));
|
||||
|
||||
when(invoiceService.getAvailablePage(any())).thenReturn(mockPage);
|
||||
|
||||
mockMvc.perform(get("/system/invoice/available")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(reqVO)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data.list[0].id").value(1L))
|
||||
.andExpect(jsonPath("$.data.list[0].availableAmount").value(100.00));
|
||||
|
||||
verify(invoiceService, times(1)).getAvailablePage(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testApplyInvoiceRecords() throws Exception {
|
||||
InvoiceRecordsReqVO reqVO = new InvoiceRecordsReqVO();
|
||||
reqVO.setPurchaseRecordId(List.of(1L, 2L));
|
||||
|
||||
doNothing().when(invoiceService).applyInvoice(any());
|
||||
|
||||
mockMvc.perform(post("/system/invoice")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(reqVO)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data").value(true));
|
||||
|
||||
verify(invoiceService).applyInvoice(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetInvoiceRecords() throws Exception {
|
||||
InvoiceDetailsPageReqVO reqVO = new InvoiceDetailsPageReqVO();
|
||||
PageResult<InvoiceRecordsRespVO> mockPage = new PageResult<>();
|
||||
mockPage.setTotal(1L);
|
||||
InvoiceRecordsRespVO pageRespVO = new InvoiceRecordsRespVO();
|
||||
pageRespVO.setId(1L);
|
||||
pageRespVO.setInvoiceAmount(new BigDecimal("150.00"));
|
||||
mockPage.setList(List.of(pageRespVO));
|
||||
|
||||
when(invoiceService.getInvoiceRecords(any())).thenReturn(mockPage);
|
||||
|
||||
mockMvc.perform(get("/system/invoice/records")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(reqVO)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data.list[0].id").value(1L))
|
||||
.andExpect(jsonPath("$.data.list[0].invoiceAmount").value(150.00));
|
||||
|
||||
verify(invoiceService, times(1)).getInvoiceRecords(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetInvoiceRecordDetail() throws Exception {
|
||||
Long recordId = 1L;
|
||||
InvoiceDetailsRespVO respVO = new InvoiceDetailsRespVO();
|
||||
respVO.setInvoiceNo("FP20231010101010");
|
||||
respVO.setRemark("测试备注");
|
||||
|
||||
when(invoiceService.getInvoiceRecordDetail(recordId)).thenReturn(respVO);
|
||||
|
||||
mockMvc.perform(get("/system/invoice/record/{recordId}", recordId))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data.invoiceNo").value("FP20231010101010"))
|
||||
.andExpect(jsonPath("$.data.remark").value("测试备注"));
|
||||
|
||||
verify(invoiceService).getInvoiceRecordDetail(recordId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConfirmInvoice() throws Exception {
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
reqVO.setId(1L);
|
||||
reqVO.setAgree(true);
|
||||
reqVO.setInvoiceNo("FP20231010101010");
|
||||
reqVO.setRemark("同意开票");
|
||||
|
||||
doNothing().when(invoiceService).confirmInvoice(any(), any());
|
||||
|
||||
MockMultipartFile file = new MockMultipartFile(
|
||||
"file",
|
||||
"invoice.pdf",
|
||||
"application/pdf",
|
||||
"test data".getBytes()
|
||||
);
|
||||
|
||||
// 使用param方式传递reqVO参数
|
||||
mockMvc.perform(multipart("/system/invoice/confirm")
|
||||
.file(file)
|
||||
.param("id", "1")
|
||||
.param("agree", "true")
|
||||
.param("invoiceNo", "FP20231010101010")
|
||||
.param("remark", "同意开票"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data").value(true));
|
||||
|
||||
verify(invoiceService).confirmInvoice(any(), any());
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -17,9 +17,9 @@ import static org.mockito.Mockito.verify;
|
||||
*/
|
||||
class SystemPermissionRefreshRedisListenerTest {
|
||||
@Test
|
||||
void onMessage_shouldClearDictDataI18nCache() {
|
||||
SecurityFrameworkService securityFrameworkService = mock(SecurityFrameworkService.class);
|
||||
void onMessage_shouldInvalidateAllPermissionsCache() {
|
||||
// given
|
||||
SecurityFrameworkService securityFrameworkService = mock(SecurityFrameworkService.class);
|
||||
SystemPermissionRefreshRedisListener listener =
|
||||
new SystemPermissionRefreshRedisListener(securityFrameworkService);
|
||||
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package com.cf.imes.module.system.service.funds.incomeandexpense;
|
||||
|
||||
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||
import com.cf.imes.module.system.dal.dataobject.incomeandexpense.IncomeExpenseDetailsDO;
|
||||
import com.cf.imes.module.system.dal.mysql.incomeandexpense.IncomeExpenseDetailsMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link IncomeExpenseServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author Gqr
|
||||
*/
|
||||
@Import(IncomeExpenseServiceImpl.class)
|
||||
class IncomeExpenseServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
|
||||
@Resource
|
||||
private IncomeExpenseServiceImpl incomeExpenseService;
|
||||
|
||||
@Resource
|
||||
private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper;
|
||||
|
||||
@Test
|
||||
void testCreateDetail() {
|
||||
// 准备数据
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = new IncomeExpenseDetailsDO();
|
||||
incomeExpenseDetailsDO.setBusinessNo("BUS20251215001");
|
||||
incomeExpenseDetailsDO.setOrderNo("ORD20251215001");
|
||||
incomeExpenseDetailsDO.setOrganId(1L);
|
||||
incomeExpenseDetailsDO.setPurchaseId(100L);
|
||||
incomeExpenseDetailsDO.setTradeType(1);
|
||||
incomeExpenseDetailsDO.setIncomeExpenseType(2);
|
||||
incomeExpenseDetailsDO.setAmount(new BigDecimal("100.00"));
|
||||
incomeExpenseDetailsDO.setCurrency(1);
|
||||
incomeExpenseDetailsDO.setCurrencyUnit("CNY");
|
||||
incomeExpenseDetailsDO.setRemark("测试收支明细");
|
||||
|
||||
// 调用方法
|
||||
Long id = incomeExpenseService.createDetail(incomeExpenseDetailsDO);
|
||||
|
||||
// 验证结果
|
||||
assertNotNull(id);
|
||||
assertTrue(id > 0);
|
||||
|
||||
// 验证数据库中是否已插入数据
|
||||
IncomeExpenseDetailsDO dbRecord = incomeExpenseDetailsMapper.selectById(id);
|
||||
assertNotNull(dbRecord);
|
||||
assertEquals("BUS20251215001", dbRecord.getBusinessNo());
|
||||
assertEquals("ORD20251215001", dbRecord.getOrderNo());
|
||||
assertEquals(1L, dbRecord.getOrganId());
|
||||
assertEquals(100L, dbRecord.getPurchaseId());
|
||||
assertEquals(1, dbRecord.getTradeType());
|
||||
assertEquals(2, dbRecord.getIncomeExpenseType());
|
||||
assertEquals(new BigDecimal("100.00"), dbRecord.getAmount());
|
||||
assertEquals(1, dbRecord.getCurrency());
|
||||
assertEquals("CNY", dbRecord.getCurrencyUnit());
|
||||
assertEquals("测试收支明细", dbRecord.getRemark());
|
||||
}
|
||||
}
|
||||
+906
@@ -0,0 +1,906 @@
|
||||
package com.cf.imes.module.system.service.funds.invoice;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.cf.imes.framework.security.test.WithMockLoginUser;
|
||||
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||
import com.cf.imes.module.infra.api.file.FileApi;
|
||||
import com.cf.imes.module.system.controller.admin.funds.invoice.vo.*;
|
||||
import com.cf.imes.module.system.dal.dataobject.funds.invoice.InvoiceRecordsDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.funds.invoice.InvoiceTitleInfoDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
|
||||
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.InvoiceIssueTypeEnum;
|
||||
import com.cf.imes.module.system.enums.pay.InvoiceStatusEnum;
|
||||
import com.cf.imes.module.system.enums.pay.PayChannelCodeEnum;
|
||||
import com.cf.imes.module.system.enums.pay.TradeTypeEnum;
|
||||
import com.cf.imes.module.system.service.organ.OrganService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
import static com.cf.imes.framework.common.util.json.JsonUtils.zipString;
|
||||
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* 发票服务测试类
|
||||
*
|
||||
* @author Gqr
|
||||
* @since 2025/12/15 15:31
|
||||
*/
|
||||
@Import(InvoiceServiceImpl.class)
|
||||
class InvoiceServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
|
||||
@Resource
|
||||
private InvoiceServiceImpl invoiceService;
|
||||
|
||||
@Resource
|
||||
private InvoiceTitleInfoMapper invoiceTitleInfoMapper;
|
||||
|
||||
@Resource
|
||||
private PurchaseRecordMapper purchaseRecordMapper;
|
||||
|
||||
@Resource
|
||||
private InvoiceRecordsMapper invoiceRecordsMapper;
|
||||
|
||||
@MockitoBean
|
||||
private OrganService organService;
|
||||
|
||||
@MockitoBean
|
||||
private FileApi fileApi;
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void testGetInvoiceTitle() {
|
||||
// 准备参数
|
||||
Long organId = SecurityFrameworkUtils.getUserOrganId();
|
||||
|
||||
// 使用真实数据查询发票抬头信息
|
||||
InvoiceTitleInfoDO invoiceTitleInfoDO = randomPojo(InvoiceTitleInfoDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(organId);
|
||||
o.setInvoiceTitle("测试公司");
|
||||
});
|
||||
|
||||
invoiceTitleInfoMapper.insert(invoiceTitleInfoDO);
|
||||
|
||||
// 调用
|
||||
InvoiceTitleInfo result = invoiceService.getInvoiceTitle();
|
||||
|
||||
// 断言
|
||||
assertNotNull(result);
|
||||
assertEquals(1L, result.getId());
|
||||
assertEquals("测试公司", result.getInvoiceTitle());
|
||||
assertEquals(organId, result.getOrganId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void insetInvoiceTitle_create_success() {
|
||||
Long organId = SecurityFrameworkUtils.getUserOrganId();
|
||||
|
||||
InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO();
|
||||
reqVO.setInvoiceTitle("测试公司");
|
||||
reqVO.setIssueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue());
|
||||
reqVO.setInvoiceType(0);
|
||||
reqVO.setTaxNumber("91330101MA2HXXXXXX");
|
||||
reqVO.setEmail("test@company.com");
|
||||
|
||||
invoiceService.insetInvoiceTitle(reqVO);
|
||||
|
||||
// ====== 校验数据库 ======
|
||||
InvoiceTitleInfoDO dbRecord = invoiceTitleInfoMapper.selectOne(
|
||||
new LambdaQueryWrapper<InvoiceTitleInfoDO>()
|
||||
.eq(InvoiceTitleInfoDO::getOrganId, organId)
|
||||
);
|
||||
|
||||
assertNotNull(dbRecord);
|
||||
assertEquals("测试公司", dbRecord.getInvoiceTitle());
|
||||
assertEquals("91330101MA2HXXXXXX", dbRecord.getTaxNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void insetInvoiceTitle_enterpriseWithoutTaxNumber_throwException() {
|
||||
InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO();
|
||||
reqVO.setInvoiceTitle("测试公司");
|
||||
reqVO.setIssueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue());
|
||||
reqVO.setInvoiceType(0);
|
||||
reqVO.setTaxNumber(null);
|
||||
|
||||
ServiceException ex = assertThrows(
|
||||
ServiceException.class,
|
||||
() -> invoiceService.insetInvoiceTitle(reqVO)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
INVOICE_TITLE_ENTERPRISE_TAXNUMBER_EMPTY_ERROR.getCode(),
|
||||
ex.getCode()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void insetInvoiceTitle_sameOrgan_throwOrgExists() {
|
||||
Long organId = SecurityFrameworkUtils.getUserOrganId();
|
||||
|
||||
invoiceTitleInfoMapper.insert(InvoiceTitleInfoDO.builder()
|
||||
.organId(organId)
|
||||
.issueType(InvoiceIssueTypeEnum.PERSONAL.getValue())
|
||||
.invoiceTitle("已存在")
|
||||
.build());
|
||||
|
||||
InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO();
|
||||
reqVO.setInvoiceTitle("新抬头");
|
||||
reqVO.setIssueType(InvoiceIssueTypeEnum.PERSONAL.getValue());
|
||||
|
||||
ServiceException ex = assertThrows(
|
||||
ServiceException.class,
|
||||
() -> invoiceService.insetInvoiceTitle(reqVO)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
INVOICE_TITLE_ORG_EXISTS_ERROR.getCode(),
|
||||
ex.getCode()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void insetInvoiceTitle_update_notExists_throwException() {
|
||||
InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO();
|
||||
reqVO.setId(999L); // 数据库不存在
|
||||
reqVO.setInvoiceTitle("测试抬头");
|
||||
reqVO.setIssueType(InvoiceIssueTypeEnum.PERSONAL.getValue());
|
||||
|
||||
ServiceException ex = assertThrows(
|
||||
ServiceException.class,
|
||||
() -> invoiceService.insetInvoiceTitle(reqVO)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
INVOICE_TITLE_NOT_EXISTS_ERROR.getCode(),
|
||||
ex.getCode()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void insetInvoiceTitle_update_orgNotMatch_throwException() {
|
||||
InvoiceTitleInfoDO exist = InvoiceTitleInfoDO.builder()
|
||||
.organId(2L)
|
||||
.issueType(InvoiceIssueTypeEnum.PERSONAL.getValue())
|
||||
.invoiceTitle("原抬头")
|
||||
.build();
|
||||
invoiceTitleInfoMapper.insert(exist);
|
||||
|
||||
InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO();
|
||||
reqVO.setId(exist.getId());
|
||||
reqVO.setInvoiceTitle("非法更新");
|
||||
reqVO.setIssueType(exist.getIssueType());
|
||||
|
||||
ServiceException ex = assertThrows(
|
||||
ServiceException.class,
|
||||
() -> invoiceService.insetInvoiceTitle(reqVO)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
INVOICE_TITLE_NOT_EXISTS_ERROR.getCode(),
|
||||
ex.getCode()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void insetInvoiceTitle_insert_success() {
|
||||
Long organId = SecurityFrameworkUtils.getUserOrganId();
|
||||
|
||||
InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO();
|
||||
reqVO.setInvoiceTitle("新增抬头");
|
||||
reqVO.setIssueType(InvoiceIssueTypeEnum.PERSONAL.getValue());
|
||||
reqVO.setInvoiceType(0);
|
||||
reqVO.setEmail("test@test.com");
|
||||
|
||||
invoiceService.insetInvoiceTitle(reqVO);
|
||||
|
||||
// 验证数据库
|
||||
List<InvoiceTitleInfoDO> list = invoiceTitleInfoMapper.selectList(null);
|
||||
assertEquals(1, list.size());
|
||||
|
||||
InvoiceTitleInfoDO saved = list.get(0);
|
||||
assertEquals(organId, saved.getOrganId());
|
||||
assertEquals("新增抬头", saved.getInvoiceTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void insetInvoiceTitle_enterprise_taxNumberExists_throwException() {
|
||||
// 先插入一条企业发票抬头
|
||||
InvoiceTitleInfoDO exist = InvoiceTitleInfoDO.builder()
|
||||
.organId(2L) // 不同组织也没关系
|
||||
.invoiceTitle("已存在抬头")
|
||||
.issueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue())
|
||||
.taxNumber("91330100XXXXXX")
|
||||
.build();
|
||||
invoiceTitleInfoMapper.insert(exist);
|
||||
|
||||
// 再新增一条相同税号
|
||||
InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO();
|
||||
reqVO.setInvoiceTitle("新抬头");
|
||||
reqVO.setIssueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue());
|
||||
reqVO.setTaxNumber("91330100XXXXXX");
|
||||
|
||||
ServiceException ex = assertThrows(
|
||||
ServiceException.class,
|
||||
() -> invoiceService.insetInvoiceTitle(reqVO)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
INVOICE_TITLE_TAXPAYERID_EXISTS_ERROR.getCode(),
|
||||
ex.getCode()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void insetInvoiceTitle_update_success() {
|
||||
Long organId = SecurityFrameworkUtils.getUserOrganId();
|
||||
|
||||
// given:数据库已有数据(organId 一定要一致)
|
||||
InvoiceTitleInfoDO exist = InvoiceTitleInfoDO.builder()
|
||||
.organId(organId)
|
||||
.invoiceTitle("旧抬头")
|
||||
.issueType(InvoiceIssueTypeEnum.PERSONAL.getValue())
|
||||
.build();
|
||||
invoiceTitleInfoMapper.insert(exist);
|
||||
|
||||
// when:更新
|
||||
InvoiceTitleSaveReqVO reqVO = new InvoiceTitleSaveReqVO();
|
||||
reqVO.setId(exist.getId());
|
||||
reqVO.setInvoiceTitle("新抬头");
|
||||
reqVO.setIssueType(InvoiceIssueTypeEnum.PERSONAL.getValue());
|
||||
|
||||
invoiceService.insetInvoiceTitle(reqVO);
|
||||
|
||||
// then:断言更新成功
|
||||
InvoiceTitleInfoDO updated = invoiceTitleInfoMapper.selectById(exist.getId());
|
||||
assertEquals("新抬头", updated.getInvoiceTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void getAvailablePage_whenEmptyList_returnEmptyPageResult() {
|
||||
// given
|
||||
InvoiceAmountAndAvailablePageReqVO reqVO = new InvoiceAmountAndAvailablePageReqVO();
|
||||
|
||||
// when
|
||||
PageResult<InvoiceAvailablePageRespVO> result =
|
||||
invoiceService.getAvailablePage(reqVO);
|
||||
|
||||
// then
|
||||
assertNotNull(result);
|
||||
assertEquals(0, result.getTotal());
|
||||
assertTrue(CollUtil.isEmpty(result.getList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser(organId = 1L)
|
||||
void getAvailablePage_whenHasData_returnConvertedPage() {
|
||||
// given
|
||||
InvoiceAmountAndAvailablePageReqVO reqVO =
|
||||
new InvoiceAmountAndAvailablePageReqVO();
|
||||
|
||||
PurchaseRecordDO invoiceRecordsDO = randomPojo(PurchaseRecordDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setCreateTime(LocalDateTime.now());
|
||||
o.setExternalSpent(new BigDecimal("100.00"));
|
||||
o.setProductName("测试产品");
|
||||
o.setTotalAmount(new BigDecimal("200.00"));
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
o.setInitial(false);
|
||||
o.setOrganId(1L);
|
||||
});
|
||||
purchaseRecordMapper.insert(invoiceRecordsDO);
|
||||
|
||||
// when
|
||||
PageResult<InvoiceAvailablePageRespVO> result =
|
||||
invoiceService.getAvailablePage(reqVO);
|
||||
|
||||
// then
|
||||
assertNotNull(result);
|
||||
assertEquals(1L, result.getTotal());
|
||||
assertEquals(1, result.getList().size());
|
||||
|
||||
InvoiceAvailablePageRespVO vo = result.getList().get(0);
|
||||
assertEquals(1L, vo.getId());
|
||||
assertEquals(TradeTypeEnum.PRODUCT.getCode(), vo.getTradeType());
|
||||
assertEquals(invoiceRecordsDO.getExternalSpent(), vo.getAvailableAmount());
|
||||
assertEquals("测试产品", vo.getProductName());
|
||||
assertEquals(invoiceRecordsDO.getTotalAmount(), vo.getTotalAmount());
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyInvoice_whenNoLogin_throwUnauthorized() {
|
||||
InvoiceRecordsReqVO reqVO = new InvoiceRecordsReqVO();
|
||||
|
||||
assertServiceException(() -> invoiceService.applyInvoice(reqVO), GlobalErrorCodeConstants.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser(organId = 1L)
|
||||
void applyInvoice_whenUninvoicableExist_throwException() {
|
||||
InvoiceRecordsReqVO reqVO = new InvoiceRecordsReqVO();
|
||||
assertServiceException(() -> invoiceService.applyInvoice(reqVO), INVOICE_TITLE_NOT_EXISTS_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser(organId = 1L)
|
||||
void applyInvoice_uninvoiceableExist() {
|
||||
// 先插入一条企业发票抬头
|
||||
InvoiceTitleInfoDO exist = InvoiceTitleInfoDO.builder()
|
||||
.organId(1L) // 不同组织也没关系
|
||||
.invoiceTitle("已存在抬头")
|
||||
.issueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue())
|
||||
.taxNumber("91330100XXXXXX")
|
||||
.build();
|
||||
invoiceTitleInfoMapper.insert(exist);
|
||||
|
||||
InvoiceRecordsReqVO reqVO = new InvoiceRecordsReqVO();
|
||||
|
||||
PurchaseRecordDO invoiceRecordsDO = randomPojo(PurchaseRecordDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setCreateTime(LocalDateTime.now());
|
||||
o.setExternalSpent(new BigDecimal("100.00"));
|
||||
o.setProductName("测试产品");
|
||||
o.setTotalAmount(new BigDecimal("200.00"));
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode());
|
||||
o.setInitial(false);
|
||||
o.setOrganId(1L);
|
||||
});
|
||||
purchaseRecordMapper.insert(invoiceRecordsDO);
|
||||
// 有不可开票状态的记录
|
||||
reqVO.setPurchaseRecordId(List.of(invoiceRecordsDO.getId()));
|
||||
assertServiceException(() -> invoiceService.applyInvoice(reqVO), INVOICE_APPLY_UNINVOICEABLE_EXIST);
|
||||
|
||||
// 可开金额为0
|
||||
invoiceRecordsDO.setId(null);
|
||||
invoiceRecordsDO.setExternalSpent(BigDecimal.ZERO);
|
||||
invoiceRecordsDO.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
purchaseRecordMapper.insert(invoiceRecordsDO);
|
||||
reqVO.setPurchaseRecordId(List.of(invoiceRecordsDO.getId()));
|
||||
assertServiceException(() -> invoiceService.applyInvoice(reqVO), INVOICE_AMOUNT_ZERO_ERROR);
|
||||
|
||||
// 更新开票状态和开票id数量不匹配
|
||||
invoiceRecordsDO.setId(null);
|
||||
invoiceRecordsDO.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
invoiceRecordsDO.setExternalSpent(new BigDecimal("100"));
|
||||
purchaseRecordMapper.insert(invoiceRecordsDO);
|
||||
|
||||
reqVO.setPurchaseRecordId(List.of(invoiceRecordsDO.getId(), 999L));
|
||||
assertServiceException(
|
||||
() -> invoiceService.applyInvoice(reqVO),
|
||||
ORG_INVOICE_PURCHASE_RECORD_UPDATE_NUM_NOT_MATCH_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser(organId = 1L)
|
||||
void applyInvoice_success() {
|
||||
// 先插入一条企业发票抬头
|
||||
InvoiceTitleInfoDO exist = InvoiceTitleInfoDO.builder()
|
||||
.organId(1L) // 不同组织也没关系
|
||||
.invoiceTitle("已存在抬头")
|
||||
.issueType(InvoiceIssueTypeEnum.ENTERPRISE.getValue())
|
||||
.taxNumber("91330100XXXXXX")
|
||||
.build();
|
||||
invoiceTitleInfoMapper.insert(exist);
|
||||
|
||||
InvoiceRecordsReqVO reqVO = new InvoiceRecordsReqVO();
|
||||
|
||||
PurchaseRecordDO invoiceRecordsDO = randomPojo(PurchaseRecordDO.class, o -> {
|
||||
o.setCreateTime(LocalDateTime.now());
|
||||
o.setExternalSpent(new BigDecimal("100.00"));
|
||||
o.setProductName("测试产品");
|
||||
o.setTotalAmount(new BigDecimal("200.00"));
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
o.setInitial(false);
|
||||
o.setOrganId(1L);
|
||||
});
|
||||
purchaseRecordMapper.insert(invoiceRecordsDO);
|
||||
|
||||
Long recordId = invoiceRecordsDO.getId();
|
||||
reqVO.setPurchaseRecordId(List.of(recordId));
|
||||
|
||||
// 组织
|
||||
OrganizationDO org = new OrganizationDO();
|
||||
org.setName("测试组织");
|
||||
org.setId(1L);
|
||||
when(organService.validOrgan(1L)).thenReturn(org);
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
invoiceService.applyInvoice(reqVO);
|
||||
});
|
||||
List<InvoiceRecordsDO> invoiceRecordsDOS = invoiceRecordsMapper.selectList();
|
||||
assertEquals(1, invoiceRecordsDOS.size());
|
||||
InvoiceRecordsDO query = invoiceRecordsDOS.get(0);
|
||||
assertNotNull(invoiceRecordsDO);
|
||||
assertEquals(invoiceRecordsDO.getOrganId(), invoiceRecordsDO.getOrganId());
|
||||
assertEquals(query.getPurchaseIds(), List.of(invoiceRecordsDO.getId()).toString());
|
||||
assertEquals("测试组织", query.getOrganName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void getInvoiceRecords_whenEmptyList_returnEmptyPageResult() {
|
||||
// given
|
||||
InvoiceDetailsPageReqVO pageReqVO = new InvoiceDetailsPageReqVO();
|
||||
|
||||
// when
|
||||
PageResult<InvoiceRecordsRespVO> result = invoiceService.getInvoiceRecords(pageReqVO);
|
||||
|
||||
// then
|
||||
assertNotNull(result);
|
||||
assertEquals(0, result.getTotal());
|
||||
assertTrue(CollUtil.isEmpty(result.getList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void getInvoiceRecords_whenHasData_returnConvertedPage() {
|
||||
// given
|
||||
InvoiceDetailsPageReqVO pageReqVO = new InvoiceDetailsPageReqVO();
|
||||
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o->{
|
||||
o.setId(1L);
|
||||
o.setInvoiceAmount(new BigDecimal("100.00"));
|
||||
o.setStatus(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
|
||||
// when
|
||||
PageResult<InvoiceRecordsRespVO> result = invoiceService.getInvoiceRecords(pageReqVO);
|
||||
|
||||
// then
|
||||
assertNotNull(result);
|
||||
assertEquals(1L, result.getTotal());
|
||||
assertEquals(1, result.getList().size());
|
||||
|
||||
InvoiceRecordsRespVO vo = result.getList().get(0);
|
||||
assertEquals(1L, vo.getId());
|
||||
assertEquals(invoiceRecordsDO.getInvoiceAmount(), vo.getInvoiceAmount());
|
||||
assertEquals(invoiceRecordsDO.getStatus(), vo.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void getInvoiceRecordDetail_whenRecordNotExists_thenThrowException() {
|
||||
assertServiceException(() -> invoiceService.getInvoiceRecordDetail(1L), INVOICE_NO_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void getInvoiceRecordDetail_whenRecordExists_thenReturnDetail() {
|
||||
// 准备数据
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setInvoiceAmount(new BigDecimal("100.00"));
|
||||
o.setPurchaseIds("[1, 2]");
|
||||
o.setInvoiceTitleInfo(zipString("{\"invoiceTitle\":\"测试公司\"}"));
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
|
||||
PurchaseRecordDO purchase1 = randomPojo(PurchaseRecordDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setProductName("产品1");
|
||||
o.setTotalAmount(new BigDecimal("50.00"));
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
o.setInitial(false);
|
||||
});
|
||||
purchaseRecordMapper.insert(purchase1);
|
||||
|
||||
PurchaseRecordDO purchase2 = randomPojo(PurchaseRecordDO.class, o -> {
|
||||
o.setId(2L);
|
||||
o.setOrganId(1L);
|
||||
o.setProductName("产品2");
|
||||
o.setTotalAmount(new BigDecimal("50.00"));
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
o.setInitial(false);
|
||||
});
|
||||
purchaseRecordMapper.insert(purchase2);
|
||||
|
||||
// 调用方法
|
||||
InvoiceDetailsRespVO result = invoiceService.getInvoiceRecordDetail(1L);
|
||||
|
||||
// 验证结果
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.getInvoicePurchaseRecords().size());
|
||||
assertEquals("测试公司", result.getInvoiceTitleInfo().getInvoiceTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
void confirmInvoice_whenNoLogin_thenThrowUnauthorized() {
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
assertServiceException(() -> invoiceService.confirmInvoice(reqVO, null), GlobalErrorCodeConstants.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void confirmInvoice_whenRecordNotExists_thenThrowException() {
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
reqVO.setId(1L);
|
||||
assertServiceException(() -> invoiceService.confirmInvoice(reqVO, null), INVOICE_NO_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void confirmInvoice_whenRecordAlreadySuccess_thenThrowException() {
|
||||
// 准备数据
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setStatus(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode());
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
reqVO.setId(1L);
|
||||
|
||||
assertServiceException(() -> invoiceService.confirmInvoice(reqVO, null), THIS_INVOICE_IS_FAIL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void confirmInvoice_whenRecordAlreadyFailed_thenThrowException() {
|
||||
// 准备数据
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setStatus(InvoiceStatusEnum.INVOICINGFAILED.getCode());
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
reqVO.setId(1L);
|
||||
|
||||
assertServiceException(() -> invoiceService.confirmInvoice(reqVO, null), THIS_INVOICE_IS_FAIL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void confirmInvoice_whenPurchaseRecordNotExists_thenThrowException() {
|
||||
// 准备数据
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setStatus(InvoiceStatusEnum.PENDINGINVOICING.getCode());
|
||||
o.setPurchaseIds("[1]");
|
||||
o.setInvoiceTitleId(1L);
|
||||
o.setOrganId(1L);
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
reqVO.setId(1L);
|
||||
|
||||
assertServiceException(() -> invoiceService.confirmInvoice(reqVO, null), PURCHASE_RECORD_NO_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void confirmInvoice_agreeWithoutFile_thenThrowException() {
|
||||
// 准备数据
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setStatus(InvoiceStatusEnum.PENDINGINVOICING.getCode());
|
||||
o.setPurchaseIds("[1]");
|
||||
o.setInvoiceTitleId(1L);
|
||||
o.setOrganId(1L);
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
|
||||
InvoiceTitleInfoDO title = randomPojo(InvoiceTitleInfoDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setInvoiceTitle("测试公司");
|
||||
});
|
||||
invoiceTitleInfoMapper.insert(title);
|
||||
|
||||
PurchaseRecordDO purchase = randomPojo(PurchaseRecordDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
o.setInitial(false);
|
||||
});
|
||||
purchaseRecordMapper.insert(purchase);
|
||||
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
reqVO.setId(1L);
|
||||
reqVO.setAgree(true);
|
||||
|
||||
assertServiceException(() -> invoiceService.confirmInvoice(reqVO, null), ORG_INVOICE_AGREE_FILE_NULL_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void confirmInvoice_rejectWithoutRemark_thenThrowException() {
|
||||
// 准备数据
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setStatus(InvoiceStatusEnum.PENDINGINVOICING.getCode());
|
||||
o.setPurchaseIds("[1]");
|
||||
o.setInvoiceTitleId(1L);
|
||||
o.setOrganId(1L);
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
|
||||
InvoiceTitleInfoDO title = randomPojo(InvoiceTitleInfoDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setInvoiceTitle("测试公司");
|
||||
});
|
||||
invoiceTitleInfoMapper.insert(title);
|
||||
|
||||
PurchaseRecordDO purchase = randomPojo(PurchaseRecordDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
o.setInitial(false);
|
||||
});
|
||||
purchaseRecordMapper.insert(purchase);
|
||||
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
reqVO.setId(1L);
|
||||
reqVO.setAgree(false);
|
||||
reqVO.setRemark(null);
|
||||
|
||||
assertServiceException(() -> invoiceService.confirmInvoice(reqVO, null), INVOICING_REJECT_REASON);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser(username = "测试用户", userId = 1L)
|
||||
void confirmInvoice_agreeWithFile_thenSuccess() {
|
||||
// 准备数据
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setStatus(InvoiceStatusEnum.PENDINGINVOICING.getCode());
|
||||
o.setPurchaseIds("[1]");
|
||||
o.setInvoiceTitleId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setInvoiceAmount(new BigDecimal("100.00"));
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
|
||||
InvoiceTitleInfoDO title = randomPojo(InvoiceTitleInfoDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setInvoiceTitle("测试公司");
|
||||
});
|
||||
invoiceTitleInfoMapper.insert(title);
|
||||
|
||||
PurchaseRecordDO purchase = randomPojo(PurchaseRecordDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
o.setInitial(false);
|
||||
});
|
||||
purchaseRecordMapper.insert(purchase);
|
||||
|
||||
// Mock 文件上传
|
||||
MockMultipartFile file = new MockMultipartFile("file", "测试公司-20231010101010-100.pdf", "application/pdf", "content".getBytes());
|
||||
when(fileApi.createFileAndReturnId(any(byte[].class), anyString())).thenReturn(1L);
|
||||
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
reqVO.setId(1L);
|
||||
reqVO.setAgree(true);
|
||||
reqVO.setInvoiceNo("FP20231010101010");
|
||||
reqVO.setRemark("同意开票");
|
||||
|
||||
// 调用方法
|
||||
assertDoesNotThrow(() -> invoiceService.confirmInvoice(reqVO, file));
|
||||
|
||||
// 验证数据库更新
|
||||
InvoiceRecordsDO updatedRecord = invoiceRecordsMapper.selectById(1L);
|
||||
assertEquals(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode(), updatedRecord.getStatus());
|
||||
assertEquals("FP20231010101010", updatedRecord.getInvoiceNo());
|
||||
assertEquals("同意开票", updatedRecord.getRemark());
|
||||
assertEquals("测试用户", updatedRecord.getInvoicePerson());
|
||||
assertEquals(1L, updatedRecord.getInvoicePersonId());
|
||||
assertNotNull(updatedRecord.getInvoiceTime());
|
||||
assertEquals(1L, updatedRecord.getInvoiceAttachmentId());
|
||||
|
||||
PurchaseRecordDO updatedPurchase = purchaseRecordMapper.selectById(1L);
|
||||
assertEquals(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode(), updatedPurchase.getIsInvocing());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser(userId = 1L, username = "测试用户")
|
||||
void confirmInvoice_reject_thenSuccess() {
|
||||
// 准备数据
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setStatus(InvoiceStatusEnum.PENDINGINVOICING.getCode());
|
||||
o.setPurchaseIds("[1]");
|
||||
o.setInvoiceTitleId(1L);
|
||||
o.setOrganId(1L);
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
|
||||
InvoiceTitleInfoDO title = randomPojo(InvoiceTitleInfoDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setInvoiceTitle("测试公司");
|
||||
});
|
||||
invoiceTitleInfoMapper.insert(title);
|
||||
|
||||
PurchaseRecordDO purchase = randomPojo(PurchaseRecordDO.class, o -> {
|
||||
o.setId(1L);
|
||||
o.setOrganId(1L);
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
o.setInitial(false);
|
||||
});
|
||||
purchaseRecordMapper.insert(purchase);
|
||||
|
||||
InvoiceConfirmReqVO reqVO = new InvoiceConfirmReqVO();
|
||||
reqVO.setId(1L);
|
||||
reqVO.setAgree(false);
|
||||
reqVO.setRemark("拒绝开票");
|
||||
|
||||
// 调用方法
|
||||
assertDoesNotThrow(() -> invoiceService.confirmInvoice(reqVO, null));
|
||||
|
||||
// 验证数据库更新
|
||||
InvoiceRecordsDO updatedRecord = invoiceRecordsMapper.selectById(1L);
|
||||
assertEquals(InvoiceStatusEnum.INVOICINGFAILED.getCode(), updatedRecord.getStatus());
|
||||
assertEquals("拒绝开票", updatedRecord.getRemark());
|
||||
assertEquals("测试用户", updatedRecord.getInvoicePerson());
|
||||
assertEquals(1L, updatedRecord.getInvoicePersonId());
|
||||
assertNotNull(updatedRecord.getInvoiceTime());
|
||||
|
||||
PurchaseRecordDO updatedPurchase = purchaseRecordMapper.selectById(1L);
|
||||
assertEquals(InvoiceStatusEnum.INVOICABLE.getCode(), updatedPurchase.getIsInvocing());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void getInvoiceAmount_whenNoData_thenReturnZeroValues() {
|
||||
// 调用方法
|
||||
InvoiceAmountRespVO result = invoiceService.getInvoiceAmount();
|
||||
|
||||
// 验证结果
|
||||
assertNotNull(result);
|
||||
assertEquals(BigDecimal.ZERO, result.getInvocable());
|
||||
assertEquals(BigDecimal.ZERO, result.getInTheInvoice());
|
||||
assertEquals(BigDecimal.ZERO, result.getInvoiced());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void getInvoiceAmount_whenHasData_thenReturnCorrectValues() {
|
||||
// 可开票
|
||||
PurchaseRecordDO purchaseRecordDO = randomPojo(PurchaseRecordDO.class, o->{
|
||||
o.setExternalSpent(new BigDecimal("100.00"));
|
||||
o.setPaymentMethod(PayChannelCodeEnum.ALIPAY_PC.getCode());
|
||||
o.setIsInvocing(InvoiceStatusEnum.INVOICABLE.getCode());
|
||||
o.setInitial(false);
|
||||
o.setOrganId(SecurityFrameworkUtils.getUserOrganId());
|
||||
});
|
||||
purchaseRecordMapper.insert(purchaseRecordDO);
|
||||
|
||||
InvoiceAmountRespVO result = invoiceService.getInvoiceAmount();
|
||||
assertNotNull(result);
|
||||
assertEquals(new BigDecimal("100.00"), result.getInvocable());
|
||||
|
||||
// 开票中
|
||||
purchaseRecordDO.setId(null);
|
||||
purchaseRecordDO.setIsInvocing(InvoiceStatusEnum.PENDINGINVOICING.getCode());
|
||||
purchaseRecordMapper.insert(purchaseRecordDO);
|
||||
result = invoiceService.getInvoiceAmount();
|
||||
assertNotNull(result);
|
||||
assertEquals(new BigDecimal("100.00"), result.getInTheInvoice());
|
||||
|
||||
// 已开票
|
||||
purchaseRecordDO.setId(null);
|
||||
purchaseRecordDO.setIsInvocing(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode());
|
||||
purchaseRecordMapper.insert(purchaseRecordDO);
|
||||
result = invoiceService.getInvoiceAmount();
|
||||
assertNotNull(result);
|
||||
assertEquals(new BigDecimal("100.00"), result.getInvoiced());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getManageInvoiceAmount_whenNoData_thenReturnZeroValues() {
|
||||
// 调用方法
|
||||
InvoiceAmountRespVO result = invoiceService.getManageInvoiceAmount();
|
||||
|
||||
// 验证结果
|
||||
assertNotNull(result);
|
||||
assertEquals(BigDecimal.ZERO, result.getPendingInvoice());
|
||||
assertEquals(BigDecimal.ZERO, result.getInvoiced());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getManageInvoiceAmount_whenHasData_thenReturnCorrectValues() {
|
||||
// 待开票
|
||||
InvoiceRecordsDO invoiceRecordsDO = randomPojo(InvoiceRecordsDO.class, o -> {
|
||||
o.setInvoiceAmount(new BigDecimal("150.00"));
|
||||
o.setStatus(InvoiceStatusEnum.PENDINGINVOICING.getCode());
|
||||
});
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
InvoiceAmountRespVO result = invoiceService.getManageInvoiceAmount();
|
||||
assertNotNull(result);
|
||||
assertEquals(new BigDecimal("150.00"), result.getPendingInvoice());
|
||||
|
||||
// 已开票
|
||||
invoiceRecordsDO.setId(null);
|
||||
invoiceRecordsDO.setStatus(InvoiceStatusEnum.INVOICINGSUCCESSFUL.getCode());
|
||||
invoiceRecordsDO.setInvoiceAmount(new BigDecimal("300.00"));
|
||||
invoiceRecordsMapper.insert(invoiceRecordsDO);
|
||||
result = invoiceService.getManageInvoiceAmount();
|
||||
assertEquals(new BigDecimal("300.00"), result.getInvoiced());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileExtension_whenFileNameIsNull_thenReturnEmpty() {
|
||||
assertEquals("", InvoiceServiceImpl.getFileExtension(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileExtension_whenFileNameIsEmpty_thenReturnEmpty() {
|
||||
assertEquals("", InvoiceServiceImpl.getFileExtension(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileExtension_whenFileNameHasNoExtension_thenReturnEmpty() {
|
||||
assertEquals("", InvoiceServiceImpl.getFileExtension("filename"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileExtension_whenFileNameEndsWithDot_thenReturnEmpty() {
|
||||
assertEquals("", InvoiceServiceImpl.getFileExtension("filename."));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileExtension_whenFileNameHasExtension_thenReturnExtension() {
|
||||
assertEquals(".pdf", InvoiceServiceImpl.getFileExtension("filename.pdf"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileExtension_whenFileNameHasMultipleDots_thenReturnLastExtension() {
|
||||
assertEquals(".pdf", InvoiceServiceImpl.getFileExtension("file.name.pdf"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileExtension_whenFileNameHasExtensionInUpperCase_thenReturnLowerCaseExtension() {
|
||||
assertEquals(".pdf", InvoiceServiceImpl.getFileExtension("filename.PDF"));
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -2,6 +2,7 @@ package com.cf.imes.module.system.service.funds.productpromotion;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils;
|
||||
import com.cf.imes.framework.test.core.ut.BaseDbClearAfterClassAndRedisUnitTest;
|
||||
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionPageReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionSaveReqVO;
|
||||
@@ -50,6 +51,9 @@ class ProductPromotionServiceImplTest extends BaseDbClearAfterClassAndRedisUnitT
|
||||
@MockitoBean
|
||||
private ProductsDetailService productsDetailService;
|
||||
|
||||
@MockitoBean
|
||||
private I18nUtils i18nUtils;
|
||||
|
||||
private static ProductPromotionDO createDO;
|
||||
|
||||
@Test
|
||||
|
||||
+8
-39
@@ -5,7 +5,6 @@ import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
import com.cf.imes.framework.common.util.collection.ArrayUtils;
|
||||
import com.cf.imes.framework.common.util.collection.CollectionUtils;
|
||||
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
|
||||
import com.cf.imes.module.infra.api.file.FileApi;
|
||||
import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||
@@ -15,11 +14,8 @@ import com.cf.imes.module.system.controller.admin.user.vo.user.UserImportRespVO;
|
||||
import com.cf.imes.module.system.controller.admin.user.vo.user.UserPageReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.user.vo.user.UserSaveReqVO;
|
||||
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.dept.PostDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.dept.UserPostDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.cf.imes.module.system.dal.mysql.dept.UserPostMapper;
|
||||
import com.cf.imes.module.system.dal.mysql.user.AdminUserMapper;
|
||||
import com.cf.imes.module.system.enums.common.SexEnum;
|
||||
import com.cf.imes.module.system.service.dept.DeptService;
|
||||
@@ -27,11 +23,12 @@ import com.cf.imes.module.system.service.permission.PermissionService;
|
||||
import com.cf.imes.module.system.service.organ.OrganService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -62,18 +59,16 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private AdminUserMapper userMapper;
|
||||
@Resource
|
||||
private UserPostMapper userPostMapper;
|
||||
|
||||
@MockBean
|
||||
@MockitoBean
|
||||
private DeptService deptService;
|
||||
@MockBean
|
||||
@MockitoBean
|
||||
private PermissionService permissionService;
|
||||
@MockBean
|
||||
@MockitoBean
|
||||
private PasswordEncoder passwordEncoder;
|
||||
@MockBean
|
||||
@MockitoBean
|
||||
private OrganService tenantService;
|
||||
@MockBean
|
||||
@MockitoBean
|
||||
private FileApi fileApi;
|
||||
|
||||
@Test
|
||||
@@ -96,13 +91,6 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
});
|
||||
when(deptService.getDept(eq(dept.getId()))).thenReturn(dept);
|
||||
// mock postService 的方法
|
||||
List<PostDO> posts = CollectionUtils.convertList(reqVO.getPostIds(), postId ->
|
||||
randomPojo(PostDO.class, o -> {
|
||||
o.setId(postId);
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
}));
|
||||
//when(postService.getPostList(eq(reqVO.getPostIds()), isNull())).thenReturn(posts);
|
||||
|
||||
// 调用
|
||||
Long userId = userService.createUser(reqVO);
|
||||
@@ -111,10 +99,6 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||
assertPojoEquals(reqVO, user, "password", "id");
|
||||
assertEquals("chenfengyuanma", user.getPassword());
|
||||
assertEquals(CommonStatusEnum.ENABLE.getStatus(), user.getStatus());
|
||||
// 断言关联岗位
|
||||
List<UserPostDO> userPosts = userPostMapper.selectListByUserId(user.getId());
|
||||
assertEquals(1L, userPosts.get(0).getPostId());
|
||||
assertEquals(2L, userPosts.get(1).getPostId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -137,8 +121,6 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||
// mock 数据
|
||||
AdminUserDO dbUser = randomAdminUserDO(o -> o.setPostIds(asSet(1L, 2L)));
|
||||
userMapper.insert(dbUser);
|
||||
userPostMapper.insert(new UserPostDO().setUserId(dbUser.getId()).setPostId(1L));
|
||||
userPostMapper.insert(new UserPostDO().setUserId(dbUser.getId()).setPostId(2L));
|
||||
// 准备参数
|
||||
UserSaveReqVO reqVO = randomPojo(UserSaveReqVO.class, o -> {
|
||||
o.setId(dbUser.getId());
|
||||
@@ -152,23 +134,12 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
});
|
||||
when(deptService.getDept(eq(dept.getId()))).thenReturn(dept);
|
||||
// mock postService 的方法
|
||||
List<PostDO> posts = CollectionUtils.convertList(reqVO.getPostIds(), postId ->
|
||||
randomPojo(PostDO.class, o -> {
|
||||
o.setId(postId);
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
}));
|
||||
//when(postService.getPostList(eq(reqVO.getPostIds()), isNull())).thenReturn(posts);
|
||||
|
||||
// 调用
|
||||
userService.updateUser(reqVO);
|
||||
// 断言
|
||||
AdminUserDO user = userMapper.selectById(reqVO.getId());
|
||||
assertPojoEquals(reqVO, user, "password");
|
||||
// 断言关联岗位
|
||||
List<UserPostDO> userPosts = userPostMapper.selectListByUserId(user.getId());
|
||||
assertEquals(2L, userPosts.get(0).getPostId());
|
||||
assertEquals(3L, userPosts.get(1).getPostId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -627,12 +598,10 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||
// mock user1 数据
|
||||
AdminUserDO user1 = randomAdminUserDO(o -> o.setPostIds(asSet(10L, 30L)));
|
||||
userMapper.insert(user1);
|
||||
userPostMapper.insert(new UserPostDO().setUserId(user1.getId()).setPostId(10L));
|
||||
userPostMapper.insert(new UserPostDO().setUserId(user1.getId()).setPostId(30L));
|
||||
|
||||
// mock user2 数据
|
||||
AdminUserDO user2 = randomAdminUserDO(o -> o.setPostIds(singleton(100L)));
|
||||
userMapper.insert(user2);
|
||||
userPostMapper.insert(new UserPostDO().setUserId(user2.getId()).setPostId(100L));
|
||||
|
||||
// 调用
|
||||
List<AdminUserDO> result = userService.getUserListByPostIds(postIds);
|
||||
|
||||
@@ -40,4 +40,7 @@ DELETE FROM "products_details";
|
||||
DELETE FROM "product_promotion";
|
||||
DELETE FROM "advertisement";
|
||||
DELETE FROM "product_delay_record";
|
||||
DELETE FROM "purchase_record"
|
||||
DELETE FROM "purchase_record";
|
||||
DELETE FROM "income_expense_details";
|
||||
DELETE FROM "invoice_title_info";
|
||||
DELETE FROM "invoice_records";
|
||||
@@ -808,3 +808,77 @@ CREATE TABLE IF NOT EXISTS "purchase_record"
|
||||
"deleted" BIT NOT NULL DEFAULT FALSE COMMENT '是否删除:0否 1是',
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '购买记录表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "income_expense_details"
|
||||
(
|
||||
"id" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT 'ID,主键',
|
||||
"business_no" VARCHAR(64) DEFAULT NULL COMMENT '流水号',
|
||||
"order_no" VARCHAR(64) DEFAULT NULL COMMENT '订单号',
|
||||
"gift_money_id" BIGINT DEFAULT NULL COMMENT '充值-赠送金规则ID',
|
||||
"purchase_id" BIGINT DEFAULT NULL COMMENT '购买-购买记录ID',
|
||||
"organ_id" BIGINT NOT NULL DEFAULT '0' COMMENT '组织ID',
|
||||
"trade_type" TINYINT NOT NULL COMMENT '交易类型 0充值 1软件购买',
|
||||
"income_expense_type" TINYINT NOT NULL COMMENT '收支类型 0收入 1支出',
|
||||
"cash_amount_change" DECIMAL(10, 2) NOT NULL DEFAULT '0.00' COMMENT '支出/入账现金金额',
|
||||
"gift_amount_change" DECIMAL(10, 2) NOT NULL DEFAULT '0.00' COMMENT '支出/入账赠送金金额',
|
||||
"available_amount" DECIMAL(10, 2) NOT NULL DEFAULT '0.00' COMMENT '可用余额(现金+赠送金)',
|
||||
"amount" DECIMAL(10, 2) DEFAULT NULL COMMENT '现金余额',
|
||||
"gift_amount" DECIMAL(10, 2) DEFAULT NULL COMMENT '赠送余额',
|
||||
"currency" TINYINT DEFAULT NULL COMMENT '货币类型(字典)',
|
||||
"currency_unit" VARCHAR(10) DEFAULT NULL COMMENT '货币单位',
|
||||
"creator" VARCHAR(64) DEFAULT NULL COMMENT '创建者/操作人',
|
||||
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间/交易时间',
|
||||
"updater" VARCHAR(64) DEFAULT NULL COMMENT '更新者',
|
||||
"update_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
"remark" VARCHAR(255) DEFAULT NULL COMMENT '备注',
|
||||
"deleted" BIT NOT NULL DEFAULT FALSE COMMENT '是否删除 0否 1是',
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '收支明细表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "invoice_title_info"
|
||||
(
|
||||
"id" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '主键,根据ID号规则生成',
|
||||
"organ_id" BIGINT NOT NULL COMMENT '组织ID',
|
||||
"invoice_title" VARCHAR(64) NOT NULL COMMENT '发票抬头',
|
||||
"issue_type" TINYINT NOT NULL COMMENT '开具类型,0企业 1个人',
|
||||
"invoice_type" TINYINT NOT NULL DEFAULT '0' COMMENT '发票类型,0增值税普通发票 1增值税专用发票',
|
||||
"tax_number" VARCHAR(18) DEFAULT NULL COMMENT '统一社会信用代码',
|
||||
"bank_name" VARCHAR(64) DEFAULT NULL COMMENT '开户银行名称',
|
||||
"bank_account" VARCHAR(40) DEFAULT NULL COMMENT '开户银行账号',
|
||||
"registered_address" VARCHAR(64) DEFAULT NULL COMMENT '注册场所地址',
|
||||
"fixed_phone" VARCHAR(20) DEFAULT NULL COMMENT '注册固定电话',
|
||||
"email" VARCHAR(255) DEFAULT '' COMMENT '邮箱',
|
||||
"creator" VARCHAR(64) DEFAULT NULL COMMENT '创建者',
|
||||
"create_time" TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
"updater" VARCHAR(64) DEFAULT NULL COMMENT '更新者',
|
||||
"update_time" TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
"deleted" BIT DEFAULT FALSE COMMENT '是否删除,0否1是',
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '发票抬头信息表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "invoice_records"
|
||||
(
|
||||
"id" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '发票记录ID',
|
||||
"organ_id" BIGINT NOT NULL DEFAULT '0' COMMENT '组织ID',
|
||||
"organ_name" VARCHAR(30) DEFAULT NULL COMMENT '组织/发票抬头名称',
|
||||
"user_id" BIGINT NOT NULL COMMENT '发票申请人ID',
|
||||
"invoice_no" VARCHAR(32) DEFAULT NULL COMMENT '发票号',
|
||||
"purchase_ids" VARCHAR(2048) DEFAULT NULL COMMENT '购买记录id集合',
|
||||
"invoice_amount" DECIMAL(10, 2) NOT NULL DEFAULT '0.00' COMMENT '发票金额',
|
||||
"status" TINYINT NOT NULL COMMENT '发票状态 1待开票 2已开票 3开票失败',
|
||||
"invoice_attachment_path" VARCHAR(255) DEFAULT NULL COMMENT '发票附件保存路径',
|
||||
"invoice_attachment_id" BIGINT DEFAULT NULL COMMENT '发票附件文件id',
|
||||
"invoice_attachment_name" VARCHAR(255) DEFAULT NULL COMMENT '发票附件名称',
|
||||
"invoice_person" VARCHAR(64) DEFAULT NULL COMMENT '开票人',
|
||||
"invoice_person_id" BIGINT DEFAULT NULL COMMENT '开票人用户ID',
|
||||
"invoice_time" TIMESTAMP DEFAULT NULL COMMENT '开票时间',
|
||||
"invoice_title_id" BIGINT DEFAULT NULL COMMENT '抬头ID',
|
||||
"invoice_title_info" CLOB DEFAULT NULL COMMENT '抬头的信息',
|
||||
"remark" VARCHAR(1024) DEFAULT NULL COMMENT '备注',
|
||||
"creator" VARCHAR(64) DEFAULT NULL COMMENT '创建者/申请人',
|
||||
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间/申请时间',
|
||||
"updater" VARCHAR(64) DEFAULT NULL COMMENT '更新者',
|
||||
"update_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
"deleted" BIT NOT NULL DEFAULT FALSE COMMENT '是否删除 0否1是',
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '开票记录表';
|
||||
Reference in New Issue
Block a user