fc / apps /invoice_recognition /models.py
jun2024's picture
Upload 2241 files
b4f2238 verified
Raw History Blame Contribute Delete
5.09 kB
"""Invoice recognition models."""
from __future__ import annotations
from typing import ClassVar
from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _
class InvoiceCategory(models.TextChoices):
"""发票类目"""
VAT_SPECIAL = "vat_special", _("增值税专用发票")
VAT_NORMAL = "vat_normal", _("增值税普通发票")
VAT_ELECTRONIC = "vat_electronic", _("增值税电子普通发票")
VEHICLE_SALES = "vehicle_sales", _("机动车销售统一发票")
TRAIN_TICKET = "train_ticket", _("火车票")
TAXI_RECEIPT = "taxi_receipt", _("出租车发票")
QUOTA_INVOICE = "quota_invoice", _("定额发票")
AIR_ITINERARY = "air_itinerary", _("飞机行程单")
TOLL_RECEIPT = "toll_receipt", _("过路费发票")
OTHER = "other", _("其他")
class InvoiceRecognitionTaskStatus(models.TextChoices):
"""发票识别任务状态"""
PENDING = "pending", _("待处理")
PROCESSING = "processing", _("处理中")
COMPLETED = "completed", _("已完成")
FAILED = "failed", _("失败")
class InvoiceRecordStatus(models.TextChoices):
"""发票记录识别状态"""
PENDING = "pending", _("待识别")
SUCCESS = "success", _("识别成功")
FAILED = "failed", _("识别失败")
class InvoiceRecognitionTask(models.Model):
"""发票识别任务。"""
id: int
name = models.CharField(max_length=255, verbose_name=_("任务名称"))
status = models.CharField(
max_length=32,
choices=InvoiceRecognitionTaskStatus.choices,
default=InvoiceRecognitionTaskStatus.PENDING,
verbose_name=_("任务状态"),
)
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="+",
verbose_name=_("创建人"),
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("创建时间"))
finished_at = models.DateTimeField(null=True, blank=True, verbose_name=_("完成时间"))
merge_config = models.JSONField(default=list, blank=True, verbose_name=_("分组合并配置"))
class Meta:
managed = False
db_table = "automation_invoicerecognitiontask"
ordering: ClassVar[list[str]] = ["-created_at"]
verbose_name = _("发票识别任务")
verbose_name_plural = _("发票识别任务")
def __str__(self) -> str:
return f"{self.name} ({self.get_status_display()})"
class InvoiceRecord(models.Model):
"""发票记录。"""
id: int
task = models.ForeignKey(
InvoiceRecognitionTask,
on_delete=models.CASCADE,
related_name="records",
verbose_name=_("所属任务"),
)
file_path = models.CharField(max_length=1024, verbose_name=_("文件路径"))
original_filename = models.CharField(max_length=255, verbose_name=_("原始文件名"))
invoice_code = models.CharField(max_length=50, blank=True, default="", verbose_name=_("发票代码"))
invoice_number = models.CharField(max_length=50, blank=True, default="", verbose_name=_("发票号码"))
invoice_date = models.DateField(null=True, blank=True, verbose_name=_("开票日期"))
amount = models.DecimalField(
max_digits=12,
decimal_places=2,
null=True,
blank=True,
verbose_name=_("金额(不含税)"),
)
tax_amount = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True, verbose_name=_("税额"))
total_amount = models.DecimalField(
max_digits=12,
decimal_places=2,
null=True,
blank=True,
verbose_name=_("价税合计"),
)
buyer_name = models.CharField(max_length=255, blank=True, default="", verbose_name=_("购买方名称"))
seller_name = models.CharField(max_length=255, blank=True, default="", verbose_name=_("销售方名称"))
project_name = models.CharField(max_length=255, blank=True, default="", verbose_name=_("项目名称"))
category = models.CharField(
max_length=32,
choices=InvoiceCategory.choices,
default=InvoiceCategory.OTHER,
verbose_name=_("发票类目"),
)
raw_text = models.TextField(blank=True, default="", verbose_name=_("OCR 原始文本"))
is_duplicate = models.BooleanField(default=False, verbose_name=_("是否重复"))
duplicate_of_id = models.IntegerField(null=True, blank=True, verbose_name=_("重复的原始记录ID"))
status = models.CharField(
max_length=32,
choices=InvoiceRecordStatus.choices,
default=InvoiceRecordStatus.PENDING,
verbose_name=_("识别状态"),
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("创建时间"))
class Meta:
managed = False
db_table = "automation_invoicerecord"
verbose_name = _("发票记录")
verbose_name_plural = _("发票记录")
def __str__(self) -> str:
return f"{self.original_filename} ({self.get_status_display()})"