# Generated by Django 4.2.24 on 2025-09-24 06:05 from django.conf import settings from django.db import migrations, models import django.db.models.deletion import django.utils.timezone import markdownfield.models class Migration(migrations.Migration): initial = True dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('orgs', '0006_delete_providedservice'), ('contenttypes', '0002_remove_content_type_name'), ] operations = [ migrations.CreateModel( name='Customer', 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=255)), ('email', models.EmailField(blank=True, max_length=254)), ('phone', models.CharField(blank=True, max_length=64)), ('billing_address', models.TextField(blank=True)), ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customers', to='orgs.organization')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='CustomerSite', 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(blank=True, max_length=255)), ('address', models.TextField()), ('contact_name', models.CharField(blank=True, max_length=255)), ('contact_phone', models.CharField(blank=True, max_length=64)), ('contact_email', models.EmailField(blank=True, max_length=254)), ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sites', to='recycle_core.customer')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='Material', 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)), ('category', models.CharField(choices=[('Plastics', 'Plastics'), ('Metals', 'Metals'), ('Paper', 'Paper'), ('Glass', 'Glass'), ('Electronics', 'Electronics'), ('Wood', 'Wood'), ('Rubber', 'Rubber'), ('Textiles', 'Textiles'), ('Organic', 'Organic'), ('Mixed', 'Mixed')], max_length=64)), ('name', models.CharField(max_length=255)), ('code', models.CharField(blank=True, max_length=64)), ('default_unit', models.CharField(choices=[('kg', 'Kilogram'), ('lb', 'Pound'), ('pcs', 'Pieces')], default='kg', max_length=8)), ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='orgs.organization')), ], ), migrations.CreateModel( name='PickupOrder', 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)), ('status', models.CharField(choices=[('requested', 'Requested'), ('scheduled', 'Scheduled'), ('en_route', 'En Route'), ('collecting', 'Collecting'), ('at_facility', 'At Facility'), ('weighed', 'Weighed'), ('invoiced', 'Invoiced'), ('completed', 'Completed'), ('canceled', 'Canceled')], db_index=True, default='requested', max_length=16)), ('scheduled_at', models.DateTimeField(blank=True, null=True)), ('completed_at', models.DateTimeField(blank=True, null=True)), ('notes', models.TextField(blank=True)), ('assigned_driver', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_pickups', to=settings.AUTH_USER_MODEL)), ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_pickups', to=settings.AUTH_USER_MODEL)), ('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='pickup_orders', to='recycle_core.customer')), ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pickup_orders', to='orgs.organization')), ('site', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='pickup_orders', to='recycle_core.customersite')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='PriceList', 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=255)), ('currency_code', models.CharField(default='USD', max_length=8)), ('effective_from', models.DateField(blank=True, null=True)), ('effective_to', models.DateField(blank=True, null=True)), ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='price_lists', to='orgs.organization')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='ScrapListing', 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)), ('title', models.CharField(max_length=255)), ('description', models.TextField(blank=True)), ('auction_type', models.CharField(choices=[('open', 'Open'), ('sealed', 'Sealed')], default='open', max_length=16)), ('currency_code', models.CharField(default='USD', max_length=8)), ('reserve_price', models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True)), ('min_increment', models.DecimalField(blank=True, decimal_places=2, max_digits=12, null=True)), ('starts_at', models.DateTimeField(blank=True, null=True)), ('ends_at', models.DateTimeField(blank=True, null=True)), ('status', models.CharField(choices=[('draft', 'Draft'), ('open', 'Open'), ('closed', 'Closed'), ('awarded', 'Awarded'), ('canceled', 'Canceled')], db_index=True, default='draft', max_length=16)), ('is_public', models.BooleanField(default=True)), ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_listings', to=settings.AUTH_USER_MODEL)), ('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='scrap_listings', to='recycle_core.customer')), ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='scrap_listings', to='orgs.organization')), ('site', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='scrap_listings', to='recycle_core.customersite')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='WeighTicket', 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)), ('ticket_number', models.CharField(blank=True, max_length=64)), ('gross_weight', models.DecimalField(decimal_places=3, max_digits=12)), ('tare_weight', models.DecimalField(decimal_places=3, max_digits=12)), ('net_weight', models.DecimalField(decimal_places=3, max_digits=12)), ('unit', models.CharField(choices=[('kg', 'Kilogram'), ('lb', 'Pound'), ('pcs', 'Pieces')], default='kg', max_length=8)), ('recorded_at', models.DateTimeField(default=django.utils.timezone.now)), ('pickup', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='weigh_ticket', to='recycle_core.pickuporder')), ('recorded_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='weigh_tickets', to=settings.AUTH_USER_MODEL)), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='WeighLine', 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)), ('quantity', models.DecimalField(decimal_places=3, max_digits=12)), ('unit', models.CharField(choices=[('kg', 'Kilogram'), ('lb', 'Pound'), ('pcs', 'Pieces')], default='kg', max_length=8)), ('material', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='recycle_core.material')), ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lines', to='recycle_core.weighticket')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='ServiceAgreement', 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)), ('valid_from', models.DateField(blank=True, null=True)), ('valid_to', models.DateField(blank=True, null=True)), ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='agreements', to='recycle_core.customer')), ('price_list', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='agreements', to='recycle_core.pricelist')), ('site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='agreements', to='recycle_core.customersite')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='ScrapListingItem', 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)), ('quantity_estimate', models.DecimalField(decimal_places=3, max_digits=12)), ('unit', models.CharField(choices=[('kg', 'Kilogram'), ('lb', 'Pound'), ('pcs', 'Pieces')], default='kg', max_length=8)), ('listing', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='recycle_core.scraplisting')), ('material', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='recycle_core.material')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='ScrapBid', 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)), ('price_total', models.DecimalField(decimal_places=2, max_digits=14)), ('message', models.TextField(blank=True)), ('status', models.CharField(choices=[('active', 'Active'), ('retracted', 'Retracted'), ('accepted', 'Accepted'), ('rejected', 'Rejected')], default='active', max_length=16)), ('bidder_org', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='bids', to='orgs.organization')), ('bidder_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bids', to=settings.AUTH_USER_MODEL)), ('listing', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bids', to='recycle_core.scraplisting')), ], ), migrations.CreateModel( name='ScrapAward', 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)), ('notes', models.TextField(blank=True)), ('listing', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='award', to='recycle_core.scraplisting')), ('pickup', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='awards', to='recycle_core.pickuporder')), ('winning_bid', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='awards', to='recycle_core.scrapbid')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='ProvidedService', 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)), ('title', models.CharField(choices=[('Pickup & Logistics', 'Pickup & Logistics'), ('Material Sorting', 'Material Sorting'), ('Weighing & Ticketing', 'Weighing & Ticketing'), ('Invoicing & Payouts', 'Invoicing & Payouts'), ('Reporting & Analytics', 'Reporting & Analytics'), ('Marketplace & Bidding', 'Marketplace & Bidding'), ('Compliance & Audits', 'Compliance & Audits'), ('Consulting & Training', 'Consulting & Training')], max_length=100)), ('description', models.TextField()), ('body', markdownfield.models.MarkdownField(blank=True, null=True, rendered_field='body_html')), ('body_html', markdownfield.models.RenderedMarkdownField(null=True)), ('display_order', models.PositiveIntegerField(default=0)), ('is_enabled', models.BooleanField(default=True)), ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='services', to='orgs.organization')), ], options={ 'ordering': ['display_order'], }, ), migrations.CreateModel( name='PriceListItem', 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)), ('unit', models.CharField(choices=[('kg', 'Kilogram'), ('lb', 'Pound'), ('pcs', 'Pieces')], default='kg', max_length=8)), ('unit_price', models.DecimalField(decimal_places=2, max_digits=12)), ('direction', models.CharField(choices=[('buy', 'Buy from customer'), ('sell', 'Sell to customer')], default='sell', max_length=8)), ('material', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='price_items', to='recycle_core.material')), ('price_list', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='recycle_core.pricelist')), ], ), migrations.CreateModel( name='PickupItem', 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)), ('estimated_qty', models.DecimalField(blank=True, decimal_places=3, max_digits=12, null=True)), ('unit', models.CharField(choices=[('kg', 'Kilogram'), ('lb', 'Pound'), ('pcs', 'Pieces')], default='kg', max_length=8)), ('material', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='recycle_core.material')), ('pickup', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='recycle_core.pickuporder')), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='MaterialImage', 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)), ('image', models.ImageField(upload_to='materials/%Y/%m/')), ('caption', models.CharField(blank=True, max_length=255)), ('display_order', models.PositiveIntegerField(default=0)), ('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='recycle_core.material')), ], options={ 'ordering': ['display_order', 'id'], }, ), migrations.CreateModel( name='MaterialCategory', 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(choices=[('Plastics', 'Plastics'), ('Metals', 'Metals'), ('Paper', 'Paper'), ('Glass', 'Glass'), ('Electronics', 'Electronics'), ('Wood', 'Wood'), ('Rubber', 'Rubber'), ('Textiles', 'Textiles'), ('Organic', 'Organic'), ('Mixed', 'Mixed')], max_length=255)), ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_categories', to='orgs.organization')), ], ), migrations.CreateModel( name='Document', 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)), ('file', models.FileField(upload_to='documents/%Y/%m/%d/')), ('kind', models.CharField(blank=True, max_length=64)), ('object_id', models.PositiveIntegerField()), ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documents', to='orgs.organization')), ('uploaded_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], options={ 'abstract': False, }, ), migrations.AddField( model_name='customer', name='price_list', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='customers', to='recycle_core.pricelist'), ), migrations.CreateModel( name='AuditLog', 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)), ('action', models.CharField(max_length=64)), ('object_id', models.PositiveIntegerField()), ('metadata', models.JSONField(blank=True, default=dict)), ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='audit_logs', to='orgs.organization')), ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], ), migrations.CreateModel( name='ScrapListingInvite', 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)), ('invited_org', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='listing_invites', to='orgs.organization')), ('invited_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='listing_invites', to=settings.AUTH_USER_MODEL)), ('listing', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='invites', to='recycle_core.scraplisting')), ], options={ 'unique_together': {('listing', 'invited_org')}, }, ), migrations.AddIndex( model_name='scrapbid', index=models.Index(fields=['listing', 'price_total'], name='recycle_cor_listing_030b96_idx'), ), migrations.AlterUniqueTogether( name='pricelistitem', unique_together={('price_list', 'material', 'unit', 'direction')}, ), migrations.AlterUniqueTogether( name='materialcategory', unique_together={('organization', 'name')}, ), migrations.AlterUniqueTogether( name='material', unique_together={('organization', 'name')}, ), migrations.AddIndex( model_name='auditlog', index=models.Index(fields=['organization', 'created_at'], name='recycle_cor_organiz_192314_idx'), ), migrations.AddIndex( model_name='auditlog', index=models.Index(fields=['action', 'created_at'], name='recycle_cor_action_aad429_idx'), ), ]