Django 6 + DRF resource server against the Gooyal accounts OAuth2 service, matching the Winsoo ecosystem's conventions. Covers locations, stores, catalog, cart, checkout/orders (with the multi-store-cart split and the status stepper), reviews, and notifications, plus a demo-data seed command. Payment integration (wallet debits, online gateway, seller payouts) is intentionally left out here — see feature/payment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
156 lines
9.3 KiB
Python
156 lines
9.3 KiB
Python
# Generated by Django 6.0.2 on 2026-08-10 10:30
|
||
|
||
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 = [
|
||
('catalog', '0001_initial'),
|
||
('stores', '0001_initial'),
|
||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||
]
|
||
|
||
operations = [
|
||
migrations.CreateModel(
|
||
name='Cart',
|
||
fields=[
|
||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True)),
|
||
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
|
||
('updated_at', models.DateTimeField(auto_now=True, db_index=True)),
|
||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='cart', to=settings.AUTH_USER_MODEL)),
|
||
],
|
||
options={
|
||
'verbose_name': 'سبد خرید',
|
||
'verbose_name_plural': 'سبدهای خرید',
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name='Order',
|
||
fields=[
|
||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True)),
|
||
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
|
||
('updated_at', models.DateTimeField(auto_now=True, db_index=True)),
|
||
('status', models.CharField(choices=[('placed', 'سفارش ثبت شد'), ('preparing', 'در حال آماده\u200cسازی'), ('ready_to_ship', 'آماده ارسال'), ('handed_to_courier', 'تحویل سفیر شد'), ('delivered', 'تحویل داده شد'), ('cancelled', 'لغو شده')], default='placed', max_length=20)),
|
||
('items_subtotal', models.PositiveBigIntegerField()),
|
||
('delivery_fee', models.PositiveBigIntegerField(default=0)),
|
||
('commission_amount', models.PositiveBigIntegerField(default=0)),
|
||
('seller_payout_amount', models.PositiveBigIntegerField(default=0)),
|
||
('cancel_reason', models.TextField(blank=True)),
|
||
('courier_name', models.CharField(blank=True, max_length=150)),
|
||
('courier_phone', models.CharField(blank=True, max_length=20)),
|
||
('placed_at', models.DateTimeField(auto_now_add=True)),
|
||
('delivered_at', models.DateTimeField(blank=True, null=True)),
|
||
('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='orders', to=settings.AUTH_USER_MODEL)),
|
||
('store', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='orders', to='stores.store')),
|
||
],
|
||
options={
|
||
'verbose_name': 'سفارش',
|
||
'verbose_name_plural': 'سفارش\u200cها',
|
||
'ordering': ['-created_at'],
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name='Notification',
|
||
fields=[
|
||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True)),
|
||
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
|
||
('updated_at', models.DateTimeField(auto_now=True, db_index=True)),
|
||
('type', models.CharField(choices=[('new_order', 'سفارش جدید'), ('settlement_done', 'تسویه حساب'), ('new_review', 'نظر جدید'), ('order_cancelled', 'لغو سفارش')], max_length=20)),
|
||
('title', models.CharField(max_length=200)),
|
||
('body', models.TextField(blank=True)),
|
||
('is_read', models.BooleanField(default=False)),
|
||
('recipient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notifications', to=settings.AUTH_USER_MODEL)),
|
||
('related_order', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='notifications', to='orders.order')),
|
||
],
|
||
options={
|
||
'verbose_name': 'اعلان',
|
||
'verbose_name_plural': 'اعلان\u200cها',
|
||
'ordering': ['-created_at'],
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name='OrderGroup',
|
||
fields=[
|
||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True)),
|
||
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
|
||
('updated_at', models.DateTimeField(auto_now=True, db_index=True)),
|
||
('recipient_name', models.CharField(max_length=150)),
|
||
('recipient_phone', models.CharField(max_length=20)),
|
||
('full_address', models.TextField()),
|
||
('delivery_type', models.CharField(choices=[('express', 'ارسال فوری'), ('scheduled', 'زمان\u200cبندی شده')], default='express', max_length=10)),
|
||
('scheduled_at', models.DateTimeField(blank=True, null=True)),
|
||
('payment_method', models.CharField(choices=[('wallet', 'کیف پول وینسو'), ('online', 'درگاه بانکی'), ('cash_on_delivery', 'پرداخت در محل')], max_length=20)),
|
||
('payment_status', models.CharField(choices=[('pending', 'در انتظار پرداخت'), ('paid', 'پرداخت شده'), ('failed', 'ناموفق')], default='pending', max_length=10)),
|
||
('notes', models.TextField(blank=True)),
|
||
('total_amount', models.PositiveBigIntegerField()),
|
||
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='order_groups', to=settings.AUTH_USER_MODEL)),
|
||
],
|
||
options={
|
||
'verbose_name': 'گروه سفارش',
|
||
'verbose_name_plural': 'گروه\u200cهای سفارش',
|
||
'ordering': ['-created_at'],
|
||
},
|
||
),
|
||
migrations.AddField(
|
||
model_name='order',
|
||
name='group',
|
||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='orders', to='orders.ordergroup'),
|
||
),
|
||
migrations.CreateModel(
|
||
name='OrderItem',
|
||
fields=[
|
||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True)),
|
||
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
|
||
('updated_at', models.DateTimeField(auto_now=True, db_index=True)),
|
||
('product_name_snapshot', models.CharField(max_length=200)),
|
||
('unit_price_snapshot', models.PositiveBigIntegerField()),
|
||
('quantity', models.PositiveIntegerField()),
|
||
('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='orders.order')),
|
||
('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='catalog.product')),
|
||
],
|
||
options={
|
||
'verbose_name': 'قلم سفارش',
|
||
'verbose_name_plural': 'اقلام سفارش',
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name='OrderStatusLog',
|
||
fields=[
|
||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True)),
|
||
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
|
||
('updated_at', models.DateTimeField(auto_now=True, db_index=True)),
|
||
('from_status', models.CharField(blank=True, max_length=20)),
|
||
('to_status', models.CharField(max_length=20)),
|
||
('note', models.TextField(blank=True)),
|
||
('changed_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||
('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='status_logs', to='orders.order')),
|
||
],
|
||
options={
|
||
'verbose_name': 'تاریخچه وضعیت سفارش',
|
||
'verbose_name_plural': 'تاریخچه وضعیت سفارش\u200cها',
|
||
'ordering': ['created_at'],
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name='CartItem',
|
||
fields=[
|
||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True)),
|
||
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
|
||
('updated_at', models.DateTimeField(auto_now=True, db_index=True)),
|
||
('quantity', models.PositiveIntegerField(default=1)),
|
||
('cart', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='orders.cart')),
|
||
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='catalog.product')),
|
||
],
|
||
options={
|
||
'verbose_name': 'قلم سبد خرید',
|
||
'verbose_name_plural': 'اقلام سبد خرید',
|
||
'unique_together': {('cart', 'product')},
|
||
},
|
||
),
|
||
]
|