示例成品 · 平台演示,按左边这组点选真跑出来的
直接按这套做。
## 1. 规则说人话
同一张发票是否重复,不看单号,不看报销人,只看这三个字段:
- `invoice_code`:发票代码,12位数字
- `invoice_number`:发票号码,8位数字
- `check_code`:校验码,20位数字或字母
三个字段完全一致,就判定为重复发票。
处理方式:
- 重复:整单驳回,写入 `duplicate_alerts` 表,状态为“疑似重复”
- 不重复:写入 `invoice_records` 占位,状态 `pending`
- 审批通过:`pending` 改成 `approved`
- 审批驳回/撤回:释放 `pending` 占位,避免员工以后不能重新提交
数据库加唯一约束,防止两个请求同时提交同一张发票时都通过。
---
## 2. JSON Schema 供 API 接入
### 2.1 请求体 JSON Schema
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "InvoiceDuplicateCheckRequest",
"type": "object",
"required": ["reimbursement_id", "applicant_id", "invoices"],
"properties": {
"reimbursement_id": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"applicant_id": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"invoices": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["invoice_code", "invoice_number", "check_code"],
"properties": {
"invoice_code": {
"type": "string",
"pattern": "^[0-9]{12}$"
},
"invoice_number": {
"type": "string",
"pattern": "^[0-9]{8}$"
},
"check_code": {
"type": "string",
"pattern": "^[A-Za-z0-9]{20}$"
}
}
}
}
}
}
```
说明:如果校验码确认只允许数字,把 `check_code` 的 pattern 改成 `^[0-9]{20}$`。
### 2.2 响应体 JSON Schema
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "InvoiceDuplicateCheckResponse",
"type": "object",
"required": ["allow_submit", "action", "duplicates"],
"properties": {
"allow_submit": {
"type": "boolean"
},
"action": {
"type": "string",
"enum": ["pass", "reject"]
},
"message": {
"type": "string"
},
"duplicates": {
"type": "array",
"items": {
"type": "object",
"required": ["invoice_code", "invoice_number", "check_code", "tag"],
"properties": {
"invoice_code": {
"type": "string"
},
"invoice_number": {
"type": "string"
},
"check_code": {
"type": "string"
},
"tag": {
"type": "string",
"enum": ["疑似重复"]
},
"existing_reimbursement_id": {
"type": "string"
},
"existing_applicant_id": {
"type": "string"
}
}
}
}
}
}
```
---
## 3. Flask 直接可用代码
依赖:
```bash
pip install flask flask-sqlalchemy
```
代码:
```python
import re
from datetime import datetime
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.exc import IntegrityError
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///invoice_dup.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
def normalize(s):
return (s or "").replace(" ", "").replace("\u3000", "").strip()
def is_valid_code(code):
return bool(re.fullmatch(r"\d{12}", code))
def is_valid_number(num):
return bool(re.fullmatch(r"\d{8}", num))
def is_valid_check_code(check):
# 如果校验码确认纯数字,把 [A-Za-z0-9] 改成 [0-9]
return bool(re.fullmatch(r"[A-Za-z0-9]{20}", check))
class InvoiceRecord(db.Model):
__tablename__ = "invoice_records"
id = db.Column(db.Integer, primary_key=True)
invoice_code = db.Column(db.String(12), nullable
点左边「开工 · 直接出成品」,出一份你自己的版本(文字免费)