270 lines
17 KiB
Python
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'),
|
|
),
|
|
]
|