You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
230 lines
15 KiB
230 lines
15 KiB
# Generated by Django 5.2.17 on 2026-09-06 19:02 |
|
|
|
import django.core.validators |
|
import django.db.models.deletion |
|
import uuid |
|
from django.db import migrations, models |
|
|
|
|
|
class Migration(migrations.Migration): |
|
|
|
initial = True |
|
|
|
dependencies = [ |
|
] |
|
|
|
operations = [ |
|
migrations.CreateModel( |
|
name='Account', |
|
fields=[ |
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), |
|
('created_at', models.DateTimeField(auto_now_add=True)), |
|
('updated_at', models.DateTimeField(auto_now=True)), |
|
('name', models.CharField(max_length=255, unique=True)), |
|
('kind', models.CharField(choices=[('BANK', 'Bank'), ('CREDIT_CARD', 'Credit card')], max_length=16)), |
|
('currency', models.CharField(default='BRL', max_length=3, validators=[django.core.validators.RegexValidator('\\A[A-Z]{3}\\Z', 'Use three uppercase ASCII letters.')])), |
|
('archived', models.BooleanField(default=False)), |
|
], |
|
options={ |
|
'constraints': [models.CheckConstraint(condition=models.Q(('kind__in', ['BANK', 'CREDIT_CARD'])), name='account_valid_kind'), models.CheckConstraint(condition=models.Q(('currency__regex', '^[A-Z]{3}$')), name='account_valid_currency'), models.CheckConstraint(condition=models.Q(('name__regex', '\\S')), name='account_nonblank_name')], |
|
}, |
|
), |
|
migrations.CreateModel( |
|
name='AuditEvent', |
|
fields=[ |
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), |
|
('created_at', models.DateTimeField(auto_now_add=True)), |
|
('actor_kind', models.CharField(choices=[('HUMAN', 'Human'), ('APPLICATION', 'Application'), ('AGENT', 'Agent')], max_length=16)), |
|
('actor_identifier', models.CharField(max_length=255)), |
|
('operation', models.CharField(max_length=128)), |
|
('target_id', models.UUIDField(blank=True, null=True)), |
|
('outcome', models.CharField(choices=[('SUCCESS', 'Success'), ('FAILURE', 'Failure')], max_length=16)), |
|
('changed_fields', models.JSONField(blank=True, default=list)), |
|
('error_code', models.CharField(blank=True, max_length=128)), |
|
], |
|
options={ |
|
'constraints': [models.CheckConstraint(condition=models.Q(('actor_kind__in', ['HUMAN', 'APPLICATION', 'AGENT'])), name='audit_valid_actor'), models.CheckConstraint(condition=models.Q(('outcome__in', ['SUCCESS', 'FAILURE'])), name='audit_valid_outcome'), models.CheckConstraint(condition=models.Q(('actor_identifier__regex', '\\S')), name='audit_nonblank_actor'), models.CheckConstraint(condition=models.Q(('operation__regex', '\\S')), name='audit_nonblank_operation')], |
|
}, |
|
), |
|
migrations.CreateModel( |
|
name='CardStatement', |
|
fields=[ |
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), |
|
('created_at', models.DateTimeField(auto_now_add=True)), |
|
('updated_at', models.DateTimeField(auto_now=True)), |
|
('period_start', models.DateField()), |
|
('period_end', models.DateField()), |
|
('due_date', models.DateField()), |
|
('statement_balance', models.DecimalField(blank=True, decimal_places=2, max_digits=18, null=True)), |
|
('account', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='statements', to='finance.account')), |
|
], |
|
), |
|
migrations.CreateModel( |
|
name='Category', |
|
fields=[ |
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), |
|
('created_at', models.DateTimeField(auto_now_add=True)), |
|
('updated_at', models.DateTimeField(auto_now=True)), |
|
('name', models.CharField(max_length=255, unique=True)), |
|
('kind', models.CharField(choices=[('INCOME', 'Income'), ('EXPENSE', 'Expense')], max_length=16)), |
|
('archived', models.BooleanField(default=False)), |
|
], |
|
options={ |
|
'constraints': [models.CheckConstraint(condition=models.Q(('kind__in', ['INCOME', 'EXPENSE'])), name='category_valid_kind'), models.CheckConstraint(condition=models.Q(('name__regex', '\\S')), name='category_nonblank_name')], |
|
}, |
|
), |
|
migrations.CreateModel( |
|
name='InstallmentPlan', |
|
fields=[ |
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), |
|
('created_at', models.DateTimeField(auto_now_add=True)), |
|
('updated_at', models.DateTimeField(auto_now=True)), |
|
('description', models.TextField(blank=True)), |
|
('total_installments', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1)])), |
|
('account', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='installment_plans', to='finance.account')), |
|
], |
|
), |
|
migrations.CreateModel( |
|
name='Payee', |
|
fields=[ |
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), |
|
('created_at', models.DateTimeField(auto_now_add=True)), |
|
('updated_at', models.DateTimeField(auto_now=True)), |
|
('name', models.CharField(max_length=255, unique=True)), |
|
('archived', models.BooleanField(default=False)), |
|
], |
|
options={ |
|
'constraints': [models.CheckConstraint(condition=models.Q(('name__regex', '\\S')), name='payee_nonblank_name')], |
|
}, |
|
), |
|
migrations.CreateModel( |
|
name='Transaction', |
|
fields=[ |
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), |
|
('created_at', models.DateTimeField(auto_now_add=True)), |
|
('updated_at', models.DateTimeField(auto_now=True)), |
|
('amount', models.DecimalField(decimal_places=2, max_digits=18)), |
|
('posting_date', models.DateField()), |
|
('occurrence_date', models.DateField(blank=True, null=True)), |
|
('description', models.TextField(blank=True)), |
|
('kind', models.CharField(choices=[('INCOME', 'Income'), ('EXPENSE', 'Expense'), ('TRANSFER', 'Transfer'), ('REFUND', 'Refund'), ('OPENING', 'Opening')], max_length=16)), |
|
('installment_number', models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)])), |
|
('account', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='finance.account')), |
|
('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='finance.category')), |
|
('installment_plan', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='finance.installmentplan')), |
|
('payee', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='finance.payee')), |
|
('refund_of', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='refunds', to='finance.transaction')), |
|
('statement', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='finance.cardstatement')), |
|
], |
|
), |
|
migrations.CreateModel( |
|
name='SourceRecord', |
|
fields=[ |
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), |
|
('created_at', models.DateTimeField(auto_now_add=True)), |
|
('document_hash', models.CharField(max_length=64, validators=[django.core.validators.RegexValidator('\\A[0-9a-f]{64}\\Z', 'Use a lowercase SHA-256 hexadecimal digest.')])), |
|
('source_format', models.CharField(choices=[('BANK_CSV', 'Bank CSV'), ('OUROCARD_TXT', 'Ourocard TXT')], max_length=16)), |
|
('parser_version', models.CharField(max_length=128)), |
|
('item_locator', models.CharField(max_length=255)), |
|
('transaction', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='source_records', to='finance.transaction')), |
|
], |
|
), |
|
migrations.CreateModel( |
|
name='Transfer', |
|
fields=[ |
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), |
|
('created_at', models.DateTimeField(auto_now_add=True)), |
|
('updated_at', models.DateTimeField(auto_now=True)), |
|
('incoming', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='incoming_transfer', to='finance.transaction')), |
|
('outgoing', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='outgoing_transfer', to='finance.transaction')), |
|
], |
|
), |
|
migrations.AddConstraint( |
|
model_name='cardstatement', |
|
constraint=models.CheckConstraint(condition=models.Q(('period_end__gte', models.F('period_start'))), name='statement_period_order'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='cardstatement', |
|
constraint=models.CheckConstraint(condition=models.Q(('due_date__gte', models.F('period_end'))), name='statement_due_order'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='cardstatement', |
|
constraint=models.UniqueConstraint(fields=('account', 'period_end'), name='statement_account_period_unique'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='installmentplan', |
|
constraint=models.CheckConstraint(condition=models.Q(('total_installments__gt', 0)), name='plan_positive_total'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(('kind__in', ['INCOME', 'EXPENSE', 'TRANSFER', 'REFUND', 'OPENING'])), name='transaction_valid_kind'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(('amount', 0), _negated=True), name='transaction_nonzero_amount'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(models.Q(('amount__gt', 0), ('kind__in', ['INCOME', 'REFUND'])), models.Q(('amount__lt', 0), ('kind', 'EXPENSE')), ('kind__in', ['TRANSFER', 'OPENING']), _connector='OR'), name='transaction_kind_sign'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.UniqueConstraint(condition=models.Q(('kind', 'OPENING')), fields=('account',), name='transaction_one_opening'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(models.Q(('kind', 'OPENING'), _negated=True), models.Q(('category__isnull', True), ('installment_number__isnull', True), ('installment_plan__isnull', True), ('payee__isnull', True), ('refund_of__isnull', True), ('statement__isnull', True)), _connector='OR'), name='transaction_opening_unassociated'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(models.Q(('kind', 'TRANSFER'), _negated=True), models.Q(('category__isnull', True), ('installment_number__isnull', True), ('installment_plan__isnull', True), ('refund_of__isnull', True)), _connector='OR'), name='transaction_transfer_unclassified'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(('refund_of__isnull', True), ('kind', 'REFUND'), _connector='OR'), name='transaction_refund_link_kind'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(('refund_of__isnull', True), models.Q(('refund_of', models.F('id')), _negated=True), _connector='OR'), name='transaction_refund_not_self'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(models.Q(('installment_number__isnull', True), ('installment_plan__isnull', True)), models.Q(('installment_number__isnull', False), ('installment_plan__isnull', False)), _connector='OR'), name='transaction_installment_pair'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(('installment_number__isnull', True), ('installment_number__gt', 0), _connector='OR'), name='transaction_installment_positive'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.CheckConstraint(condition=models.Q(('installment_plan__isnull', True), ('kind', 'EXPENSE'), _connector='OR'), name='transaction_installment_expense'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transaction', |
|
constraint=models.UniqueConstraint(condition=models.Q(('installment_plan__isnull', False)), fields=('installment_plan', 'installment_number'), name='transaction_installment_unique'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='sourcerecord', |
|
constraint=models.CheckConstraint(condition=models.Q(('source_format__in', ['BANK_CSV', 'OUROCARD_TXT'])), name='source_valid_format'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='sourcerecord', |
|
constraint=models.CheckConstraint(condition=models.Q(('document_hash__regex', '^[0-9a-f]{64}$')), name='source_valid_hash'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='sourcerecord', |
|
constraint=models.CheckConstraint(condition=models.Q(('parser_version__regex', '\\S')), name='source_nonblank_parser'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='sourcerecord', |
|
constraint=models.CheckConstraint(condition=models.Q(('item_locator__regex', '\\S')), name='source_nonblank_locator'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='sourcerecord', |
|
constraint=models.UniqueConstraint(fields=('document_hash', 'item_locator'), name='source_document_item_unique'), |
|
), |
|
migrations.AddConstraint( |
|
model_name='transfer', |
|
constraint=models.CheckConstraint(condition=models.Q(('outgoing', models.F('incoming')), _negated=True), name='transfer_distinct_legs'), |
|
), |
|
]
|
|
|