254 lines
6.8 KiB
Markdown
254 lines
6.8 KiB
Markdown
# 发票列表查询优化建议
|
||
|
||
## 问题描述
|
||
当前发票列表查询没有关联项目表和结算表,导致无法显示项目名称、结算年份、结算季度等信息。
|
||
|
||
## 需求
|
||
发票列表需要显示以下字段:
|
||
- 项目编号 (projectCode)
|
||
- 项目名称 (projectName)
|
||
- 结算年份 (settlementYear)
|
||
- 结算季度 (settlementQuarter)
|
||
- 税率 (taxRate)
|
||
|
||
## 数据库表关系
|
||
|
||
```
|
||
biz_invoice (发票表)
|
||
|
|
||
|-- settlementId (结算ID) --> biz_settlement (结算表)
|
||
| |
|
||
| |-- projectId --> biz_project (项目表)
|
||
| |-- contractId --> biz_contract (合同表)
|
||
|
|
||
|-- contractId (合同ID) --> biz_contract (合同表)
|
||
```
|
||
|
||
## SQL 查询优化建议
|
||
|
||
### 当前查询(可能的问题)
|
||
```sql
|
||
SELECT
|
||
bi.*,
|
||
ba.attachmentCount
|
||
FROM biz_invoice bi
|
||
LEFT JOIN (
|
||
SELECT businessId, COUNT(*) as attachmentCount
|
||
FROM biz_attachment
|
||
WHERE businessType = 'invoice'
|
||
GROUP BY businessId
|
||
) ba ON bi.business_id = ba.businessId
|
||
-- 问题:缺少关联 biz_settlement 和 biz_project 表
|
||
```
|
||
|
||
### 优化后的查询
|
||
```sql
|
||
SELECT
|
||
bi.invoice_id,
|
||
bi.invoice_no,
|
||
bi.invoice_title_a,
|
||
bi.invoice_title_b,
|
||
bi.invoice_amount,
|
||
bi.settlement_id,
|
||
bi.contract_id,
|
||
bi.tax_rate,
|
||
bi.status,
|
||
bi.payment_date,
|
||
bi.payment_remark,
|
||
bi.remark,
|
||
bi.create_time,
|
||
-- 结算表字段
|
||
bs.settlement_year,
|
||
bs.settlement_quarter,
|
||
bs.settlement_quarter_name,
|
||
-- 项目表字段
|
||
bp.project_id,
|
||
bp.project_code,
|
||
bp.project_name,
|
||
-- 合同表字段
|
||
bc.contract_code,
|
||
bc.contract_name,
|
||
bc.contract_amount,
|
||
-- 附件数量
|
||
COALESCE(ba.attachment_count, 0) as attachment_count
|
||
FROM biz_invoice bi
|
||
LEFT JOIN biz_settlement bs ON bi.settlement_id = bs.settlement_id
|
||
LEFT JOIN biz_project bp ON bs.project_id = bp.project_id
|
||
LEFT JOIN biz_contract bc ON bi.contract_id = bc.contract_id
|
||
LEFT JOIN (
|
||
SELECT business_id, COUNT(*) as attachment_count
|
||
FROM biz_attachment
|
||
WHERE business_type = 'invoice'
|
||
GROUP BY business_id
|
||
) ba ON bi.invoice_id = ba.business_id
|
||
WHERE 1=1
|
||
ORDER BY bi.create_time DESC
|
||
```
|
||
|
||
## MyBatis-Plus 配置建议
|
||
|
||
如果使用 MyBatis-Plus,可以使用以下方式:
|
||
|
||
### 方案1:使用 @TableField (注解方式)
|
||
|
||
```java
|
||
public class BizInvoice {
|
||
@TableId
|
||
private Long invoiceId;
|
||
|
||
@TableField("settlement_id")
|
||
private Long settlementId;
|
||
|
||
// 以下字段不对应数据库表字段,仅用于返回前端
|
||
@TableField(exist = false)
|
||
private String projectCode;
|
||
|
||
@TableField(exist = false)
|
||
private String projectName;
|
||
|
||
@TableField(exist = false)
|
||
private String settlementYear;
|
||
|
||
@TableField(exist = false)
|
||
private String settlementQuarter;
|
||
|
||
@TableField(exist = false)
|
||
private String taxRate;
|
||
|
||
// ... 其他字段
|
||
}
|
||
```
|
||
|
||
### 方案2:使用 VO 类
|
||
|
||
创建一个 `BizInvoiceVO` 类:
|
||
|
||
```java
|
||
@Data
|
||
public class BizInvoiceVO extends BizInvoice {
|
||
private String projectCode;
|
||
private String projectName;
|
||
private String settlementYear;
|
||
private String settlementQuarter;
|
||
private String settlementQuarterName;
|
||
private String taxRate;
|
||
private String taxRateName;
|
||
private String contractCode;
|
||
private String contractName;
|
||
private BigDecimal contractAmount;
|
||
private Integer attachmentCount;
|
||
}
|
||
```
|
||
|
||
### 方案3:在 Mapper 中使用关联查询
|
||
|
||
```java
|
||
@Mapper
|
||
public interface BizInvoiceMapper extends BaseMapper<BizInvoice> {
|
||
|
||
@Select("""
|
||
SELECT
|
||
bi.*,
|
||
bs.settlement_year,
|
||
bs.settlement_quarter,
|
||
bs.settlement_quarter_name,
|
||
bp.project_code,
|
||
bp.project_name,
|
||
bc.contract_code,
|
||
bc.contract_name,
|
||
bc.contract_amount,
|
||
COALESCE(ba.attachment_count, 0) as attachment_count
|
||
FROM biz_invoice bi
|
||
LEFT JOIN biz_settlement bs ON bi.settlement_id = bs.settlement_id
|
||
LEFT JOIN biz_project bp ON bs.project_id = bp.project_id
|
||
LEFT JOIN biz_contract bc ON bi.contract_id = bc.contract_id
|
||
LEFT JOIN (
|
||
SELECT business_id, COUNT(*) as attachment_count
|
||
FROM biz_attachment
|
||
WHERE business_type = 'invoice'
|
||
GROUP BY business_id
|
||
) ba ON bi.invoice_id = ba.business_id
|
||
${ew.customSqlSegment}
|
||
""")
|
||
Page<BizInvoiceVO> selectInvoicePage(
|
||
@Param("page") Page<BizInvoiceVO> page,
|
||
@Param("ew") Wrapper<BizInvoice> queryWrapper
|
||
);
|
||
}
|
||
```
|
||
|
||
## 查询条件处理
|
||
|
||
查询时支持按以下条件筛选:
|
||
- 发票抬头(甲方) - invoice_title_a
|
||
- 发票抬头(乙方) - invoice_title_b
|
||
- 结算信息ID - settlement_id
|
||
- 发票状态 - status
|
||
|
||
```java
|
||
// 示例查询条件
|
||
QueryWrapper<BizInvoice> wrapper = new QueryWrapper<>();
|
||
wrapper.like(StringUtils.isNotBlank(params.getInvoiceTitleA()),
|
||
"invoice_title_a", params.getInvoiceTitleA())
|
||
.like(StringUtils.isNotBlank(params.getInvoiceTitleB()),
|
||
"invoice_title_b", params.getInvoiceTitleB())
|
||
.eq(params.getSettlementId() != null,
|
||
"settlement_id", params.getSettlementId())
|
||
.eq(StringUtils.isNotBlank(params.getStatus()),
|
||
"status", params.getStatus());
|
||
```
|
||
|
||
## 数据返回格式
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "查询成功",
|
||
"rows": [
|
||
{
|
||
"invoiceId": 1,
|
||
"invoiceNo": "INV2024001",
|
||
"invoiceTitleA": "甲方公司",
|
||
"invoiceTitleB": "乙方公司",
|
||
"invoiceAmount": 10000.00,
|
||
"settlementId": 10,
|
||
"projectId": 5,
|
||
"projectCode": "PRJ001",
|
||
"projectName": "某某项目",
|
||
"settlementYear": "2024",
|
||
"settlementQuarter": "1",
|
||
"taxRate": "6",
|
||
"taxRateName": "6%",
|
||
"contractId": 3,
|
||
"contractCode": "CONTRACT001",
|
||
"contractName": "服务合同",
|
||
"contractAmount": 50000.00,
|
||
"status": "0",
|
||
"paymentDate": null,
|
||
"remark": null,
|
||
"createTime": "2024-01-01 10:00:00",
|
||
"attachmentCount": 2
|
||
}
|
||
],
|
||
"total": 100
|
||
}
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **LEFT JOIN 使用**:确保使用 LEFT JOIN,避免因为没有关联数据而导致发票记录不显示
|
||
2. **字段映射**:确保数据库字段与Java实体类字段正确映射(使用下划线转驼峰)
|
||
3. **字典转换**:后端需要将字典代码转换为字典名称
|
||
- `settlementQuarter` (1,2,3,4) -> `settlementQuarterName` (第一季度,第二季度...)
|
||
- `taxRate` (6,13) -> `taxRateName` (6%,13%)
|
||
4. **性能优化**:为关联字段添加索引
|
||
- `biz_invoice.settlement_id`
|
||
- `biz_invoice.contract_id`
|
||
- `biz_settlement.project_id`
|
||
|
||
## 验证方法
|
||
|
||
1. 查看发票列表API返回的数据是否包含项目名称、结算年份、结算季度等字段
|
||
2. 确认这些字段有正确的值(不是null或空)
|
||
3. 前端列表能正确显示这些信息
|