diff --git a/blade-service-api/blade-system-api/src/main/java/org/springblade/system/pojo/entity/InvoiceItem.java b/blade-service-api/blade-system-api/src/main/java/org/springblade/system/pojo/entity/InvoiceItem.java
new file mode 100644
index 0000000..86afaba
--- /dev/null
+++ b/blade-service-api/blade-system-api/src/main/java/org/springblade/system/pojo/entity/InvoiceItem.java
@@ -0,0 +1,56 @@
+/**
+ * BladeX Commercial License Agreement
+ * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
+ *
+ * Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
+ *
+ * 1. This software is for development use only under a valid license from BladeX.
+ *
+ * 2. Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
+ *
+ * 3. Licensees may copyright their own code but cannot use segments from this software for such purposes. Copyright of this software remains with BladeX.
+ *
+ * Using this software signifies agreement to this License, and the software must not be used for illegal purposes.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is not liable for any claims arising from secondary or illegal development.
+ *
+ * Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
+ *
+ * 1. This software is for development use only under a valid license from BladeX.
+ *
+ * 2. Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
+ *
+ * 3. Licensees may copyright their own code but cannot use segments from this software for such purposes. Copyright of this software remains with BladeX.
+ *
+ * Using this software signifies agreement to this License, and the software must not be used for illegal purposes.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is not liable for any claims arising from secondary or illegal development.
+ *
+ * Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
+ *
+ * 1. This software is for development use only under a valid license from BladeX.
+ *
+ * 2. Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
+ *
+ * 3. Licensees may copyright their own code but cannot use segments from this software for such purposes. Copyright of this software remains with BladeX.
+ *
+ * Using this software signifies agreement to this License, and the software must not be used for illegal purposes.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is not liable for any claims arising from secondary or illegal development.
+ *
+ * Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
+ *
+ * 1. This software is for development use only under a valid license from BladeX.
+ *
+ * 2. Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
+ *
+ * 3. Licensees may copyright their own code but cannot use segments from this software for such purposes. Copyright of this software remains with BladeX.
+ *
+ * Using this software signifies agreement to this License, and the software must not be used for illegal purposes.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is not liable for any claims arising from secondary or illegal development.
+ *
+ * Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
+ *
+ * 1. This software is for development use only under a valid license from BladeX.
+ *
+ * 2. Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
+ *
+ * 3. Licensees may copyright their own code but cannot use segments from this software for such purposes. Copyright of this software remains with BladeX.
+ *
+ * Using this software signifies agreement to this License, and the software must not be used for illegal purposes.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is not liable for any claims arising from secondary or illegal development.
+ *
+ * Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
+ *
+ * 1. This software is for development use only under a valid license from BladeX.
+ *
+ * 2. Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
+ *
+ * 3. Licensees may copyright their own code but cannot use segments from this software for such purposes. Copyright of this software remains with BladeX.
+ *
+ * Using this software signifies agreement to this License, and the software must not be used for illegal purposes.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is not liable for any claims arising from secondary or illegal development.
+ *
+ * Author: Chill Zhuang (bladejava@qq.com)
+ */
+package org.springblade.system.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.mapper.InvoiceItemMapper;
+import org.springblade.system.pojo.entity.InvoiceItem;
+import org.springblade.system.pojo.vo.InvoiceItemVO;
+import org.springblade.system.service.IInvoiceItemService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+
+/**
+ * 开票项目服务实现类
+ *
+ * @author Chill
+ */
+@Service
+public class InvoiceItemServiceImpl extends BaseServiceImpl
+ implements IInvoiceItemService {
+
+ private static final int SHORT_NAME_MAX_LENGTH = 100;
+ private static final int TAX_CODE_MAX_LENGTH = 30;
+ private static final int CATEGORY_NAME_MAX_LENGTH = 200;
+
+ @Override
+ public IPage selectInvoiceItemPage(IPage page, InvoiceItemVO invoiceItem) {
+ return page.setRecords(baseMapper.selectInvoiceItemPage(page, invoiceItem));
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean submit(InvoiceItem invoiceItem) {
+ prepare(invoiceItem);
+ validate(invoiceItem);
+ return saveOrUpdate(invoiceItem);
+ }
+
+ private void prepare(InvoiceItem invoiceItem) {
+ invoiceItem.setShortName(trim(invoiceItem.getShortName()));
+ invoiceItem.setTaxClassificationCode(trim(invoiceItem.getTaxClassificationCode()));
+ invoiceItem.setCategoryName(trim(invoiceItem.getCategoryName()));
+ if (Func.isEmpty(invoiceItem.getStatus())) {
+ invoiceItem.setStatus(1);
+ }
+ }
+
+ private void validate(InvoiceItem invoiceItem) {
+ if (Func.isEmpty(invoiceItem.getShortName())) throw new ServiceException("货物或服务简称不能为空");
+ if (invoiceItem.getShortName().length() > SHORT_NAME_MAX_LENGTH) throw new ServiceException("货物或服务简称不能超过100字");
+ if (Func.isEmpty(invoiceItem.getTaxClassificationCode())) throw new ServiceException("税收分类编码不能为空");
+ if (invoiceItem.getTaxClassificationCode().length() > TAX_CODE_MAX_LENGTH) throw new ServiceException("税收分类编码不能超过30字");
+ if (Func.isEmpty(invoiceItem.getCategoryName())) throw new ServiceException("商品和服务分类名称不能为空");
+ if (invoiceItem.getCategoryName().length() > CATEGORY_NAME_MAX_LENGTH) throw new ServiceException("商品和服务分类名称不能超过200字");
+ BigDecimal taxRate = invoiceItem.getDefaultTaxRate();
+ if (taxRate == null) throw new ServiceException("默认税率不能为空");
+ if (taxRate.compareTo(BigDecimal.ZERO) < 0 || taxRate.compareTo(new BigDecimal("100")) > 0) throw new ServiceException("默认税率必须在0到100之间");
+ boolean duplicate = count(Wrappers.lambdaQuery()
+ .eq(InvoiceItem::getTaxClassificationCode, invoiceItem.getTaxClassificationCode())
+ .eq(InvoiceItem::getShortName, invoiceItem.getShortName())
+ .eq(InvoiceItem::getIsDeleted, 0)
+ .ne(Func.isNotEmpty(invoiceItem.getId()), InvoiceItem::getId, invoiceItem.getId())) > 0;
+ if (duplicate) throw new ServiceException("该开票项目已存在");
+ }
+
+ private String trim(String value) {
+ return value == null ? "" : value.trim();
+ }
+
+}
diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/wrapper/InvoiceItemWrapper.java b/blade-service/blade-system/src/main/java/org/springblade/system/wrapper/InvoiceItemWrapper.java
new file mode 100644
index 0000000..beac880
--- /dev/null
+++ b/blade-service/blade-system/src/main/java/org/springblade/system/wrapper/InvoiceItemWrapper.java
@@ -0,0 +1,50 @@
+/**
+ * BladeX Commercial License Agreement
+ * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
+ *
+ * Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
+ *
+ * 1. This software is for development use only under a valid license from BladeX.
+ *
+ * 2. Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
+ *
+ * 3. Licensees may copyright their own code but cannot use segments from this software for such purposes. Copyright of this software remains with BladeX.
+ *
+ * Using this software signifies agreement to this License, and the software must not be used for illegal purposes.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is not liable for any claims arising from secondary or illegal development.
+ *