# Generated by Django 5.2.11 on 2026-02-07 01:16

import django.core.validators
import django.db.models.deletion
import modelsearch.index
import taggit.managers
import uuid
import wagtail.fields
import wagtail.models.preview
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ('auth', '0012_alter_user_first_name_max_length'),
        ('contenttypes', '0002_remove_content_type_name'),
        ('wagtailcore', '0096_referenceindex_referenceindex_source_object_and_more'),
        ('wagtailimages', '0027_image_description'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='TemplateVariable',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
                ('name', models.CharField(help_text='Name used in templates as {{ variable_name }}', max_length=50, verbose_name='Variable Name')),
                ('description', models.CharField(help_text='What this variable represents', max_length=200, verbose_name='Description')),
                ('default_value', models.CharField(blank=True, help_text='Default value if not provided in context', max_length=200, verbose_name='Default Value')),
                ('is_required', models.BooleanField(default=False, help_text='This variable must be provided in context', verbose_name='Required')),
                ('variable_type', models.CharField(choices=[('text', 'Text'), ('url', 'URL'), ('email', 'Email'), ('date', 'Date'), ('number', 'Number'), ('boolean', 'Boolean'), ('color', 'Color'), ('image', 'Image'), ('file', 'File')], default='text', max_length=20, verbose_name='Type')),
                ('validation_regex', models.CharField(blank=True, help_text='Regular expression for validating this variable (optional)', max_length=200, verbose_name='Validation Regex')),
            ],
            options={
                'verbose_name': 'Template Variable',
                'verbose_name_plural': 'Template Variables',
                'ordering': ['name'],
            },
        ),
        migrations.CreateModel(
            name='EmailSettings',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('default_from_email', models.EmailField(default='noreply@example.com', max_length=254, verbose_name='Default From Email')),
                ('default_from_name', models.CharField(default='CTC Hub', max_length=100, verbose_name='Default From Name')),
                ('enable_tracking', models.BooleanField(default=True, help_text='Track email opens and clicks in newsletters.', verbose_name='Enable Tracking')),
                ('use_marketing_consent', models.BooleanField(default=True, help_text='Only send newsletters to users who opted in.', verbose_name='Require Marketing Consent')),
                ('max_daily_emails', models.PositiveIntegerField(default=1000, help_text='Maximum number of emails that can be sent per day.', verbose_name='Max Daily Emails')),
                ('batch_size', models.PositiveIntegerField(default=100, help_text='Emails per sending batch.', verbose_name='Batch Size')),
                ('smtp_server', models.CharField(blank=True, help_text='Optional custom SMTP host for sending.', max_length=255, verbose_name='SMTP Server')),
                ('analytics_provider', models.CharField(blank=True, help_text='Optional service for email analytics (e.g., Mailchimp, Sendgrid).', max_length=255, verbose_name='Analytics Provider')),
                ('language', models.CharField(choices=[('en', 'English'), ('fr', 'French'), ('de', 'German'), ('es', 'Spanish'), ('ar', 'العربيّة')], default='en', help_text="Language code for these settings (e.g., 'en', 'fr').", max_length=10, verbose_name='Language Code')),
                ('active', models.BooleanField(default=False, help_text='Designates whether these settings are active for this language. Only one active per language.', verbose_name='Active')),
            ],
            options={
                'verbose_name': 'Email Settings',
                'verbose_name_plural': 'Email Settings',
                'constraints': [models.UniqueConstraint(condition=models.Q(('active', True)), fields=('language',), name='unique_active_email_settings_per_language')],
            },
        ),
        migrations.CreateModel(
            name='EmailTemplate',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
                ('live', models.BooleanField(default=True, help_text='Whether this record is publicly accessible', verbose_name='Live')),
                ('first_published_at', models.DateTimeField(blank=True, null=True, verbose_name='First Published At')),
                ('last_published_at', models.DateTimeField(blank=True, null=True, verbose_name='Last Published At')),
                ('search_description', models.TextField(blank=True, help_text='Description for search engines and social sharing', verbose_name='Search description')),
                ('name', models.CharField(help_text="Name for internal reference, e.g., 'Default Newsletter Template'.", max_length=150, verbose_name='Template Name')),
                ('description', models.TextField(blank=True, help_text='Optional description of this email template.', verbose_name='Description')),
                ('go_live_at', models.DateTimeField(blank=True, help_text='Schedule the template to become active at this date/time.', null=True, verbose_name='Go live at')),
                ('expire_at', models.DateTimeField(blank=True, help_text='Schedule the template to expire at this date/time.', null=True, verbose_name='Expire at')),
                ('template_source', models.CharField(choices=[('inline', 'Inline Content'), ('file', 'Uploaded Files'), ('path', 'Template Path'), ('external', 'External URL')], default='inline', help_text='Where the template content comes from.', max_length=20, verbose_name='Template Source')),
                ('template_path', models.CharField(blank=True, help_text="Django template path (e.g., 'emails/newsletter.html'). Used when template source is 'path'.", max_length=255, verbose_name='Template Path')),
                ('external_url', models.URLField(blank=True, help_text="External URL to fetch template from. Used when template source is 'external'.", verbose_name='External URL')),
                ('subject_template', models.CharField(help_text='Subject line template. Use {{ title }}, {{ site_name }}, {{ user_name }}, etc.', max_length=255, verbose_name='Subject Template')),
                ('preview_text', models.CharField(blank=True, help_text='Text preview shown in email clients (usually 85-100 characters).', max_length=255, verbose_name='Preview Text')),
                ('html_file', models.FileField(blank=True, help_text='Upload a complete HTML email template file (.html, .htm).', null=True, upload_to='email_templates/html/%Y/%m/%d/', verbose_name='HTML Template File')),
                ('css_file', models.FileField(blank=True, help_text='Upload a CSS file for styling (.css).', null=True, upload_to='email_templates/css/%Y/%m/%d/', verbose_name='CSS Stylesheet File')),
                ('html_content', models.TextField(blank=True, help_text='HTML markup with placeholders like {{ title }}, {{ content }}, {{ preview_text }}, {{ header_image_url }}, {{ unsubscribe_url }}, {{ site_url }}, {{ current_year }}.', verbose_name='Inline HTML Content')),
                ('css_content', models.TextField(blank=True, help_text='Inline CSS styles (used if no CSS file is uploaded).', verbose_name='Inline CSS Styles')),
                ('text_content', models.TextField(blank=True, help_text='Plain text fallback for non-HTML email clients.', verbose_name='Plain Text Content')),
                ('template_type', models.CharField(choices=[('invitation', 'Invitation'), ('notification', 'Notification'), ('newsletter', 'Newsletter'), ('transactional', 'Transactional'), ('welcome', 'Welcome'), ('password_reset', 'Password Reset'), ('order_confirmation', 'Order Confirmation'), ('system_alert', 'System Alert'), ('campaign', 'Campaign'), ('promotional', 'Promotional'), ('abandoned_cart', 'Abandoned Cart'), ('receipt', 'Receipt'), ('feedback', 'Feedback'), ('announcement', 'Announcement')], default='newsletter', help_text='Category for organizing templates.', max_length=50, verbose_name='Template Type')),
                ('language', models.CharField(choices=[('en', 'English'), ('es', 'Spanish'), ('fr', 'French'), ('de', 'German'), ('it', 'Italian'), ('pt', 'Portuguese'), ('ru', 'Russian'), ('zh', 'Chinese'), ('ja', 'Japanese'), ('ar', 'Arabic'), ('ko', 'Korean'), ('hi', 'Hindi'), ('tr', 'Turkish'), ('nl', 'Dutch'), ('pl', 'Polish')], default='en', help_text='Primary language for this template.', max_length=10, verbose_name='Language')),
                ('version', models.PositiveIntegerField(default=1, help_text='Template version number.', verbose_name='Version')),
                ('is_default', models.BooleanField(default=False, help_text='Mark as default template for this type.', verbose_name='Set as Default')),
                ('is_active', models.BooleanField(default=True, help_text='Whether this template can be used for sending emails.', verbose_name='Is Active')),
                ('is_system', models.BooleanField(default=False, help_text='System templates cannot be deleted or deactivated.', verbose_name='System Template')),
                ('is_draft', models.BooleanField(default=False, help_text='Mark as draft - not ready for production use.', verbose_name='Is Draft')),
                ('reply_to_email', models.EmailField(blank=True, help_text='Default reply-to address for emails using this template.', max_length=254, verbose_name='Reply-To Email')),
                ('from_email', models.EmailField(blank=True, help_text='Default sender email address.', max_length=254, verbose_name='From Email')),
                ('from_name', models.CharField(blank=True, help_text='Display name for the sender.', max_length=100, verbose_name='From Name')),
                ('unsubscribe_url', models.URLField(blank=True, help_text='Default unsubscribe link for newsletters.', verbose_name='Unsubscribe URL')),
                ('category', models.CharField(blank=True, help_text="Optional category for grouping templates (e.g., 'Marketing', 'Transactional').", max_length=100, verbose_name='Category')),
                ('tags', models.JSONField(blank=True, default=list, help_text='List of tags for filtering and organizing templates.', verbose_name='Tags')),
                ('cache_key', models.CharField(blank=True, help_text='Auto-generated cache key for template rendering.', max_length=100, verbose_name='Cache Key')),
                ('last_rendered', models.DateTimeField(blank=True, help_text='When this template was last rendered.', null=True, verbose_name='Last Rendered')),
                ('render_count', models.PositiveIntegerField(default=0, help_text='How many times this template has been rendered.', verbose_name='Render Count')),
                ('open_rate', models.FloatField(default=0.0, help_text='Historical open rate percentage for this template.', verbose_name='Open Rate')),
                ('click_rate', models.FloatField(default=0.0, help_text='Historical click rate percentage for this template.', verbose_name='Click Rate')),
                ('conversion_rate', models.FloatField(default=0.0, help_text='Historical conversion rate percentage for this template.', verbose_name='Conversion Rate')),
                ('bounce_rate', models.FloatField(default=0.0, help_text='Historical bounce rate percentage for this template.', verbose_name='Bounce Rate')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this record', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('footer_image', models.ForeignKey(blank=True, help_text='Image for the email footer (e.g., social media icons).', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Footer Image')),
                ('header_image', models.ForeignKey(blank=True, help_text='Default header image for the email template.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Header Image')),
                ('logo_image', models.ForeignKey(blank=True, help_text='Logo to display in the email header.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Logo Image')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last updated this record', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Email Template',
                'verbose_name_plural': 'Email Templates',
                'ordering': ['template_type', 'name', 'version'],
            },
        ),
        migrations.CreateModel(
            name='Newsletter',
            fields=[
                ('translation_key', models.UUIDField(default=uuid.uuid4, editable=False)),
                ('live', models.BooleanField(default=True, editable=False, verbose_name='live')),
                ('has_unpublished_changes', models.BooleanField(default=False, editable=False, verbose_name='has unpublished changes')),
                ('first_published_at', models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='first published at')),
                ('last_published_at', models.DateTimeField(editable=False, null=True, verbose_name='last published at')),
                ('go_live_at', models.DateTimeField(blank=True, null=True, verbose_name='go live date/time')),
                ('expire_at', models.DateTimeField(blank=True, null=True, verbose_name='expiry date/time')),
                ('expired', models.BooleanField(default=False, editable=False, verbose_name='expired')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
                ('is_active', models.BooleanField(default=True, help_text='Indicates whether this record is active', verbose_name='Is Active')),
                ('search_description', models.TextField(blank=True, help_text='Description for search engines and social sharing', verbose_name='Search description')),
                ('title', models.CharField(max_length=255, verbose_name='Newsletter Title')),
                ('subject', models.CharField(max_length=255, verbose_name='Email Subject')),
                ('preview_text', models.TextField(blank=True, help_text='Short summary text displayed in some email clients.', max_length=500, verbose_name='Preview Text')),
                ('body', wagtail.fields.StreamField([('heading', 0), ('paragraph', 1), ('image', 2), ('quote', 11), ('embed', 12), ('table', 33), ('typed_table', 54), ('info_section', 62)], blank=True, block_lookup={0: ('wagtail.blocks.CharBlock', (), {'help_text': 'Main heading for this section.', 'icon': 'title', 'label': 'Heading', 'template': 'blocks/heading_block.html'}), 1: ('wagtail.blocks.RichTextBlock', (), {'features': ['h2', 'h3', 'bold', 'italic', 'link', 'ol', 'ul', 'code'], 'icon': 'pilcrow', 'label': 'Paragraph', 'template': 'blocks/paragraph_block.html'}), 2: ('wagtail.images.blocks.ImageChooserBlock', (), {'help_text': 'Optional image for this section.', 'icon': 'image', 'label': 'Image', 'template': 'blocks/image_block.html'}), 3: ('wagtail.blocks.TextBlock', (), {'help_text': 'The quoted text.', 'label': 'Quote Text', 'required': True}), 4: ('wagtail.blocks.CharBlock', (), {'help_text': "Who said it (e.g., 'John Doe, CEO of Company').", 'label': 'Citation', 'max_length': 200, 'required': False}), 5: ('wagtail.blocks.URLBlock', (), {'help_text': 'Optional link for the citation.', 'label': 'Citation URL', 'required': False}), 6: ('wagtail.images.blocks.ImageChooserBlock', (), {'help_text': 'Optional photo of the person quoted.', 'label': 'Avatar Image', 'required': False}), 7: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('default', 'Default'), ('large', 'Large Text'), ('border', 'With Border'), ('icon', 'With Quote Icon'), ('highlight', 'Highlighted Background')], 'label': 'Quote Style', 'required': False}), 8: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('left', 'Left Aligned'), ('center', 'Center Aligned'), ('right', 'Right Aligned')], 'label': 'Alignment', 'required': False}), 9: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'label': 'Show Quote Icon', 'required': False}), 10: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('top-left', 'Top Left'), ('top', 'Top Center'), ('left', 'Left Side')], 'label': 'Icon Position', 'required': False}), 11: ('wagtail.blocks.StructBlock', [[('quote_text', 3), ('citation', 4), ('citation_url', 5), ('avatar', 6), ('quote_style', 7), ('alignment', 8), ('quote_icon', 9), ('icon_position', 10)]], {}), 12: ('wagtail.embeds.blocks.EmbedBlock', (), {'help_text': 'Embed a video or external media (YouTube, Vimeo, etc.)', 'icon': 'media', 'label': 'Embedded Video/Media', 'template': 'blocks/embed_block.html'}), 13: ('wagtail.blocks.CharBlock', (), {'help_text': 'Custom HTML ID for CSS targeting and JavaScript.', 'label': 'Custom CSS ID', 'max_length': 50, 'required': False}), 14: ('wagtail.blocks.CharBlock', (), {'help_text': 'Additional CSS classes for custom styling.', 'label': 'Custom CSS Class', 'max_length': 100, 'required': False}), 15: ('wagtail.blocks.RawHTMLBlock', (), {'help_text': 'Custom data attributes for JavaScript interaction.', 'label': 'Data Attributes', 'required': False}), 16: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'help_text': 'Toggle visibility of this block.', 'label': 'Visible', 'required': False}), 17: ('wagtail.contrib.table_block.blocks.TableBlock', (), {'help_text': 'Enter table data with rows and columns.', 'label': 'Table Data', 'required': True}), 18: ('wagtail.blocks.CharBlock', (), {'help_text': 'Optional caption displayed above or below the table.', 'label': 'Table Caption', 'max_length': 200, 'required': False}), 19: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('top', 'Top'), ('bottom', 'Bottom')], 'label': 'Caption Position', 'required': False}), 20: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('default', 'Default'), ('striped', 'Striped Rows'), ('bordered', 'Bordered'), ('hover', 'Hover Effects'), ('condensed', 'Condensed'), ('responsive', 'Responsive Scroll')], 'label': 'Table Style', 'required': False}), 21: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('default', 'Default Header'), ('dark', 'Dark Header'), ('light', 'Light Header'), ('primary', 'Primary Color'), ('secondary', 'Secondary Color')], 'label': 'Header Style', 'required': False}), 22: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'help_text': 'Alternate row background colors for better readability.', 'label': 'Zebra Striping', 'required': False}), 23: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Allow sorting by clicking column headers.', 'label': 'Sortable Columns', 'required': False}), 24: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Add search/filter functionality.', 'label': 'Searchable', 'required': False}), 25: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Split large tables into pages.', 'label': 'Pagination', 'required': False}), 26: ('wagtail.blocks.IntegerBlock', (), {'default': 10, 'label': 'Rows Per Page', 'max_value': 100, 'min_value': 5, 'required': False}), 27: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Allow exporting table data to CSV/Excel.', 'label': 'Exportable', 'required': False}), 28: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('csv', 'CSV'), ('excel', 'Excel'), ('pdf', 'PDF'), ('print', 'Print')]}), 29: ('wagtail.blocks.ListBlock', (28,), {'default': ['csv'], 'label': 'Export Formats', 'required': False}), 30: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Keep header visible while scrolling.', 'label': 'Fixed Header', 'required': False}), 31: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Allow users to resize columns.', 'label': 'Column Resizing', 'required': False}), 32: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Allow selecting rows (checkboxes).', 'label': 'Row Selection', 'required': False}), 33: ('wagtail.blocks.StructBlock', [[('custom_css_id', 13), ('custom_css_class', 14), ('data_attributes', 15), ('is_visible', 16), ('table', 17), ('caption', 18), ('caption_position', 19), ('table_style', 20), ('header_style', 21), ('zebra_striping', 22), ('sortable', 23), ('searchable', 24), ('pagination', 25), ('rows_per_page', 26), ('exportable', 27), ('export_formats', 29), ('fixed_header', 30), ('column_resizing', 31), ('row_selection', 32)]], {'label': 'Table', 'template': 'blocks/table_block.html'}), 34: ('wagtail.blocks.CharBlock', (), {'label': 'Table Title', 'max_length': 200, 'required': False}), 35: ('wagtail.blocks.RichTextBlock', (), {'label': 'Table Description', 'required': False}), 36: ('wagtail.blocks.CharBlock', (), {'label': 'Column Name', 'required': True}), 37: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'label': 'Required'}), 38: ('wagtail.blocks.IntegerBlock', (), {'label': 'Max Length', 'required': False}), 39: ('wagtail.blocks.StructBlock', [[('name', 36), ('required', 37), ('max_length', 38)]], {'label': 'Text Column'}), 40: ('wagtail.blocks.IntegerBlock', (), {'label': 'Minimum Value', 'required': False}), 41: ('wagtail.blocks.IntegerBlock', (), {'label': 'Maximum Value', 'required': False}), 42: ('wagtail.blocks.StructBlock', [[('name', 36), ('required', 37), ('min_value', 40), ('max_value', 41)]], {'label': 'Number Column'}), 43: ('wagtail.blocks.CharBlock', (), {'default': 'YYYY-MM-DD', 'label': 'Date Format'}), 44: ('wagtail.blocks.StructBlock', [[('name', 36), ('required', 37), ('format', 43)]], {'label': 'Date Column'}), 45: ('wagtail.blocks.CharBlock', (), {'label': 'Option'}), 46: ('wagtail.blocks.ListBlock', (45,), {'label': 'Choices'}), 47: ('wagtail.blocks.StructBlock', [[('name', 36), ('required', 37), ('choices', 46)]], {'label': 'Choice Column'}), 48: ('wagtail.blocks.StreamBlock', [[('text_column', 39), ('number_column', 42), ('date_column', 44), ('choice_column', 47)]], {'label': 'Column Definitions', 'max_num': 10}), 49: ('wagtail.contrib.typed_table_block.blocks.TypedTableBlock', [[]], {'help_text': 'Table data will be dynamically generated based on column definitions.', 'label': 'Table Data'}), 50: ('wagtail.blocks.CharBlock', (), {'label': 'Text'}), 51: ('wagtail.blocks.FloatBlock', (), {'label': 'Number'}), 52: ('wagtail.blocks.RichTextBlock', (), {'label': 'Rich Text'}), 53: ('wagtail.blocks.CharBlock', (), {'label': 'File Link'}), 54: ('wagtail.blocks.StructBlock', [[('custom_css_id', 13), ('custom_css_class', 14), ('data_attributes', 15), ('is_visible', 16), ('table_title', 34), ('table_description', 35), ('column_definitions', 48), ('table_data', 49), ('text', 50), ('number', 51), ('rich_text', 52), ('file', 53)]], {'label': 'Typed Table', 'template': 'blocks/typed_table.html'}), 55: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('overview', 'Overview'), ('details', 'Details'), ('requirements', 'Requirements'), ('resources', 'Resources')], 'help_text': 'Defines what kind of section this is.', 'label': 'Section Type', 'required': False}), 56: ('wagtail.blocks.CharBlock', (), {'help_text': 'Optional heading for the section.', 'label': 'Heading', 'required': False}), 57: ('wagtail.blocks.RichTextBlock', (), {'features': ['h2', 'h3', 'bold', 'italic', 'link', 'ol', 'ul', 'code'], 'help_text': 'Main descriptive text for this section.', 'label': 'Body Text', 'required': False}), 58: ('wagtail.images.blocks.ImageChooserBlock', (), {'help_text': 'Optional image for this section.', 'label': 'Image', 'required': False}), 59: ('wagtail.embeds.blocks.EmbedBlock', (), {'help_text': 'Insert a YouTube/Vimeo or other embed URL.', 'label': 'Embedded Media', 'required': False}), 60: ('wagtail.blocks.CharBlock', (), {'label': 'List Item'}), 61: ('wagtail.blocks.ListBlock', (60,), {'label': 'Key Points', 'required': False}), 62: ('wagtail.blocks.StructBlock', [[('section_type', 55), ('heading', 56), ('body', 57), ('image', 58), ('embed', 59), ('list_items', 61)]], {})}, verbose_name='Newsletter Content')),
                ('audience_type', models.CharField(choices=[('ALL', 'All Users'), ('STUDENTS', 'Students Only'), ('INSTRUCTORS', 'Instructors Only'), ('ADMINS', 'Administrators Only'), ('SPECIFIC', 'Specific Users/Groups')], default='ALL', max_length=15)),
                ('target_user_levels', models.CharField(blank=True, help_text='Comma-separated user levels, e.g. UNDERGRAD,GRADUATE', max_length=50, verbose_name='Target User Levels')),
                ('schedule_type', models.CharField(choices=[('DRAFT', 'Save as Draft'), ('IMMEDIATE', 'Send Immediately'), ('SCHEDULED', 'Schedule for Later'), ('TEST', 'Send Test Email')], default='DRAFT', max_length=15)),
                ('scheduled_date', models.DateTimeField(blank=True, null=True, verbose_name='Scheduled Date')),
                ('sent_date', models.DateTimeField(blank=True, editable=False, null=True)),
                ('total_recipients', models.PositiveIntegerField(default=0, editable=False)),
                ('open_count', models.PositiveIntegerField(default=0, editable=False)),
                ('click_count', models.PositiveIntegerField(default=0, editable=False)),
                ('track_opens', models.BooleanField(default=True, verbose_name='Track Opens')),
                ('track_clicks', models.BooleanField(default=True, verbose_name='Track Clicks')),
                ('include_unsubscribe', models.BooleanField(default=True, verbose_name='Include Unsubscribe Link')),
                ('important_announcement', models.BooleanField(default=False)),
                ('show_in_portal', models.BooleanField(default=True)),
                ('test_email_addresses', models.TextField(blank=True, help_text='Comma-separated test email addresses')),
                ('newsletter_id', models.CharField(editable=False, max_length=50, unique=True)),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this record', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('header_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Header Image')),
                ('latest_revision', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.revision', verbose_name='latest revision')),
                ('live_revision', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.revision', verbose_name='live revision')),
                ('locale', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='wagtailcore.locale', verbose_name='locale')),
                ('template', models.ForeignKey(blank=True, help_text='HTML template for rendering this newsletter.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='pipelines.emailtemplate', verbose_name='Email Template')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last updated this record', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Newsletter',
                'verbose_name_plural': 'Newsletters',
                'ordering': ['-created_at'],
                'abstract': False,
            },
            bases=(wagtail.models.preview.PreviewableMixin, models.Model, modelsearch.index.Indexed),
        ),
        migrations.CreateModel(
            name='Person',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
                ('is_active', models.BooleanField(default=True, help_text='Indicates whether this record is active', verbose_name='Is Active')),
                ('live', models.BooleanField(default=True, help_text='Whether this record is publicly accessible', verbose_name='Live')),
                ('first_published_at', models.DateTimeField(blank=True, null=True, verbose_name='First Published At')),
                ('last_published_at', models.DateTimeField(blank=True, null=True, verbose_name='Last Published At')),
                ('search_description', models.TextField(blank=True, help_text='Description for search engines and social sharing', verbose_name='Search description')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='ID')),
                ('first_name', models.CharField(blank=True, max_length=100, null=True, verbose_name='First Name')),
                ('last_name', models.CharField(blank=True, max_length=100, null=True, verbose_name='Last Name')),
                ('full_name', models.CharField(blank=True, help_text='Automatically generated from first and last name', max_length=200, null=True, verbose_name='Full Name')),
                ('display_name', models.CharField(blank=True, help_text='Name to display publicly (can be different from legal name)', max_length=200, null=True, verbose_name='Display Name')),
                ('birth_date', models.DateField(blank=True, null=True, verbose_name='Date of Birth')),
                ('gender', models.CharField(blank=True, choices=[('MALE', 'Male'), ('FEMALE', 'Female'), ('OTHER', 'Other'), ('PREFER_NOT_TO_SAY', 'Prefer not to say')], max_length=20, null=True, verbose_name='Gender')),
                ('email', models.EmailField(blank=True, help_text='Primary email for this profile (can be different from user account email)', max_length=254, null=True, verbose_name='Profile Email')),
                ('phone_number', models.CharField(blank=True, help_text='Primary phone number for this profile', max_length=20, null=True, verbose_name='Phone Number')),
                ('alternate_email', models.EmailField(blank=True, help_text='Alternate email address', max_length=254, null=True, verbose_name='Alternate Email')),
                ('alternate_phone', models.CharField(blank=True, help_text='Alternate phone number', max_length=20, null=True, verbose_name='Alternate Phone')),
                ('address', models.TextField(blank=True, help_text='Full physical address', null=True, verbose_name='Primary Address')),
                ('country', models.CharField(blank=True, max_length=100, null=True, verbose_name='Country')),
                ('city', models.CharField(blank=True, max_length=100, null=True, verbose_name='City')),
                ('postal_code', models.CharField(blank=True, max_length=20, null=True, verbose_name='Postal Code')),
                ('location', models.CharField(blank=True, help_text='General location (e.g. City, Country)', max_length=255, null=True, verbose_name='Location')),
                ('public_profile', models.BooleanField(default=False, help_text='Make your profile visible to everyone', verbose_name='Public Profile')),
                ('profile_visibility', models.CharField(choices=[('public', 'Public - Anyone can see your profile'), ('members', 'Members Only - Only registered members can see your profile'), ('private', 'Private - Only you can see your profile')], default='public', max_length=20, verbose_name='Profile Visibility')),
                ('share_usage_data', models.BooleanField(default=True, help_text='Help us improve by sharing anonymous usage data', verbose_name='Share Usage Data')),
                ('allow_search_indexing', models.BooleanField(default=True, help_text='Allow search engines to index your profile', verbose_name='Allow Search Indexing')),
                ('show_online_status', models.BooleanField(default=True, verbose_name='Show Online Status')),
                ('allow_contact', models.BooleanField(default=True, help_text='Allow other members to contact you', verbose_name='Allow Contact')),
                ('show_email', models.BooleanField(default=False, help_text='Show your email address on your public profile', verbose_name='Show Email')),
                ('job_title', models.CharField(blank=True, max_length=200, null=True, verbose_name='Job Title')),
                ('company', models.CharField(blank=True, max_length=200, null=True, verbose_name='Company')),
                ('department', models.CharField(blank=True, max_length=200, null=True, verbose_name='Department')),
                ('position', models.CharField(blank=True, max_length=200, null=True, verbose_name='Current Position')),
                ('industry', models.CharField(blank=True, max_length=200, null=True, verbose_name='Industry')),
                ('bio', models.TextField(blank=True, help_text='Brief professional biography', null=True, verbose_name='Biography')),
                ('website', models.URLField(blank=True, null=True, verbose_name='Personal Website')),
                ('linkedin_url', models.URLField(blank=True, null=True, verbose_name='LinkedIn Profile')),
                ('github_url', models.URLField(blank=True, null=True, verbose_name='GitHub Profile')),
                ('twitter_url', models.URLField(blank=True, null=True, verbose_name='Twitter/X Profile')),
                ('facebook_url', models.URLField(blank=True, null=True, verbose_name='Facebook Profile')),
                ('instagram_url', models.URLField(blank=True, null=True, verbose_name='Instagram Profile')),
                ('profile_type', models.CharField(choices=[('EMP', 'Employee'), ('STU', 'Student'), ('CUS', 'Customer'), ('SUP', 'Supplier Contact'), ('PRT', 'Partner Contact'), ('CON', 'Contact Person'), ('GST', 'Guest'), ('ADM', 'Administrator'), ('OTH', 'Other')], default='CON', help_text='Type of profile/role in the system', max_length=3, verbose_name='Profile Type')),
                ('status', models.CharField(choices=[('ACTIVE', 'Active'), ('INACTIVE', 'Inactive'), ('SUSPENDED', 'Suspended'), ('PENDING', 'Pending Approval'), ('INVITED', 'Invited'), ('ARCHIVED', 'Archived')], default='PENDING', max_length=20, verbose_name='Status')),
                ('is_registered', models.BooleanField(default=False, help_text="Designates whether this profile has been registered/activated by a user. False = profile exists but user hasn't registered yet.", verbose_name='Registered')),
                ('registration_date', models.DateTimeField(blank=True, help_text='Date when the profile was registered', null=True, verbose_name='Registration Date')),
                ('is_email_verified', models.BooleanField(default=False, help_text='Indicates if the profile email has been verified.', verbose_name='Email Verified')),
                ('email_verified_at', models.DateTimeField(blank=True, help_text='Timestamp when profile email was verified.', null=True, verbose_name='Email Verified At')),
                ('is_phone_verified', models.BooleanField(default=False, help_text='Indicates if the profile phone number has been verified.', verbose_name='Phone Verified')),
                ('phone_verified_at', models.DateTimeField(blank=True, help_text='Timestamp when profile phone was verified.', null=True, verbose_name='Phone Verified At')),
                ('language', models.CharField(choices=[('en', 'English'), ('fr', 'French'), ('de', 'German'), ('es', 'Spanish'), ('ar', 'العربيّة')], default='en', help_text='Preferred language for this profile.', max_length=10, verbose_name='Language')),
                ('timezone', models.CharField(default='UTC', help_text="Profile's preferred timezone.", max_length=50, verbose_name='Timezone')),
                ('profile_completion', models.IntegerField(default=0, help_text='Percentage of profile completion.', verbose_name='Profile Completion %')),
                ('email_notifications', models.BooleanField(default=True, help_text='Enable email notifications for this profile.', verbose_name='Email Notifications')),
                ('newsletter_notifications', models.BooleanField(default=True, help_text='Subscribe to newsletters for this profile.', verbose_name='Newsletter Notifications')),
                ('marketing_emails', models.BooleanField(default=False, help_text='Receive marketing and promotional emails.', verbose_name='Marketing Emails')),
                ('course_updates_notifications', models.BooleanField(default=True, help_text='Notifications for course updates and announcements', verbose_name='Course Updates')),
                ('instructor_messages_notifications', models.BooleanField(default=True, help_text='Notifications for new messages from instructors', verbose_name='Instructor Messages')),
                ('weekly_reports_notifications', models.BooleanField(default=True, help_text='Receive weekly progress reports', verbose_name='Weekly Reports')),
                ('assignment_notifications', models.BooleanField(default=True, help_text='Notifications for assignment graded or feedback', verbose_name='Assignment Notifications')),
                ('forum_activity_notifications', models.BooleanField(default=True, help_text='Notifications for forum mentions and replies', verbose_name='Forum Activity')),
                ('deadline_reminders_notifications', models.BooleanField(default=True, help_text='Reminders for upcoming deadlines', verbose_name='Deadline Reminders')),
                ('notification_frequency', models.CharField(choices=[('instantly', 'Instantly'), ('daily', 'Daily Digest'), ('weekly', 'Weekly Newsletter')], default='instantly', max_length=20, verbose_name='Notification Frequency')),
                ('dark_mode', models.BooleanField(default=True, verbose_name='Dark Mode')),
                ('high_contrast', models.BooleanField(default=False, verbose_name='High Contrast')),
                ('reduce_animations', models.BooleanField(default=False, verbose_name='Reduce Animations')),
                ('ui_density', models.CharField(choices=[('compact', 'Compact'), ('comfortable', 'Comfortable'), ('spacious', 'Spacious')], default='comfortable', max_length=20, verbose_name='UI Density')),
                ('date_format', models.CharField(default='DD/MM/YYYY', max_length=20, verbose_name='Date Format')),
                ('time_format', models.CharField(choices=[('12h', '12-hour (AM/PM)'), ('24h', '24-hour')], default='24h', max_length=10, verbose_name='Time Format')),
                ('subscription_plan', models.CharField(choices=[('free', 'Free Plan'), ('pro', 'Pro Monthly'), ('enterprise', 'Enterprise')], default='free', max_length=50, verbose_name='Subscription Plan')),
                ('billing_cycle', models.CharField(choices=[('monthly', 'Monthly'), ('yearly', 'Yearly')], default='monthly', max_length=20, verbose_name='Billing Cycle')),
                ('payment_method', models.CharField(blank=True, choices=[('card', 'Credit/Debit Card'), ('paypal', 'PayPal'), ('stripe', 'Stripe')], max_length=50, null=True, verbose_name='Payment Method')),
                ('auto_renew', models.BooleanField(default=True, verbose_name='Auto Renew')),
                ('billing_name', models.CharField(blank=True, max_length=200, null=True, verbose_name='Billing Name')),
                ('billing_address', models.TextField(blank=True, null=True, verbose_name='Billing Address')),
                ('tax_id', models.CharField(blank=True, max_length=50, null=True, verbose_name='Tax ID')),
                ('send_invoices', models.BooleanField(default=True, verbose_name='Send Invoices')),
                ('paperless_billing', models.BooleanField(default=True, verbose_name='Paperless Billing')),
                ('last_active', models.DateTimeField(blank=True, help_text='Last time the profile was actively used', null=True, verbose_name='Last Active')),
                ('last_profile_update', models.DateTimeField(blank=True, help_text='Last time profile information was updated', null=True, verbose_name='Last Profile Update')),
                ('login_count', models.IntegerField(default=0, help_text='Number of times the user has logged in', verbose_name='Login Count')),
                ('profile_image', models.ImageField(blank=True, help_text='Profile photo (recommended: 400x400px)', null=True, upload_to='profiles/images/%Y/%m/%d/', verbose_name='Profile Image')),
                ('cover_image', models.ImageField(blank=True, help_text='Cover photo (recommended: 1500x500px)', null=True, upload_to='profiles/covers/%Y/%m/%d/', verbose_name='Cover Image')),
                ('profile_content', wagtail.fields.StreamField([('certification', 14), ('project', 28), ('testimonial', 43), ('contact_method', 52), ('website_link', 74)], blank=True, block_lookup={0: ('wagtail.blocks.CharBlock', (), {'help_text': 'Custom HTML ID for CSS targeting and JavaScript.', 'label': 'Custom CSS ID', 'max_length': 50, 'required': False}), 1: ('wagtail.blocks.CharBlock', (), {'help_text': 'Additional CSS classes for custom styling.', 'label': 'Custom CSS Class', 'max_length': 100, 'required': False}), 2: ('wagtail.blocks.RawHTMLBlock', (), {'help_text': 'Custom data attributes for JavaScript interaction.', 'label': 'Data Attributes', 'required': False}), 3: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'help_text': 'Toggle visibility of this block.', 'label': 'Visible', 'required': False}), 4: ('wagtail.blocks.CharBlock', (), {'help_text': 'Full name of the certification', 'label': 'Certification Name'}), 5: ('wagtail.blocks.CharBlock', (), {'help_text': 'Organization that issued the certification', 'label': 'Issuing Organization'}), 6: ('wagtail.blocks.DateBlock', (), {'help_text': 'When the certification was issued', 'label': 'Issue Date'}), 7: ('wagtail.blocks.DateBlock', (), {'help_text': 'When the certification expires (if applicable)', 'label': 'Expiration Date', 'required': False}), 8: ('wagtail.blocks.CharBlock', (), {'help_text': 'Official credential or license number', 'label': 'Credential ID', 'required': False}), 9: ('wagtail.blocks.URLBlock', (), {'help_text': 'Link to verify the credential online', 'label': 'Credential URL', 'required': False}), 10: ('wagtail.blocks.CharBlock', (), {'label': 'Skill'}), 11: ('wagtail.blocks.ListBlock', (10,), {'help_text': 'Skills demonstrated by this certification', 'label': 'Related Skills', 'required': False}), 12: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Mark if certification has expired', 'label': 'Expired', 'required': False}), 13: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'help_text': 'Display certification badge', 'label': 'Show Badge', 'required': False}), 14: ('wagtail.blocks.StructBlock', [[('custom_css_id', 0), ('custom_css_class', 1), ('data_attributes', 2), ('is_visible', 3), ('name', 4), ('issuing_organization', 5), ('issue_date', 6), ('expiration_date', 7), ('credential_id', 8), ('credential_url', 9), ('skills', 11), ('is_expired', 12), ('show_badge', 13)]], {}), 15: ('wagtail.blocks.CharBlock', (), {'help_text': 'Name of the project', 'label': 'Project Name'}), 16: ('wagtail.blocks.RichTextBlock', (), {'features': ['bold', 'italic', 'link', 'ol', 'ul'], 'help_text': 'Detailed description of the project', 'label': 'Description'}), 17: ('wagtail.blocks.CharBlock', (), {'help_text': 'Brief summary for project cards', 'label': 'Short Description', 'max_length': 200, 'required': False}), 18: ('wagtail.images.blocks.ImageChooserBlock', (), {'help_text': 'Project thumbnail image', 'label': 'Thumbnail Image', 'required': False}), 19: ('wagtail.blocks.CharBlock', (), {'label': 'Technology'}), 20: ('wagtail.blocks.ListBlock', (19,), {'help_text': 'Technologies, frameworks, and tools used', 'label': 'Technologies Used', 'required': False}), 21: ('wagtail.blocks.URLBlock', (), {'help_text': 'Link to the live project', 'label': 'Live Project URL', 'required': False}), 22: ('wagtail.blocks.URLBlock', (), {'help_text': 'Link to source code repository', 'label': 'GitHub Repository', 'required': False}), 23: ('wagtail.blocks.DateBlock', (), {'help_text': 'When the project started', 'label': 'Start Date'}), 24: ('wagtail.blocks.DateBlock', (), {'help_text': 'When the project ended (if applicable)', 'label': 'End Date', 'required': False}), 25: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Project is currently in development', 'label': 'Ongoing Project', 'required': False}), 26: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Highlight this project as featured', 'label': 'Featured Project', 'required': False}), 27: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('personal', 'Personal Project'), ('professional', 'Professional Work'), ('open_source', 'Open Source'), ('client', 'Client Project'), ('academic', 'Academic')], 'label': 'Project Type'}), 28: ('wagtail.blocks.StructBlock', [[('custom_css_id', 0), ('custom_css_class', 1), ('data_attributes', 2), ('is_visible', 3), ('name', 15), ('description', 16), ('short_description', 17), ('thumbnail', 18), ('technologies', 20), ('project_url', 21), ('github_url', 22), ('start_date', 23), ('end_date', 24), ('is_ongoing', 25), ('is_featured', 26), ('project_type', 27)]], {}), 29: ('wagtail.blocks.RichTextBlock', (), {'features': ['bold', 'italic', 'link'], 'help_text': 'What the person said about your product/service.', 'label': 'Testimonial Text', 'required': True}), 30: ('wagtail.blocks.CharBlock', (), {'label': 'Customer Name', 'max_length': 100, 'required': True}), 31: ('wagtail.blocks.CharBlock', (), {'help_text': 'Job title or position.', 'label': 'Customer Title', 'max_length': 100, 'required': False}), 32: ('wagtail.blocks.CharBlock', (), {'help_text': 'Company or organization name.', 'label': 'Company', 'max_length': 100, 'required': False}), 33: ('wagtail.images.blocks.ImageChooserBlock', (), {'label': 'Company Logo', 'required': False}), 34: ('wagtail.images.blocks.ImageChooserBlock', (), {'label': 'Customer Photo', 'required': False}), 35: ('wagtail.blocks.IntegerBlock', (), {'help_text': 'Star rating from 1 to 5.', 'label': 'Rating', 'max_value': 5, 'min_value': 1, 'required': False}), 36: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'label': 'Show Star Rating', 'required': False}), 37: ('wagtail.blocks.DateBlock', (), {'label': 'Testimonial Date', 'required': False}), 38: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Mark as verified purchase or interaction', 'label': 'Verified Customer', 'required': False}), 39: ('wagtail.blocks.CharBlock', (), {'default': 'Verified Customer', 'label': 'Verification Text', 'max_length': 50, 'required': False}), 40: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('card', 'Card Layout'), ('simple', 'Simple Layout'), ('horizontal', 'Horizontal Layout'), ('quote', 'Quote Style'), ('grid', 'Grid Layout')], 'label': 'Layout Style', 'required': False}), 41: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('customer', 'Customer'), ('client', 'Client'), ('colleague', 'Colleague'), ('partner', 'Partner'), ('student', 'Student'), ('other', 'Other')], 'label': 'Source Type', 'required': False}), 42: ('wagtail.embeds.blocks.EmbedBlock', (), {'help_text': 'Embed a video testimonial from YouTube, Vimeo, etc.', 'label': 'Video Testimonial', 'required': False}), 43: ('wagtail.blocks.StructBlock', [[('custom_css_id', 0), ('custom_css_class', 1), ('data_attributes', 2), ('is_visible', 3), ('testimonial_text', 29), ('customer_name', 30), ('customer_title', 31), ('company', 32), ('company_logo', 33), ('avatar', 34), ('rating', 35), ('show_rating', 36), ('date', 37), ('verified', 38), ('verification_text', 39), ('layout_style', 40), ('testimonial_source', 41), ('video_testimonial', 42)]], {}), 44: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('email', 'Email Address'), ('phone', 'Phone Number'), ('mobile', 'Mobile Phone'), ('fax', 'Fax Number'), ('website', 'Website'), ('social', 'Social Media'), ('address', 'Physical Address'), ('other', 'Other')], 'help_text': 'Type of contact method', 'label': 'Contact Type'}), 45: ('wagtail.blocks.CharBlock', (), {'help_text': 'Email address, phone number, URL, username, etc.', 'label': 'Contact Value', 'max_length': 255, 'required': True}), 46: ('wagtail.blocks.CharBlock', (), {'help_text': 'Optional custom label for this contact method', 'label': 'Custom Label', 'max_length': 100, 'required': False}), 47: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Mark as the primary contact method for this type', 'label': 'Primary Contact', 'required': False}), 48: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Has this contact method been verified?', 'label': 'Verified', 'required': False}), 49: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'help_text': 'Display this contact method publicly', 'label': 'Show Publicly', 'required': False}), 50: ('wagtail.blocks.CharBlock', (), {'help_text': 'Optional CSS class for custom icons', 'label': 'Icon CSS Class', 'required': False}), 51: ('wagtail.blocks.TextBlock', (), {'help_text': 'Additional notes or context for this contact method', 'label': 'Notes', 'required': False}), 52: ('wagtail.blocks.StructBlock', [[('contact_type', 44), ('value', 45), ('label', 46), ('is_primary', 47), ('verified', 48), ('show_publicly', 49), ('icon_class', 50), ('notes', 51)]], {}), 53: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('social', 'Social Media Profile'), ('website', 'Website/Blog'), ('professional', 'Professional Profile'), ('portfolio', 'Portfolio/Showcase'), ('business', 'Business/Company'), ('contact', 'Contact Method'), ('other', 'Other')], 'help_text': 'Category of this profile/link', 'label': 'Profile Type'}), 54: ('wagtail.blocks.CharBlock', (), {'help_text': 'How this profile should be displayed', 'label': 'Display Title', 'max_length': 150, 'required': True}), 55: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('linkedin', 'LinkedIn'), ('twitter', 'Twitter/X'), ('facebook', 'Facebook'), ('instagram', 'Instagram'), ('github', 'GitHub'), ('youtube', 'YouTube'), ('whatsapp', 'WhatsApp Business'), ('telegram', 'Telegram'), ('discord', 'Discord'), ('slack', 'Slack'), ('tiktok', 'TikTok'), ('pinterest', 'Pinterest'), ('reddit', 'Reddit'), ('medium', 'Medium'), ('behance', 'Behance'), ('dribbble', 'Dribbble'), ('stackoverflow', 'Stack Overflow'), ('gitlab', 'GitLab'), ('bitbucket', 'Bitbucket'), ('mastodon', 'Mastodon'), ('threads', 'Threads'), ('snapchat', 'Snapchat'), ('twitch', 'Twitch'), ('spotify', 'Spotify'), ('soundcloud', 'SoundCloud'), ('other', 'Other Social Platform')], 'help_text': 'Social media platform', 'label': 'Social Platform', 'required': False}), 56: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('personal', 'Personal Website'), ('portfolio', 'Portfolio'), ('blog', 'Blog/Newsletter'), ('company', 'Company Website'), ('project', 'Project Site'), ('ecommerce', 'E-commerce Store'), ('educational', 'Educational'), ('documentation', 'Documentation'), ('forum', 'Forum/Community'), ('wiki', 'Wiki/KB'), ('dashboard', 'Dashboard/Admin'), ('landing', 'Landing Page'), ('saas', 'SaaS Application'), ('api', 'API/Docs'), ('other_website', 'Other Website Type')], 'help_text': 'Type of website', 'label': 'Website Type', 'required': False}), 57: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('upwork', 'Upwork/Freelancer'), ('fiverr', 'Fiverr'), ('toptal', 'Toptal'), ('angel', 'AngelList'), ('crunchbase', 'Crunchbase'), ('producthunt', 'Product Hunt'), ('indiehackers', 'Indie Hackers'), ('clutch', 'Clutch'), ('glassdoor', 'Glassdoor'), ('resume', 'Resume/CV'), ('calendly', 'Calendly/Booking'), ('other_professional', 'Other Professional')], 'help_text': 'Professional platform type', 'label': 'Professional Platform', 'required': False}), 58: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('email', 'Email Address'), ('phone', 'Phone Number'), ('whatsapp', 'WhatsApp'), ('signal', 'Signal'), ('telegram', 'Telegram'), ('skype', 'Skype'), ('zoom', 'Zoom'), ('meet', 'Google Meet'), ('teams', 'Microsoft Teams'), ('address', 'Physical Address'), ('other_contact', 'Other Contact Method')], 'help_text': 'Type of contact method', 'label': 'Contact Method', 'required': False}), 59: ('wagtail.blocks.CharBlock', (), {'help_text': "Custom type name for 'Other' selections", 'label': 'Custom Type', 'max_length': 100, 'required': False}), 60: ('wagtail.blocks.URLBlock', (), {'help_text': 'Full URL to the profile/website', 'label': 'Profile URL', 'required': False}), 61: ('wagtail.blocks.CharBlock', (), {'help_text': 'Username, handle, or identifier for the profile', 'label': 'Username/Handle/ID', 'required': False}), 62: ('wagtail.blocks.CharBlock', (), {'help_text': 'Value (email, phone number, etc.)', 'label': 'Value', 'required': False}), 63: ('wagtail.blocks.TextBlock', (), {'help_text': 'Brief description or purpose', 'label': 'Description', 'required': False}), 64: ('wagtail.images.blocks.ImageChooserBlock', (), {'help_text': 'Profile picture, logo, or screenshot', 'label': 'Thumbnail/Logo', 'required': False}), 65: ('wagtail.blocks.CharBlock', (), {'default': '', 'help_text': "CSS classes for icon (e.g., 'fab fa-linkedin')", 'label': 'Icon CSS Class', 'required': False}), 66: ('wagtail.blocks.CharBlock', (), {'help_text': 'Hex color code (e.g., #0077B5 for LinkedIn)', 'label': 'Brand Color', 'max_length': 7, 'required': False}), 67: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Main/default profile for this type', 'label': 'Primary Profile', 'required': False}), 68: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'help_text': 'Show this profile publicly', 'label': 'Public', 'required': False}), 69: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Mark as verified/confirmed', 'label': 'Verified', 'required': False}), 70: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'help_text': 'Open link in new browser tab', 'label': 'Open in New Tab', 'required': False}), 71: ('wagtail.blocks.IntegerBlock', (), {'default': 0, 'help_text': 'Higher numbers appear first (0 = default)', 'label': 'Display Priority', 'max_value': 10, 'min_value': -10, 'required': False}), 72: ('wagtail.blocks.DateTimeBlock', (), {'help_text': 'When this profile was last confirmed', 'label': 'Last Verified', 'required': False}), 73: ('wagtail.blocks.TextBlock', (), {'help_text': 'Private notes for editors', 'label': 'Internal Notes', 'required': False}), 74: ('wagtail.blocks.StructBlock', [[('custom_css_id', 0), ('custom_css_class', 1), ('data_attributes', 2), ('is_visible', 3), ('profile_type', 53), ('title', 54), ('social_platform', 55), ('website_type', 56), ('professional_type', 57), ('contact_type', 58), ('custom_type', 59), ('url', 60), ('username', 61), ('value', 62), ('description', 63), ('thumbnail', 64), ('icon_class', 65), ('color', 66), ('is_primary', 67), ('is_public', 68), ('verified', 69), ('open_in_new_tab', 70), ('priority', 71), ('last_verified', 72), ('notes', 73)]], {})}, help_text='Add social links, certifications, projects, and more', verbose_name='Additional Profile Content')),
                ('slug', models.SlugField(blank=True, help_text='URL-friendly version of the profile', max_length=255, null=True, unique=True, verbose_name='Slug')),
                ('metadata', models.JSONField(blank=True, default=dict, help_text='Additional structured data for the profile', verbose_name='Metadata')),
                ('reputation_score', models.IntegerField(default=0, help_text='Gamification score based on activity', verbose_name='Reputation Score')),
                ('level', models.IntegerField(default=1, help_text='User level based on reputation', verbose_name='Level')),
                ('languages_spoken', models.JSONField(blank=True, default=list, help_text='List of languages spoken (ISO codes)', verbose_name='Languages Spoken')),
                ('is_available_for_hire', models.BooleanField(default=False, verbose_name='Available for Hire')),
                ('is_available_for_mentoring', models.BooleanField(default=False, verbose_name='Available for Mentoring')),
                ('onboarding_status', models.JSONField(blank=True, default=dict, help_text='Tracking of onboarding steps completed', verbose_name='Onboarding Status')),
                ('data_export_requested_at', models.DateTimeField(blank=True, null=True, verbose_name='Data Export Requested At')),
                ('account_deletion_requested_at', models.DateTimeField(blank=True, null=True, verbose_name='Account Deletion Requested At')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this record', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('linked_profile', models.ForeignKey(blank=True, help_text='Linked system profile for additional settings', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='linked_profiles', to='pipelines.person', verbose_name='Linked System Profile')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last updated this record', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
                ('user', models.OneToOneField(help_text='Linked Django/Wagtail user account', on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL, verbose_name='User Account')),
            ],
            options={
                'verbose_name': 'Profile',
                'verbose_name_plural': 'Profiles',
                'db_table': 'profiles',
                'ordering': ['-created_at', 'full_name'],
                'permissions': [('view_profile_stats', 'Can view profile statistics'), ('export_profiles', 'Can export profile data'), ('can_manage_profiles', 'Can manage all profiles'), ('can_view_sensitive_data', 'Can view sensitive profile data'), ('can_invite_profiles', 'Can invite new profiles'), ('can_share_profiles', 'Can share profile data'), ('can_impersonate_profile', 'Can impersonate profile')],
            },
        ),
        migrations.CreateModel(
            name='NewsletterSubscription',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
                ('is_active', models.BooleanField(default=True, help_text='Indicates whether this record is active', verbose_name='Is Active')),
                ('live', models.BooleanField(default=True, help_text='Whether this record is publicly accessible', verbose_name='Live')),
                ('first_published_at', models.DateTimeField(blank=True, null=True, verbose_name='First Published At')),
                ('last_published_at', models.DateTimeField(blank=True, null=True, verbose_name='Last Published At')),
                ('search_description', models.TextField(blank=True, help_text='Description for search engines and social sharing', verbose_name='Search description')),
                ('email', models.EmailField(help_text='Primary contact email for receiving newsletters.', max_length=254, verbose_name='Email Address')),
                ('is_subscribed', models.BooleanField(default=True, help_text='Uncheck to unsubscribe from this newsletter type.', verbose_name='Is Subscribed')),
                ('subscription_type', models.CharField(choices=[('ALL', 'All Newsletters'), ('IMPORTANT', 'Important Announcements Only'), ('COURSE', 'Course-related Updates'), ('DEPARTMENT', 'Department News Only')], default='ALL', max_length=20, verbose_name='Subscription Type')),
                ('preferred_format', models.CharField(choices=[('HTML', 'HTML'), ('TEXT', 'Plain Text')], default='HTML', help_text='Preferred newsletter format.', max_length=10, verbose_name='Preferred Format')),
                ('last_sent', models.DateTimeField(blank=True, null=True, verbose_name='Last Newsletter Sent')),
                ('unsubscribed_at', models.DateTimeField(blank=True, help_text='Date and time when user unsubscribed.', null=True, verbose_name='Unsubscribed At')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this record', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last updated this record', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
                ('person', models.ForeignKey(blank=True, help_text='Linked user account (optional for guest subscribers).', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='newsletter_subscriptions', to='pipelines.person', verbose_name='User')),
            ],
            options={
                'verbose_name': 'Newsletter Subscription',
                'verbose_name_plural': 'Newsletter Subscriptions',
                'ordering': ['-created_at'],
            },
        ),
        migrations.CreateModel(
            name='PersonTagCategory',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(help_text='Display name for the category', max_length=100, unique=True, verbose_name='Category Name')),
                ('slug', models.SlugField(help_text='URL-friendly version of the name', max_length=100, unique=True, verbose_name='Slug')),
                ('description', wagtail.fields.RichTextField(blank=True, help_text='Detailed description of the category purpose', verbose_name='Description')),
                ('short_description', models.CharField(blank=True, help_text='Brief summary for listings', max_length=200, verbose_name='Short Description')),
                ('color', models.CharField(blank=True, default='#6B7280', help_text='Category color in hex format (e.g., #3B82F6)', max_length=7, verbose_name='Color')),
                ('icon', models.CharField(blank=True, help_text='Icon class or SVG name for this category', max_length=100, verbose_name='Icon')),
                ('visibility', models.IntegerField(choices=[(0, 'Private'), (1, 'Protected'), (2, 'Public')], default=2, help_text='Who can see this category', verbose_name='Visibility Level')),
                ('display_order', models.PositiveIntegerField(default=0, help_text='Order in which categories appear (lower numbers first)', verbose_name='Display Order')),
                ('is_featured', models.BooleanField(default=False, help_text='Highlight this category in listings', verbose_name='Featured Category')),
                ('max_tags_per_item', models.PositiveIntegerField(blank=True, help_text='Maximum number of tags from this category that can be assigned to an item (leave blank for unlimited)', null=True, verbose_name='Max Tags Per Item')),
                ('require_approval', models.BooleanField(default=False, help_text='New tags in this category require administrator approval', verbose_name='Require Approval')),
                ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
                ('last_used', models.DateTimeField(blank=True, editable=False, null=True, verbose_name='Last Used')),
                ('allow_multiple', models.BooleanField(default=True, help_text='Allow multiple tags from this category on a single person', verbose_name='Allow Multiple Tags')),
                ('applies_to_user_type', models.ManyToManyField(blank=True, help_text='User types/groups this category applies to', to='auth.group', verbose_name='Applies to User Types')),
                ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(class)s', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
            ],
            options={
                'verbose_name': 'Person Tag Category',
                'verbose_name_plural': 'Person Tag Categories',
                'db_table': 'person_tag_categories',
            },
        ),
        migrations.CreateModel(
            name='PersonTag',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100, unique=True, verbose_name='name')),
                ('slug', models.SlugField(allow_unicode=True, max_length=100, unique=True, verbose_name='slug')),
                ('description', wagtail.fields.RichTextField(blank=True, help_text='Detailed description of the tag', verbose_name='Description')),
                ('short_description', models.CharField(blank=True, help_text='Brief summary for tooltips and listings', max_length=200, verbose_name='Short Description')),
                ('color', models.CharField(blank=True, default='#6B7280', help_text='Tag color in hex format', max_length=7, verbose_name='Color')),
                ('icon', models.CharField(blank=True, help_text='Icon class or SVG name', max_length=100, verbose_name='Icon')),
                ('importance', models.IntegerField(choices=[(1, 'Low'), (2, 'Medium'), (3, 'High'), (4, 'Critical')], default=2, help_text='How important is this tag', verbose_name='Importance Level')),
                ('visibility', models.IntegerField(choices=[(0, 'Private'), (1, 'Protected'), (2, 'Public')], default=2, help_text='Who can see this tag', verbose_name='Visibility Level')),
                ('meta_title', models.CharField(blank=True, help_text='Title for SEO (leave blank to use tag name)', max_length=200, verbose_name='Meta Title')),
                ('meta_description', models.TextField(blank=True, help_text='Description for SEO (leave blank to use tag description)', verbose_name='Meta Description')),
                ('meta_keywords', models.CharField(blank=True, help_text='Comma-separated keywords for SEO', max_length=500, verbose_name='Meta Keywords')),
                ('usage_count', models.PositiveIntegerField(default=0, editable=False, verbose_name='Usage Count')),
                ('view_count', models.PositiveIntegerField(default=0, editable=False, verbose_name='View Count')),
                ('click_count', models.PositiveIntegerField(default=0, editable=False, verbose_name='Click Count')),
                ('last_used', models.DateTimeField(blank=True, editable=False, null=True, verbose_name='Last Used')),
                ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
                ('average_rating', models.FloatField(default=0.0, editable=False, verbose_name='Average Rating')),
                ('relevance_score', models.FloatField(default=0.0, editable=False, verbose_name='Relevance Score')),
                ('expiration_date', models.DateTimeField(blank=True, help_text='Date when this tag automatically expires', null=True, verbose_name='Expiration Date')),
                ('requires_verification', models.BooleanField(default=False, help_text='This tag requires manual verification', verbose_name='Requires Verification')),
                ('verified_at', models.DateTimeField(blank=True, null=True, verbose_name='Verified At')),
                ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(class)s_tags', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('synonyms', models.ManyToManyField(blank=True, help_text='Tags with similar meaning', to='pipelines.persontag', verbose_name='Synonyms')),
                ('verified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='verified_tags', to=settings.AUTH_USER_MODEL, verbose_name='Verified By')),
                ('category', models.ForeignKey(blank=True, help_text='Category this tag belongs to', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tags', to='pipelines.persontagcategory', verbose_name='Category')),
            ],
            options={
                'verbose_name': 'Person Tag',
                'verbose_name_plural': 'Person Tags',
                'db_table': 'person_tags',
            },
        ),
        migrations.CreateModel(
            name='SiteSettings',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('live', models.BooleanField(default=True, editable=False, verbose_name='live')),
                ('has_unpublished_changes', models.BooleanField(default=False, editable=False, verbose_name='has unpublished changes')),
                ('first_published_at', models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='first published at')),
                ('last_published_at', models.DateTimeField(editable=False, null=True, verbose_name='last published at')),
                ('go_live_at', models.DateTimeField(blank=True, null=True, verbose_name='go live date/time')),
                ('expire_at', models.DateTimeField(blank=True, null=True, verbose_name='expiry date/time')),
                ('expired', models.BooleanField(default=False, editable=False, verbose_name='expired')),
                ('site_name', models.CharField(default='CTC Hub', help_text='Main brand name used across the website.', max_length=150, verbose_name='Site Name')),
                ('tagline', models.CharField(blank=True, default='Empowering Digital Transformation', help_text='Short descriptive slogan displayed near logo or headers.', max_length=255, verbose_name='Tagline')),
                ('language', models.CharField(choices=[('en', 'English'), ('fr', 'French'), ('de', 'German'), ('es', 'Spanish'), ('ar', 'العربيّة')], default='en', help_text="Language code for these settings (e.g., 'en', 'fr').", max_length=10, verbose_name='Language Code')),
                ('active', models.BooleanField(default=False, help_text='Designates whether these settings are active for this language. Only one active per language.', verbose_name='Active')),
                ('title_suffix', models.CharField(default=' | CTC Hub', help_text="Suffix for <title> tag, e.g. ' | Company Name'", max_length=255, verbose_name='Title suffix')),
                ('meta_description', models.TextField(blank=True, default='CTC Hub delivers innovative web, mobile, and cloud-based digital solutions for forward-thinking businesses.', verbose_name='META description')),
                ('meta_keywords', models.TextField(blank=True, default='CTC, digital transformation, software, AI, technology, innovation', verbose_name='META Keywords')),
                ('meta_author', models.CharField(blank=True, default='CTC Hub Team', max_length=255, verbose_name='META Author')),
                ('favicon', models.ForeignKey(blank=True, help_text='Small icon used in browser tabs and bookmarks.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Favicon')),
                ('latest_revision', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.revision', verbose_name='latest revision')),
                ('live_revision', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.revision', verbose_name='live revision')),
                ('logo', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Logo')),
            ],
            options={
                'verbose_name': 'Site Settings',
                'verbose_name_plural': 'Site Settings',
            },
            bases=(wagtail.models.preview.PreviewableMixin, models.Model, modelsearch.index.Indexed),
        ),
        migrations.CreateModel(
            name='SocialSettings',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('live', models.BooleanField(default=True, editable=False, verbose_name='live')),
                ('has_unpublished_changes', models.BooleanField(default=False, editable=False, verbose_name='has unpublished changes')),
                ('first_published_at', models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='first published at')),
                ('last_published_at', models.DateTimeField(editable=False, null=True, verbose_name='last published at')),
                ('go_live_at', models.DateTimeField(blank=True, null=True, verbose_name='go live date/time')),
                ('expire_at', models.DateTimeField(blank=True, null=True, verbose_name='expiry date/time')),
                ('expired', models.BooleanField(default=False, editable=False, verbose_name='expired')),
                ('description', models.TextField(blank=True, default='We connect innovation with strategy — empowering brands to grow through technology.', verbose_name='Footer Description')),
                ('phone_number', models.CharField(blank=True, default='+1 800 123 4567', max_length=24, verbose_name='Phone number')),
                ('whatsapp_number', models.CharField(blank=True, default='+1 800 765 4321', help_text='Optional WhatsApp business contact.', max_length=24, verbose_name='WhatsApp number')),
                ('email', models.EmailField(blank=True, default='info@ctchub.com', max_length=254, verbose_name='Email')),
                ('support_email', models.EmailField(blank=True, default='support@ctchub.com', max_length=254, verbose_name='Support Email')),
                ('address', models.TextField(blank=True, default='123 Innovation Drive, San Francisco, CA 94105', verbose_name='Address')),
                ('google_maps_link', models.URLField(blank=True, help_text='Optional map link for location directions.', verbose_name='Google Maps Link')),
                ('organisation_url', models.URLField(blank=True, default='https://www.ctchub.com', verbose_name='Organisation URL')),
                ('additional_info', models.TextField(blank=True, default='Open Monday – Friday, 9:00am – 6:00pm (PST).', verbose_name='Additional Information')),
                ('social_links', wagtail.fields.StreamField([('link', 9)], blank=True, block_lookup={0: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('linkedin', 'LinkedIn'), ('twitter', 'Twitter/X'), ('facebook', 'Facebook'), ('instagram', 'Instagram'), ('github', 'GitHub'), ('youtube', 'YouTube'), ('whatsapp', 'WhatsApp'), ('telegram', 'Telegram'), ('portfolio', 'Portfolio'), ('website', 'Personal Website'), ('other', 'Other Platform')], 'label': 'Platform'}), 1: ('wagtail.blocks.CharBlock', (), {'help_text': 'Your username on this platform', 'label': 'Username/Handle', 'required': False}), 2: ('wagtail.blocks.URLBlock', (), {'help_text': 'Full URL to your profile (auto-generated if blank)', 'label': 'Profile URL', 'required': False}), 3: ('wagtail.blocks.CharBlock', (), {'help_text': "If 'Other Platform' is selected, specify the platform name", 'label': 'Custom Platform Name', 'max_length': 50, 'required': False}), 4: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Mark as primary profile for this platform', 'label': 'Primary Profile', 'required': False}), 5: ('wagtail.blocks.BooleanBlock', (), {'default': True, 'help_text': 'Show this profile publicly', 'label': 'Public Profile', 'required': False}), 6: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Mark as verified if confirmed', 'label': 'Verified', 'required': False}), 7: ('wagtail.blocks.CharBlock', (), {'default': '', 'help_text': 'Optional CSS class for custom icons (e.g., FontAwesome classes).', 'label': 'Icon CSS Class', 'required': False}), 8: ('wagtail.blocks.TextBlock', (), {'help_text': 'Additional notes about this profile', 'label': 'Notes', 'required': False}), 9: ('wagtail.blocks.StructBlock', [[('platform', 0), ('username', 1), ('profile_url', 2), ('custom_platform', 3), ('is_primary', 4), ('is_public', 5), ('verified', 6), ('icon_class', 7), ('notes', 8)]], {})}, help_text='Add links to your social media profiles', verbose_name='Social links')),
                ('language', models.CharField(choices=[('en', 'English'), ('fr', 'French'), ('de', 'German'), ('es', 'Spanish'), ('ar', 'العربيّة')], default='en', help_text="Language code for these settings (e.g., 'en', 'fr').", max_length=10, verbose_name='Language Code')),
                ('active', models.BooleanField(default=False, help_text='Designates whether these settings are active for this language. Only one active per language.', verbose_name='Active')),
                ('latest_revision', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.revision', verbose_name='latest revision')),
                ('live_revision', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.revision', verbose_name='live revision')),
            ],
            options={
                'verbose_name': 'Social & Contact Settings',
                'verbose_name_plural': 'Social & Contact Settings',
            },
            bases=(wagtail.models.preview.PreviewableMixin, models.Model, modelsearch.index.Indexed),
        ),
        migrations.CreateModel(
            name='Tag',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100, unique=True, verbose_name='name')),
                ('slug', models.SlugField(allow_unicode=True, max_length=100, unique=True, verbose_name='slug')),
                ('description', wagtail.fields.RichTextField(blank=True, help_text='Detailed description of the tag', verbose_name='Description')),
                ('short_description', models.CharField(blank=True, help_text='Brief summary for tooltips and listings', max_length=200, verbose_name='Short Description')),
                ('color', models.CharField(blank=True, default='#6B7280', help_text='Tag color in hex format', max_length=7, verbose_name='Color')),
                ('icon', models.CharField(blank=True, help_text='Icon class or SVG name', max_length=100, verbose_name='Icon')),
                ('importance', models.IntegerField(choices=[(1, 'Low'), (2, 'Medium'), (3, 'High'), (4, 'Critical')], default=2, help_text='How important is this tag', verbose_name='Importance Level')),
                ('visibility', models.IntegerField(choices=[(0, 'Private'), (1, 'Protected'), (2, 'Public')], default=2, help_text='Who can see this tag', verbose_name='Visibility Level')),
                ('meta_title', models.CharField(blank=True, help_text='Title for SEO (leave blank to use tag name)', max_length=200, verbose_name='Meta Title')),
                ('meta_description', models.TextField(blank=True, help_text='Description for SEO (leave blank to use tag description)', verbose_name='Meta Description')),
                ('meta_keywords', models.CharField(blank=True, help_text='Comma-separated keywords for SEO', max_length=500, verbose_name='Meta Keywords')),
                ('usage_count', models.PositiveIntegerField(default=0, editable=False, verbose_name='Usage Count')),
                ('view_count', models.PositiveIntegerField(default=0, editable=False, verbose_name='View Count')),
                ('click_count', models.PositiveIntegerField(default=0, editable=False, verbose_name='Click Count')),
                ('last_used', models.DateTimeField(blank=True, editable=False, null=True, verbose_name='Last Used')),
                ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
                ('average_rating', models.FloatField(default=0.0, editable=False, verbose_name='Average Rating')),
                ('relevance_score', models.FloatField(default=0.0, editable=False, verbose_name='Relevance Score')),
                ('content_type', models.ForeignKey(blank=True, help_text='Content type this tag is primarily associated with', null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')),
                ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(class)s_tags', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('synonyms', models.ManyToManyField(blank=True, help_text='Tags with similar meaning', to='pipelines.tag', verbose_name='Synonyms')),
            ],
            options={
                'verbose_name': 'Tag',
                'verbose_name_plural': 'Tags',
                'ordering': ['name'],
            },
        ),
        migrations.CreateModel(
            name='TagAnalytics',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('date', models.DateField()),
                ('views', models.PositiveIntegerField(default=0)),
                ('clicks', models.PositiveIntegerField(default=0)),
                ('applications', models.PositiveIntegerField(default=0)),
                ('removals', models.PositiveIntegerField(default=0)),
                ('unique_users', models.PositiveIntegerField(default=0)),
                ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='analytics', to='pipelines.persontag')),
            ],
            options={
                'verbose_name': 'Tag Analytics',
                'verbose_name_plural': 'Tag Analytics',
                'ordering': ['-date'],
            },
        ),
        migrations.CreateModel(
            name='TaggedPerson',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('object_id', models.CharField(max_length=255)),
                ('notes', wagtail.fields.RichTextField(blank=True, help_text='Additional notes about this tagging', verbose_name='Notes')),
                ('confidence', models.FloatField(default=1.0, help_text='Confidence in this tagging (0.0 to 1.0)', validators=[django.core.validators.MinValueValidator(0.0), django.core.validators.MaxValueValidator(1.0)], verbose_name='Confidence Score')),
                ('importance', models.IntegerField(choices=[(1, 'Low'), (2, 'Medium'), (3, 'High'), (4, 'Critical')], default=2, help_text='How important is this tag for this specific person', verbose_name='Importance for this item')),
                ('verified_at', models.DateTimeField(blank=True, null=True, verbose_name='Verified At')),
                ('start_date', models.DateTimeField(blank=True, help_text='When this tag becomes active', null=True, verbose_name='Start Date')),
                ('end_date', models.DateTimeField(blank=True, help_text='When this tag expires', null=True, verbose_name='End Date')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_persons', to='contenttypes.contenttype')),
                ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_tag_assignments', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_persons', to='pipelines.persontag')),
                ('verified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='verified_tag_assignments', to=settings.AUTH_USER_MODEL, verbose_name='Verified By')),
            ],
            options={
                'verbose_name': 'Tagged Person',
                'verbose_name_plural': 'Tagged Persons',
                'db_table': 'person_tagged_items',
                'ordering': ['-importance', '-confidence', '-created_at'],
            },
        ),
        migrations.AddField(
            model_name='person',
            name='tags',
            field=taggit.managers.TaggableManager(blank=True, help_text='Skills and tags associated with this profile', through='pipelines.TaggedPerson', to='pipelines.PersonTag', verbose_name='Tags/Skills'),
        ),
        migrations.CreateModel(
            name='TagHistory',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('action', models.CharField(choices=[('create', 'Created'), ('update', 'Updated'), ('delete', 'Deleted'), ('merge', 'Merged'), ('publish', 'Published'), ('unpublish', 'Unpublished'), ('approve', 'Approved'), ('reject', 'Rejected')], max_length=20)),
                ('changes', models.JSONField(default=dict, help_text='JSON object containing changed fields')),
                ('notes', models.TextField(blank=True)),
                ('ip_address', models.GenericIPAddressField(blank=True, null=True)),
                ('user_agent', models.TextField(blank=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'Tag History',
                'verbose_name_plural': 'Tag Histories',
                'ordering': ['-created_at'],
            },
        ),
        migrations.CreateModel(
            name='TagRelationship',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('relationship_type', models.CharField(choices=[('related', 'Related'), ('parent', 'Parent'), ('child', 'Child'), ('requires', 'Requires'), ('conflicts', 'Conflicts'), ('similar', 'Similar')], default='related', max_length=20)),
                ('strength', models.FloatField(default=1.0, help_text='Strength of relationship (0.0 to 1.0)')),
                ('description', models.TextField(blank=True, help_text='Description of the relationship')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
            ],
            options={
                'ordering': ['-strength', 'relationship_type'],
                'unique_together': {('relationship_type',)},
            },
        ),
        migrations.CreateModel(
            name='Token',
            fields=[
                ('id', models.AutoField(editable=False, primary_key=True, serialize=False)),
                ('jti', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, help_text='Unique identifier for JWT token', unique=True, verbose_name='JWT ID')),
                ('token', models.TextField(blank=True, help_text='Token value for authentication', null=True)),
                ('token_type', models.CharField(choices=[('access', 'Access'), ('refresh', 'Refresh'), ('sliding', 'Sliding')], help_text='Type of token', max_length=10)),
                ('secret', models.CharField(blank=True, help_text='Secure secret for token validation', max_length=64, null=True)),
                ('is_revoked', models.BooleanField(default=False)),
                ('is_deleted', models.BooleanField(default=False)),
                ('usage', models.CharField(choices=[('api', 'API'), ('web', 'Web'), ('mobile', 'Mobile')], default='api', help_text='Usage context for the token', max_length=20)),
                ('session_token', models.CharField(blank=True, db_index=True, help_text='Session ID associated with the token', max_length=64, null=True)),
                ('preferences', models.JSONField(blank=True, default=list, help_text='Token preferences and metadata')),
                ('iat', models.DateTimeField(auto_now_add=True, help_text='When the token was issued', verbose_name='Issued At')),
                ('exp', models.DateTimeField(blank=True, help_text='When the token expires', null=True, verbose_name='Expires At')),
                ('last_used', models.DateTimeField(blank=True, help_text='Last time the token was used', null=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('parent', models.ForeignKey(blank=True, help_text='Parent token (refresh token for access tokens)', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='pipelines.token')),
                ('user', models.ForeignKey(help_text='The user this token was issued for.', on_delete=django.db.models.deletion.CASCADE, related_name='tokens', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'Bearer Token',
                'verbose_name_plural': 'Bearer Tokens',
                'db_table': 'tokens',
                'ordering': ['-created_at'],
            },
        ),
        migrations.AddIndex(
            model_name='emailtemplate',
            index=models.Index(fields=['template_type', 'is_active'], name='pipelines_e_templat_94144e_idx'),
        ),
        migrations.AddIndex(
            model_name='emailtemplate',
            index=models.Index(fields=['language', 'is_active'], name='pipelines_e_languag_0c3715_idx'),
        ),
        migrations.AddIndex(
            model_name='emailtemplate',
            index=models.Index(fields=['is_default', 'is_active'], name='pipelines_e_is_defa_c53b54_idx'),
        ),
        migrations.AddIndex(
            model_name='emailtemplate',
            index=models.Index(fields=['template_source'], name='pipelines_e_templat_d79679_idx'),
        ),
        migrations.AddIndex(
            model_name='emailtemplate',
            index=models.Index(fields=['cache_key'], name='pipelines_e_cache_k_3ad8ec_idx'),
        ),
        migrations.AddIndex(
            model_name='emailtemplate',
            index=models.Index(fields=['go_live_at'], name='pipelines_e_go_live_46cfba_idx'),
        ),
        migrations.AddIndex(
            model_name='emailtemplate',
            index=models.Index(fields=['expire_at'], name='pipelines_e_expire__4e827a_idx'),
        ),
        migrations.AddIndex(
            model_name='emailtemplate',
            index=models.Index(fields=['category'], name='pipelines_e_categor_e5e797_idx'),
        ),
        migrations.AddIndex(
            model_name='emailtemplate',
            index=models.Index(fields=['is_draft', 'is_active'], name='pipelines_e_is_draf_f713c4_idx'),
        ),
        migrations.AlterUniqueTogether(
            name='emailtemplate',
            unique_together={('template_type', 'language', 'is_default', 'version')},
        ),
        migrations.AlterUniqueTogether(
            name='newsletter',
            unique_together={('translation_key', 'locale')},
        ),
        migrations.AlterUniqueTogether(
            name='newslettersubscription',
            unique_together={('email', 'subscription_type')},
        ),
        migrations.AddIndex(
            model_name='persontag',
            index=models.Index(fields=['name'], name='person_tags_name_721db5_idx'),
        ),
        migrations.AddIndex(
            model_name='persontag',
            index=models.Index(fields=['usage_count'], name='person_tags_usage_c_85af51_idx'),
        ),
        migrations.AddIndex(
            model_name='persontag',
            index=models.Index(fields=['importance', 'usage_count'], name='person_tags_importa_053671_idx'),
        ),
        migrations.AddIndex(
            model_name='persontag',
            index=models.Index(fields=['created_at'], name='person_tags_created_89fdd9_idx'),
        ),
        migrations.AddIndex(
            model_name='persontag',
            index=models.Index(fields=['last_used'], name='person_tags_last_us_0b9eb1_idx'),
        ),
        migrations.AddIndex(
            model_name='persontag',
            index=models.Index(fields=['relevance_score'], name='person_tags_relevan_f3c969_idx'),
        ),
        migrations.AddIndex(
            model_name='persontag',
            index=models.Index(fields=['category', 'importance'], name='person_tags_categor_d58af4_idx'),
        ),
        migrations.AddIndex(
            model_name='persontag',
            index=models.Index(fields=['expiration_date'], name='person_tags_expirat_2b11a2_idx'),
        ),
        migrations.AddIndex(
            model_name='persontag',
            index=models.Index(fields=['requires_verification', 'verified_at'], name='person_tags_require_39f35b_idx'),
        ),
        migrations.AddConstraint(
            model_name='sitesettings',
            constraint=models.UniqueConstraint(condition=models.Q(('active', True)), fields=('language',), name='unique_active_site_settings_per_language'),
        ),
        migrations.AddConstraint(
            model_name='socialsettings',
            constraint=models.UniqueConstraint(condition=models.Q(('active', True)), fields=('language',), name='unique_active_social_settings_per_language'),
        ),
        migrations.AddIndex(
            model_name='tag',
            index=models.Index(fields=['name'], name='pipelines_t_name_5403b2_idx'),
        ),
        migrations.AddIndex(
            model_name='tag',
            index=models.Index(fields=['usage_count'], name='pipelines_t_usage_c_29c5a6_idx'),
        ),
        migrations.AddIndex(
            model_name='tag',
            index=models.Index(fields=['importance', 'usage_count'], name='pipelines_t_importa_bd8587_idx'),
        ),
        migrations.AddIndex(
            model_name='tag',
            index=models.Index(fields=['created_at'], name='pipelines_t_created_03b76f_idx'),
        ),
        migrations.AddIndex(
            model_name='tag',
            index=models.Index(fields=['last_used'], name='pipelines_t_last_us_f7b5e8_idx'),
        ),
        migrations.AddIndex(
            model_name='tag',
            index=models.Index(fields=['relevance_score'], name='pipelines_t_relevan_e5e69d_idx'),
        ),
        migrations.AddIndex(
            model_name='tag',
            index=models.Index(fields=['content_type'], name='pipelines_t_content_4d2d69_idx'),
        ),
        migrations.AlterUniqueTogether(
            name='taganalytics',
            unique_together={('tag', 'date')},
        ),
        migrations.AddIndex(
            model_name='taggedperson',
            index=models.Index(fields=['content_type', 'object_id'], name='person_tagg_content_4b0178_idx'),
        ),
        migrations.AddIndex(
            model_name='taggedperson',
            index=models.Index(fields=['start_date', 'end_date'], name='person_tagg_start_d_3f97ce_idx'),
        ),
        migrations.AddIndex(
            model_name='taggedperson',
            index=models.Index(fields=['importance'], name='person_tagg_importa_6ac818_idx'),
        ),
        migrations.AddIndex(
            model_name='taggedperson',
            index=models.Index(fields=['confidence'], name='person_tagg_confide_48f072_idx'),
        ),
        migrations.AddIndex(
            model_name='taggedperson',
            index=models.Index(fields=['created_at'], name='person_tagg_created_2de998_idx'),
        ),
        migrations.AlterUniqueTogether(
            name='taggedperson',
            unique_together={('content_type', 'object_id', 'tag')},
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['user'], name='profiles_user_id_29277a_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['email'], name='profiles_email_2f292b_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['is_registered'], name='profiles_is_regi_19005b_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['status'], name='profiles_status_0dafe7_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['profile_type'], name='profiles_profile_3cdb9f_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['created_at'], name='profiles_created_cbafd1_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['updated_at'], name='profiles_updated_7c22e2_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['slug'], name='profiles_slug_a9ab23_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['country', 'city'], name='profiles_country_61d005_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['last_active'], name='profiles_last_ac_8ceaaf_idx'),
        ),
        migrations.AddIndex(
            model_name='person',
            index=models.Index(fields=['profile_completion'], name='profiles_profile_d24a44_idx'),
        ),
        migrations.AddIndex(
            model_name='token',
            index=models.Index(fields=['user', 'token_type', 'is_revoked'], name='tokens_user_id_d54023_idx'),
        ),
        migrations.AddIndex(
            model_name='token',
            index=models.Index(fields=['jti'], name='tokens_jti_910755_idx'),
        ),
        migrations.AddIndex(
            model_name='token',
            index=models.Index(fields=['session_token'], name='tokens_session_5958d0_idx'),
        ),
        migrations.AddIndex(
            model_name='token',
            index=models.Index(fields=['exp'], name='tokens_exp_e89627_idx'),
        ),
        migrations.AddIndex(
            model_name='token',
            index=models.Index(fields=['created_at'], name='tokens_created_a3c85e_idx'),
        ),
    ]
