一、增值税的根本逻辑:进项 vs 销项
1️⃣ 基本原则
- 销项税额:销售商品或提供应税劳务时按销售额计算的增值税。
- 进项税额:购进货物、接受服务或取得资产等环节取得的增值税专用发票上注明的税额。
2️⃣ 抵扣机制
只有当进项税额与应税销售相关时,才能用来抵扣销项税。 反之,如果与非应税项目、免税项目、集体福利或个人消费相关,那部分进项税必须转出(不得抵扣)。
| 项目 | 金额 |
|---|---|
| 含税金额 | 1000 |
| 不含税金额 | 870 |
| 税额 | 130 |
✅ 情形一:该采购用于应税
例如你买的原材料用于生产销售商品。 则这张发票的进项税额 130 可以抵扣 销项税。
借:库存商品/原材料 870
借:应交税费—应交增值税(进项税额) 130
贷:银行存款/应付账款 1000
✅ 情形二:该支出用于管理或非应税项目
账务分录通常分两步:
(1) 初始入账(先认证)
借:管理费用 / 费用科目 870 借:应交税费—应交增值税(进项税额) 130 贷:银行存款/应付账款 1000
(2) 转出(不得抵扣部分)
借:应交税费—应交增值税(进项税额转出) 130
贷:应交税费—应交增值税(进项税额) 13
简化就是合并
借:管理费用 / 费用科目 870
借:应交税费—应交增值税(进项税额) 130
贷:银行存款/应付账款 1000
借:应交税费—应交增值税(进项税额转出) 130
贷:应交税费—应交增值税(进项税额) 130
二、难度提升多条明细场景
前面举得例子都是一条费用明细,现在要上难度,多条明细。
假设你收到了一张增值税专用发票,内容如下:
| 明细 | 含税金额 | 不含税金额 | 税额 | 说明 |
|---|---|---|---|---|
| 1. 原材料采购 | 500 | 435 | 65 | ✅ 用于应税销售,可抵扣 |
| 2. 办公用品 | 300 | 261 | 39 | 🚫 管理费用,不得抵扣 |
| 3. 员工福利 | 200 | 174 | 26 | 🚫 个人消费,不得抵扣 |
| 合计 | 1000 | 870 | 130 |
- 发票整体金额 1000;
- 但 税法允许拆分用途,即: 可以对同一张发票中不同用途的明细进行比例分摊与部分转出。
所以:
- 原材料那部分进项税(65)→ 可抵扣;
- 办公与福利部分进项税(39+26=65)→ 要转出。
✅ 先整张发票入账(认证进项)
借:原材料 435 借:管理费用—办公用品 261 借:职工福利费 174 借:应交税费—应交增值税(进项税额) 130 贷:银行存款/应付账款 1000
✅ 再对“不可抵扣部分”做税额转出
借:管理费用—办公用品 39 借:职工福利费 26 贷:应交税费—应交增值税(进项税额转出) 65
合并逻辑
借:原材料 435 借:管理费用—办公用品 261 借:职工福利费 174 借:应交税费—应交增值税(进项税额) 130 贷:银行存款/应付账款 1000
借:管理费用—办公用品 39 借:职工福利费 26 贷:应交税费—应交增值税(进项税额转出) 65
三、继续上难度,未税金额和税金不知道
核心公式: 明细行不含税金额 = 行含税金额 / 发票金额 * 税金
主要难点: 尾差
尾差
发票信息:含税总额 ¥1,100,税率 13%,税额合计 ¥126.55
| 明细 | 含税金额 | 未税金额 | 税额 | 尾差调整 |
|---|---|---|---|---|
| 明细1 | 350 | 309.73 | 350/1100*126.55 =40.266 约 40.27 | 0.00 |
| 明细2 | 370 | 327.43 | 370/1100*126.55=42.567 约 42.57 | 0.00 |
| 明细3 | 380 | 336.28 | 380/1100*126.55=43.717 约 43.72 | +0.01 |
| 合计 | 1,100 | 973.44 | 126.55 | — |
含税金额 = 未税金额 * (1+13%)= 1100
未税金额 = 1100 / (1+13%) = 973.45132743362831858407079646018
税金 = 1100 - 973.45(约 2 位) = 126.55
总税金 = 明细税金的和(这里不等于说明有尾插)。
126.55 != 40.27 + 42.57 + 43.72= 126.56
解决办法就是最后一条明细税额 = 126.55 - 40.27 - 42.57 = 43.71
java代码实现
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class InvoiceTaxCalculator {
static class InvoiceDetail {
String name; // 明细名称
BigDecimal withTax; // 含税金额
BigDecimal noTax; // 不含税金额
BigDecimal tax; // 税额
public InvoiceDetail(String name, BigDecimal withTax) {
this.name = name;
this.withTax = withTax;
}
@Override
public String toString() {
return String.format("%-10s 含税: %8s 未税: %8s 税额: %8s",
name,
withTax.setScale(2, RoundingMode.HALF_UP),
noTax.setScale(2, RoundingMode.HALF_UP),
tax.setScale(2, RoundingMode.HALF_UP));
}
}
/**
* 计算明细的税额和未税金额,并处理尾差
* @param details 明细列表,必须设置含税金额
* @param totalTax 发票总税额
*/
public static void calculate(List<InvoiceDetail> details, BigDecimal totalTax) {
// 1. 计算含税总额
BigDecimal totalWithTax = details.stream()
.map(d -> d.withTax)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 2. 按比例分摊税额,保留两位小数
BigDecimal sumTax = BigDecimal.ZERO;
for (int i = 0; i < details.size(); i++) {
InvoiceDetail detail = details.get(i);
if (i < details.size() - 1) {
// 非最后一条,按比例计算税额
detail.tax = totalTax.multiply(detail.withTax)
.divide(totalWithTax, 2, RoundingMode.HALF_UP);
sumTax = sumTax.add(detail.tax);
} else {
// 最后一条,税额 = 总税额 - 已分配税额(尾差处理)
detail.tax = totalTax.subtract(sumTax);
}
// 计算未税金额
detail.noTax = detail.withTax.subtract(detail.tax);
}
}
public static void main(String[] args) {
List<InvoiceDetail> details = new ArrayList<>();
details.add(new InvoiceDetail("明细1", new BigDecimal("350")));
details.add(new InvoiceDetail("明细2", new BigDecimal("370")));
details.add(new InvoiceDetail("明细3", new BigDecimal("380")));
BigDecimal totalTax = new BigDecimal("126.55");
calculate(details, totalTax);
System.out.println("=== 发票明细计算结果 ===");
for (InvoiceDetail d : details) {
System.out.println(d);
}
}
}