Files
2026-10-06 10:03:22 +03:30

270 lines
17 KiB
Python

# Generated by Django 5.1.1 on 2026-10-05 10:44
import apps.payments.models
import django.db.models.deletion
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('notifications', '0017_alter_smstemplate_event_type'),
('staff', '0012_organizationalunit_supervisor_mobile_5'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='BankInstitution',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('code', models.SlugField(unique=True)),
('name', models.CharField(max_length=100)),
('is_active', models.BooleanField(default=True)),
('historical', models.BooleanField(default=False)),
],
options={
'ordering': ['historical', 'name'],
},
),
migrations.CreateModel(
name='PaymentAccessConfiguration',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('singleton', models.PositiveSmallIntegerField(default=1, editable=False, unique=True)),
('open_view', models.BooleanField(default=True, verbose_name='مشاهده برای همه کارشناسان فعال')),
('open_create', models.BooleanField(default=True, verbose_name='ایجاد برای همه کارشناسان فعال')),
],
options={
'permissions': [('manage_payment_access', 'Manage payment access')],
},
),
migrations.CreateModel(
name='CompanyBankAccount',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('public_id', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
('name', models.CharField(max_length=120, verbose_name='نام نمایشی حساب')),
('holder', models.CharField(max_length=150, verbose_name='صاحب حساب')),
('account_number', models.CharField(blank=True, max_length=40, verbose_name='شماره حساب')),
('iban', models.CharField(blank=True, max_length=26, verbose_name='شبا')),
('card_number', models.CharField(blank=True, max_length=16, verbose_name='شماره کارت')),
('requires_deposit_id', models.BooleanField(default=False, verbose_name='شناسه واریز الزامی')),
('is_active', models.BooleanField(default=True, verbose_name='فعال کلی')),
('available_to_staff', models.BooleanField(default=True, verbose_name='قابل انتخاب کارشناسان')),
('available_to_customers', models.BooleanField(default=True, verbose_name='قابل انتخاب مشتریان')),
('sort_order', models.PositiveIntegerField(default=0)),
('bank', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='payments.bankinstitution', verbose_name='بانک')),
],
options={
'ordering': ['sort_order', 'name', 'pk'],
'permissions': [('manage_company_bankaccounts', 'Manage company bank accounts')],
},
),
migrations.CreateModel(
name='PaymentAuditEvent',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('actor_name', models.CharField(max_length=150)),
('action', models.CharField(max_length=50)),
('object_type', models.CharField(max_length=50)),
('object_id', models.CharField(max_length=64)),
('details', models.JSONField(default=dict)),
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
('actor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ['-created_at', '-pk'],
'permissions': [('view_payment_audit', 'View financial audit')],
},
),
migrations.CreateModel(
name='PaymentNotice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('public_id', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
('account_snapshot', models.JSONField()),
('subject', models.CharField(max_length=200)),
('amount', models.BigIntegerField()),
('deposit_id', models.CharField(blank=True, max_length=100)),
('invoice_number', models.CharField(blank=True, max_length=100)),
('description', models.TextField(blank=True)),
('cancelled_at', models.DateTimeField(blank=True, null=True)),
('account', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='payments.companybankaccount')),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='issued_payment_notices', to=settings.AUTH_USER_MODEL)),
('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='payment_notices', to=settings.AUTH_USER_MODEL)),
('owning_unit', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='staff.organizationalunit')),
],
options={
'ordering': ['-created_at', '-pk'],
},
),
migrations.CreateModel(
name='PaymentNotification',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('context', models.JSONField()),
('rendered_body', models.TextField(blank=True)),
('template_snapshot', models.JSONField(default=dict)),
('job', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='payment_notification', to='notifications.notificationjob')),
('notice', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='payments.paymentnotice')),
('unit', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='staff.organizationalunit')),
],
),
migrations.CreateModel(
name='PaymentNotificationAttempt',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('started_at', models.DateTimeField(auto_now_add=True)),
('finished_at', models.DateTimeField(null=True)),
('success', models.BooleanField(null=True)),
('provider_code', models.CharField(blank=True, max_length=50)),
('provider_id', models.CharField(blank=True, max_length=500)),
('error', models.TextField(blank=True)),
('notification', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='attempt_log', to='payments.paymentnotification')),
],
),
migrations.CreateModel(
name='PaymentReceipt',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('public_id', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
('status', models.CharField(choices=[('PENDING', 'در انتظار بررسی'), ('PARTIAL', 'تأیید ناقص'), ('APPROVED', 'تأیید شده'), ('REJECTED', 'رد شده')], db_index=True, default='PENDING', max_length=12)),
('submission_key', models.UUIDField(unique=True)),
('current_version', models.PositiveIntegerField(default=1)),
('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='payment_receipts', to=settings.AUTH_USER_MODEL)),
('notice', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='receipts', to='payments.paymentnotice')),
('owning_unit', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='staff.organizationalunit')),
('submitted_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='submitted_payment_receipts', to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ['-created_at', '-pk'],
'permissions': [('approve_paymentreceipt', 'Approve payment receipt'), ('senior_approve_paymentreceipt', 'Senior final approval'), ('submit_customer_receipt', 'Submit receipt for customer'), ('view_all_payments', 'View payments across units')],
},
),
migrations.CreateModel(
name='PaymentReceiptRevision',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('version', models.PositiveIntegerField()),
('amount', models.BigIntegerField()),
('paid_date', models.DateField()),
('account_snapshot', models.JSONField()),
('origin_other', models.CharField(blank=True, max_length=100)),
('deposit_id', models.CharField(blank=True, max_length=100)),
('tracking_number', models.CharField(blank=True, max_length=100)),
('description', models.TextField(blank=True)),
('destination_mismatch', models.BooleanField(default=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('image', models.FileField(max_length=500, upload_to=apps.payments.models.receipt_path)),
('mime_type', models.CharField(max_length=100)),
('sha256', models.CharField(max_length=64)),
('original_name', models.CharField(max_length=255)),
('file_size', models.PositiveBigIntegerField()),
('destination', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='payments.companybankaccount')),
('origin_bank', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='payments.bankinstitution')),
('receipt', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='revisions', to='payments.paymentreceipt')),
],
),
migrations.CreateModel(
name='ReceiptApprovalCycle',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('policy_snapshot', models.JSONField(default=dict)),
('status', models.CharField(choices=[('PENDING', 'در انتظار بررسی'), ('PARTIAL', 'تأیید ناقص'), ('APPROVED', 'تأیید شده'), ('REJECTED', 'رد شده')], default='PENDING', max_length=12)),
('finalized_at', models.DateTimeField(blank=True, null=True)),
('finalized_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
('revision', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='cycle', to='payments.paymentreceiptrevision')),
],
),
migrations.CreateModel(
name='ReceiptApprovalAssignment',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_senior', models.BooleanField(default=False)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
('cycle', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='assignments', to='payments.receiptapprovalcycle')),
],
),
migrations.AddField(
model_name='paymentnotification',
name='cycle',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='payments.receiptapprovalcycle'),
),
migrations.CreateModel(
name='ReceiptDecision',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('action', models.CharField(choices=[('APPROVE', 'تأیید'), ('REJECT', 'رد'), ('SENIOR_APPROVE', 'تأیید ارشد')], max_length=20)),
('reason', models.TextField(blank=True)),
('actor_name', models.CharField(max_length=150)),
('created_at', models.DateTimeField(auto_now_add=True)),
('cycle', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='decisions', to='payments.receiptapprovalcycle')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='PaymentApprovalPolicy',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=100, verbose_name='عنوان سیاست')),
('is_active', models.BooleanField(default=True)),
('reviewers', models.ManyToManyField(related_name='payment_review_policies', to=settings.AUTH_USER_MODEL, verbose_name='افراد الزامی تأیید')),
('seniors', models.ManyToManyField(blank=True, related_name='payment_senior_policies', to=settings.AUTH_USER_MODEL, verbose_name='تأییدکنندگان ارشد')),
('unit', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='staff.organizationalunit', verbose_name='واحد (خالی: عمومی)')),
],
options={
'permissions': [('manage_payment_approval_policy', 'Manage payment approval policy')],
'constraints': [models.UniqueConstraint(condition=models.Q(('is_active', True), ('unit__isnull', False)), fields=('unit',), name='pay_active_unit_policy'), models.UniqueConstraint(condition=models.Q(('is_active', True), ('unit__isnull', True)), fields=('is_active',), name='pay_active_global_policy')],
},
),
migrations.AddIndex(
model_name='paymentnotice',
index=models.Index(fields=['customer', '-created_at'], name='payments_pa_custome_bc6e3f_idx'),
),
migrations.AddIndex(
model_name='paymentnotice',
index=models.Index(fields=['owning_unit', '-created_at'], name='payments_pa_owning__f2b6af_idx'),
),
migrations.AddConstraint(
model_name='paymentnotice',
constraint=models.CheckConstraint(condition=models.Q(('amount__gt', 0), ('amount__lte', 9007199254740991)), name='pay_notice_amount'),
),
migrations.AddIndex(
model_name='paymentreceipt',
index=models.Index(fields=['customer', '-created_at'], name='payments_pa_custome_e266cc_idx'),
),
migrations.AddIndex(
model_name='paymentreceipt',
index=models.Index(fields=['status', '-created_at'], name='payments_pa_status_5cd50b_idx'),
),
migrations.AddConstraint(
model_name='paymentreceiptrevision',
constraint=models.UniqueConstraint(fields=('receipt', 'version'), name='pay_receipt_revision'),
),
migrations.AddConstraint(
model_name='paymentreceiptrevision',
constraint=models.CheckConstraint(condition=models.Q(('amount__gt', 0), ('amount__lte', 9007199254740991)), name='pay_receipt_amount'),
),
migrations.AddConstraint(
model_name='receiptapprovalassignment',
constraint=models.UniqueConstraint(fields=('cycle', 'user', 'is_senior'), name='pay_cycle_assignment'),
),
migrations.AddConstraint(
model_name='receiptdecision',
constraint=models.UniqueConstraint(fields=('cycle', 'user'), name='pay_one_vote_per_user'),
),
]