From c2533d9ea2531affc292ade8f40e4ecc6cae12b4 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 10 Sep 2025 21:28:10 +0200 Subject: [PATCH] add migration shortcut --- ...0227_space_ai_default_provider_and_more.py | 1168 +++++++++++++++++ 1 file changed, 1168 insertions(+) create mode 100644 cookbook/migrations/0001_squashed_0227_space_ai_default_provider_and_more.py diff --git a/cookbook/migrations/0001_squashed_0227_space_ai_default_provider_and_more.py b/cookbook/migrations/0001_squashed_0227_space_ai_default_provider_and_more.py new file mode 100644 index 000000000..b7a6ad9cc --- /dev/null +++ b/cookbook/migrations/0001_squashed_0227_space_ai_default_provider_and_more.py @@ -0,0 +1,1168 @@ +# Generated by Django 5.2.6 on 2025-09-10 18:59 + +import annoying.fields +from django_scopes import scopes_disabled + +import cookbook.models +import datetime +import django.contrib.postgres.indexes +import django.contrib.postgres.operations +import django.contrib.postgres.search +import django.core.validators +import django.db.models.deletion +import django.utils.timezone +import django_prometheus.models +import uuid +from django.conf import settings +from django.db import migrations, models +from cookbook.models import SearchFields + + +def allSearchFields(): + return list(SearchFields.objects.values_list('id', flat=True)) + + +def nameSearchField(): + return [SearchFields.objects.get(name='Name').id] + + +def create_default_groups(apps, schema_editor): + with scopes_disabled(): + Group = apps.get_model('auth', 'Group') + Group.objects.bulk_create([ + Group(name=u'guest'), + Group(name=u'user'), + Group(name=u'admin'), + ]) + + +def create_fields(apps, schema_editor): + SearchFields = apps.get_model('cookbook', 'SearchFields') + + SearchFields.objects.create(name='Name', field='name') + SearchFields.objects.create(name='Description', field='description') + SearchFields.objects.create(name='Instructions', field='steps__instruction') + SearchFields.objects.create(name='Ingredients', field='steps__ingredients__food__name') + SearchFields.objects.create(name='Keywords', field='keywords__name') + SearchFields.objects.create(name='Units', field='steps__ingredients__unit__name') + + FoodInheritField = apps.get_model('cookbook', 'FoodInheritField') + + FoodInheritField.objects.create(name='Supermarket Category', field='supermarket_category') + FoodInheritField.objects.create(name='Ignore Shopping', field='ignore_shopping') + FoodInheritField.objects.create(name='Diet', field='diet') + FoodInheritField.objects.create(name='Substitute', field='substitute') + FoodInheritField.objects.create(name='Substitute Children', field='substitute_children') + FoodInheritField.objects.create(name='Substitute Siblings', field='substitute_siblings') + + +class Migration(migrations.Migration): + replaces = [('cookbook', '0001_initial'), ('cookbook', '0002_auto_20191119_2035'), ('cookbook', '0003_enable_pgtrm'), ('cookbook', '0004_storage_created_by'), + ('cookbook', '0005_recipebook_recipebookentry'), ('cookbook', '0006_recipe_image'), ('cookbook', '0007_auto_20191226_0852'), ('cookbook', '0008_mealplan'), + ('cookbook', '0009_auto_20200130_1056'), ('cookbook', '0010_auto_20200130_1059'), ('cookbook', '0011_remove_recipeingredients_unit'), + ('cookbook', '0012_auto_20200130_1116'), ('cookbook', '0013_userpreference'), ('cookbook', '0014_auto_20200213_2332'), ('cookbook', '0015_auto_20200213_2334'), + ('cookbook', '0016_auto_20200213_2335'), ('cookbook', '0017_auto_20200216_2257'), ('cookbook', '0018_auto_20200216_2303'), ('cookbook', '0019_ingredient'), + ('cookbook', '0020_recipeingredient_ingredient'), ('cookbook', '0021_auto_20200216_2309'), ('cookbook', '0022_remove_recipeingredient_name'), + ('cookbook', '0023_auto_20200216_2311'), ('cookbook', '0024_auto_20200216_2313'), ('cookbook', '0025_userpreference_nav_color'), + ('cookbook', '0026_auto_20200219_1605'), ('cookbook', '0027_ingredient_recipe'), ('cookbook', '0028_auto_20200317_1901'), ('cookbook', '0029_auto_20200317_1901'), + ('cookbook', '0030_recipeingredient_note'), ('cookbook', '0031_auto_20200407_1841'), ('cookbook', '0032_userpreference_default_unit'), + ('cookbook', '0033_userpreference_default_page'), ('cookbook', '0034_auto_20200426_1614'), ('cookbook', '0035_auto_20200427_1637'), + ('cookbook', '0036_auto_20200427_1800'), ('cookbook', '0037_userpreference_search_style'), ('cookbook', '0038_auto_20200502_1259'), + ('cookbook', '0039_recipebook_shared'), ('cookbook', '0040_auto_20200502_1433'), ('cookbook', '0041_auto_20200502_1446'), ('cookbook', '0042_cooklog'), + ('cookbook', '0043_auto_20200507_2302'), ('cookbook', '0044_viewlog'), ('cookbook', '0045_userpreference_show_recent'), ('cookbook', '0046_auto_20200602_1133'), + ('cookbook', '0047_auto_20200602_1133'), ('cookbook', '0048_auto_20200602_1140'), ('cookbook', '0049_mealtype_created_by'), ('cookbook', '0050_auto_20200611_1509'), + ('cookbook', '0051_auto_20200611_1518'), ('cookbook', '0052_userpreference_ingredient_decimals'), ('cookbook', '0053_auto_20200611_2217'), + ('cookbook', '0054_sharelink'), ('cookbook', '0055_auto_20200616_1236'), ('cookbook', '0056_auto_20200625_2118'), ('cookbook', '0057_auto_20200625_2127'), + ('cookbook', '0058_auto_20200625_2128'), ('cookbook', '0059_auto_20200625_2137'), ('cookbook', '0060_auto_20200625_2144'), ('cookbook', '0056_auto_20200625_2157'), + ('cookbook', '0061_merge_20200625_2209'), ('cookbook', '0062_auto_20200625_2219'), ('cookbook', '0063_auto_20200625_2230'), ('cookbook', '0064_auto_20200625_2329'), + ('cookbook', '0065_auto_20200626_1444'), ('cookbook', '0066_auto_20200626_1455'), ('cookbook', '0067_auto_20200629_1508'), ('cookbook', '0068_auto_20200629_2127'), + ('cookbook', '0069_auto_20200629_2134'), ('cookbook', '0070_auto_20200701_2007'), ('cookbook', '0071_auto_20200701_2048'), ('cookbook', '0072_step_show_as_header'), + ('cookbook', '0073_auto_20200708_2311'), ('cookbook', '0074_remove_keyword_created_by'), ('cookbook', '0075_shoppinglist_shoppinglistentry_shoppinglistrecipe'), + ('cookbook', '0076_shoppinglist_entries'), ('cookbook', '0077_invitelink'), ('cookbook', '0078_invitelink_used_by'), ('cookbook', '0079_invitelink_group'), + ('cookbook', '0080_auto_20200921_2331'), ('cookbook', '0081_auto_20200921_2349'), ('cookbook', '0082_auto_20200922_1143'), ('cookbook', '0083_space'), + ('cookbook', '0084_auto_20200922_1233'), ('cookbook', '0085_auto_20200922_1235'), ('cookbook', '0086_auto_20200929_1143'), ('cookbook', '0087_auto_20200929_1152'), + ('cookbook', '0088_shoppinglist_finished'), ('cookbook', '0089_auto_20201117_2222'), ('cookbook', '0090_auto_20201214_1359'), + ('cookbook', '0091_auto_20201226_1551'), ('cookbook', '0092_recipe_servings'), ('cookbook', '0093_auto_20201231_1236'), ('cookbook', '0094_auto_20201231_1238'), + ('cookbook', '0095_auto_20210107_1804'), ('cookbook', '0096_auto_20210109_2044'), ('cookbook', '0097_auto_20210113_1315'), ('cookbook', '0098_auto_20210113_1320'), + ('cookbook', '0099_auto_20210113_1518'), ('cookbook', '0100_recipe_servings_text'), ('cookbook', '0101_storage_path'), ('cookbook', '0102_auto_20210125_1147'), + ('cookbook', '0103_food_ignore_shopping'), ('cookbook', '0104_auto_20210125_2133'), ('cookbook', '0105_auto_20210126_1604'), + ('cookbook', '0106_shoppinglist_supermarket'), ('cookbook', '0107_auto_20210128_1535'), ('cookbook', '0108_auto_20210219_1410'), + ('cookbook', '0109_auto_20210221_1204'), ('cookbook', '0110_auto_20210221_1406'), ('cookbook', '0111_space_created_by'), ('cookbook', '0112_remove_synclog_space'), + ('cookbook', '0113_auto_20210317_2017'), ('cookbook', '0114_importlog'), ('cookbook', '0115_telegrambot'), ('cookbook', '0116_auto_20210319_0012'), + ('cookbook', '0117_space_max_recipes'), ('cookbook', '0118_auto_20210406_1805'), ('cookbook', '0119_auto_20210411_2101'), ('cookbook', '0120_bookmarklet'), + ('cookbook', '0121_auto_20210518_1638'), ('cookbook', '0122_auto_20210527_1712'), ('cookbook', '0123_invitelink_email'), + ('cookbook', '0124_alter_userpreference_theme'), ('cookbook', '0125_space_demo'), ('cookbook', '0126_alter_userpreference_theme'), + ('cookbook', '0127_remove_invitelink_username'), ('cookbook', '0128_userfile'), ('cookbook', '0129_auto_20210608_1233'), + ('cookbook', '0130_alter_userfile_file_size_kb'), ('cookbook', '0131_auto_20210608_1929'), ('cookbook', '0132_sharelink_request_count'), + ('cookbook', '0133_sharelink_abuse_blocked'), ('cookbook', '0134_space_allow_sharing'), ('cookbook', '0135_auto_20210615_2210'), + ('cookbook', '0136_auto_20210617_1343'), ('cookbook', '0137_auto_20210617_1501'), ('cookbook', '0138_auto_20210617_1602'), ('cookbook', '0139_space_created_at'), + ('cookbook', '0140_userpreference_created_at'), ('cookbook', '0141_auto_20210713_1042'), ('cookbook', '0142_alter_userpreference_search_style'), + ('cookbook', '0143_build_full_text_index'), ('cookbook', '0144_create_searchfields'), ('cookbook', '0145_alter_userpreference_search_style'), + ('cookbook', '0146_alter_userpreference_use_fractions'), ('cookbook', '0147_keyword_to_tree'), ('cookbook', '0148_auto_20210813_1829'), + ('cookbook', '0149_fix_leading_trailing_spaces'), ('cookbook', '0150_food_to_tree'), ('cookbook', '0151_auto_20210915_1037'), ('cookbook', '0152_automation'), + ('cookbook', '0153_auto_20210915_2327'), ('cookbook', '0154_auto_20210922_1705'), ('cookbook', '0155_mealtype_default'), + ('cookbook', '0156_searchpreference_trigram_threshold'), ('cookbook', '0157_alter_searchpreference_trigram'), ('cookbook', '0158_userpreference_use_kj'), + ('cookbook', '0159_add_shoppinglistentry_fields'), ('cookbook', '0160_delete_shoppinglist_orphans'), ('cookbook', '0161_alter_shoppinglistentry_food'), + ('cookbook', '0162_userpreference_csv_delim'), ('cookbook', '0163_auto_20220105_0758'), ('cookbook', '0164_space_show_facet_count'), + ('cookbook', '0165_remove_step_type'), ('cookbook', '0166_alter_userpreference_shopping_add_onhand'), ('cookbook', '0167_userpreference_left_handed'), + ('cookbook', '0168_add_unit_searchfields'), ('cookbook', '0169_exportlog'), ('cookbook', '0170_auto_20220207_1848'), + ('cookbook', '0171_alter_searchpreference_trigram_threshold'), ('cookbook', '0172_ingredient_original_text'), ('cookbook', '0173_recipe_source_url'), + ('cookbook', '0174_alter_food_substitute_userspace'), ('cookbook', '0175_remove_userpreference_space'), + ('cookbook', '0176_alter_searchpreference_icontains_and_more'), ('cookbook', '0177_recipe_show_ingredient_overview'), + ('cookbook', '0178_remove_userpreference_search_style_and_more'), ('cookbook', '0179_recipe_private_recipe_shared'), ('cookbook', '0180_invitelink_reusable'), + ('cookbook', '0181_space_image'), ('cookbook', '0182_userpreference_image'), ('cookbook', '0183_alter_space_image'), + ('cookbook', '0184_alter_userpreference_image'), ('cookbook', '0185_food_plural_name_ingredient_always_use_plural_food_and_more'), + ('cookbook', '0186_automation_order_alter_automation_type'), ('cookbook', '0187_alter_space_use_plural'), ('cookbook', '0188_space_no_sharing_limit'), + ('cookbook', '0189_property_propertytype_unitconversion_food_fdc_id_and_more'), ('cookbook', '0190_auto_20230525_1506'), + ('cookbook', '0191_foodproperty_property_import_food_id_and_more'), ('cookbook', '0192_food_food_unique_open_data_slug_per_space_and_more'), + ('cookbook', '0193_space_internal_note'), ('cookbook', '0194_alter_food_properties_food_amount'), + ('cookbook', '0195_invitelink_internal_note_userspace_internal_note_and_more'), ('cookbook', '0196_food_url'), + ('cookbook', '0197_step_show_ingredients_table_and_more'), ('cookbook', '0198_propertytype_order'), + ('cookbook', '0199_alter_propertytype_options_alter_automation_type_and_more'), ('cookbook', '0200_alter_propertytype_options_remove_keyword_icon_and_more'), + ('cookbook', '0201_rename_date_mealplan_from_date_mealplan_to_date'), ('cookbook', '0202_remove_space_show_facet_count'), + ('cookbook', '0203_alter_unique_contstraints'), ('cookbook', '0204_propertytype_fdc_id'), ('cookbook', '0205_alter_food_fdc_id_alter_propertytype_fdc_id'), + ('cookbook', '0206_rename_sticky_navbar_userpreference_nav_sticky_and_more'), ('cookbook', '0207_space_logo_color_128_space_logo_color_144_and_more'), + ('cookbook', '0208_space_app_name_userpreference_max_owned_spaces'), ('cookbook', '0209_remove_space_use_plural'), + ('cookbook', '0210_shoppinglistentry_updated_at'), ('cookbook', '0211_recipebook_order'), ('cookbook', '0212_alter_property_property_amount'), + ('cookbook', '0213_remove_property_property_unique_import_food_per_space_and_more'), ('cookbook', '0214_cooklog_comment_cooklog_updated_at_and_more'), + ('cookbook', '0215_connectorconfig'), ('cookbook', '0216_delete_shoppinglist'), ('cookbook', '0217_alter_userpreference_default_page'), + ('cookbook', '0218_alter_mealplan_from_date_alter_mealplan_to_date'), ('cookbook', '0219_connectorconfig_supports_description_field'), + ('cookbook', '0220_shoppinglistrecipe_created_by_and_more'), ('cookbook', '0221_migrate_shoppinglistrecipe_space_created_by'), + ('cookbook', '0222_alter_shoppinglistrecipe_created_by_and_more'), ('cookbook', '0223_auto_20250831_1111'), + ('cookbook', '0224_space_ai_credits_balance_space_ai_credits_monthly_and_more'), ('cookbook', '0225_space_ai_enabled'), + ('cookbook', '0226_aiprovider_log_credit_cost_and_more'), ('cookbook', '0227_space_ai_default_provider_and_more')] + + initial = True + + dependencies = [ + ('auth', '0011_update_proxy_permissions'), + ('auth', '0012_alter_user_first_name_max_length'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.RunPython(create_default_groups), + migrations.CreateModel( + name='AiProvider', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('description', models.TextField(blank=True)), + ('api_key', models.CharField(max_length=2048)), + ('model_name', models.CharField(max_length=256)), + ('url', models.CharField(blank=True, max_length=2048, null=True)), + ('log_credit_cost', models.BooleanField(default=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + ), + migrations.CreateModel( + name='FoodInheritField', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('field', models.CharField(max_length=32, unique=True)), + ('name', models.CharField(max_length=64, unique=True)), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='Keyword', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('path', models.CharField(max_length=255, unique=True)), + ('depth', models.PositiveIntegerField()), + ('numchild', models.PositiveIntegerField(default=0)), + ('name', models.CharField(max_length=64)), + ('description', models.TextField(blank=True, default='')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('keyword'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='NutritionInformation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('fats', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('carbohydrates', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('proteins', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('calories', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('source', models.CharField(blank=True, default='', max_length=512, null=True)), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='Property', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('property_amount', models.DecimalField(decimal_places=4, default=None, max_digits=32, null=True)), + ('open_data_food_slug', models.CharField(blank=True, default=None, max_length=128, null=True)), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='PropertyType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('unit', models.CharField(blank=True, max_length=64, null=True)), + ('order', models.IntegerField(default=0)), + ('description', models.CharField(blank=True, max_length=512, null=True)), + ('category', models.CharField(blank=True, choices=[('NUTRITION', 'Nutrition'), ('ALLERGEN', 'Allergen'), ('PRICE', 'Price'), ('GOAL', 'Goal'), ('OTHER', 'Other')], + max_length=64, null=True)), + ('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)), + ('fdc_id', models.IntegerField(blank=True, default=None, null=True)), + ], + options={ + 'ordering': ('order',), + }, + bases=(models.Model, cookbook.models.PermissionModelMixin, cookbook.models.MergeModelMixin), + ), + migrations.CreateModel( + name='SearchFields', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=32, unique=True)), + ('field', models.CharField(max_length=64, unique=True)), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='CustomFilter', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('type', models.CharField(choices=[('RECIPE', 'Recipe'), ('FOOD', 'Food'), ('KEYWORD', 'Keyword')], default=('RECIPE', 'Recipe'), max_length=128)), + ('search', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('shared', models.ManyToManyField(blank=True, related_name='f_shared_with', to=settings.AUTH_USER_MODEL)), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='Food', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('path', models.CharField(max_length=255, unique=True)), + ('depth', models.PositiveIntegerField()), + ('numchild', models.PositiveIntegerField(default=0)), + ('name', models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)])), + ('plural_name', models.CharField(blank=True, default=None, max_length=128, null=True)), + ('url', models.CharField(blank=True, default='', max_length=1024, null=True)), + ('ignore_shopping', models.BooleanField(default=False)), + ('description', models.TextField(blank=True, default='')), + ('substitute_siblings', models.BooleanField(default=False)), + ('substitute_children', models.BooleanField(default=False)), + ('properties_food_amount', models.DecimalField(blank=True, decimal_places=2, default=100, max_digits=16)), + ('fdc_id', models.IntegerField(blank=True, default=None, null=True)), + ('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)), + ('onhand_users', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL)), + ('substitute', models.ManyToManyField(blank=True, to='cookbook.food')), + ('child_inherit_fields', models.ManyToManyField(blank=True, related_name='child_inherit', to='cookbook.foodinheritfield')), + ('inherit_fields', models.ManyToManyField(blank=True, to='cookbook.foodinheritfield')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('food'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='MealType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('order', models.IntegerField(default=0)), + ('color', models.CharField(blank=True, max_length=7, null=True)), + ('time', models.TimeField(blank=True, null=True)), + ('default', models.BooleanField(blank=True, default=False)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='FoodProperty', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('food', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')), + ('property', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.property')), + ], + ), + migrations.AddField( + model_name='food', + name='properties', + field=models.ManyToManyField(blank=True, through='cookbook.FoodProperty', to='cookbook.property'), + ), + migrations.AddField( + model_name='property', + name='property_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.propertytype'), + ), + migrations.CreateModel( + name='Recipe', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('description', models.CharField(blank=True, max_length=512, null=True)), + ('servings', models.IntegerField(default=1)), + ('servings_text', models.CharField(blank=True, default='', max_length=32)), + ('image', models.ImageField(blank=True, null=True, upload_to='recipes/')), + ('file_uid', models.CharField(blank=True, default='', max_length=256)), + ('file_path', models.CharField(blank=True, default='', max_length=512)), + ('link', models.CharField(blank=True, max_length=512, null=True)), + ('cors_link', models.CharField(blank=True, max_length=1024, null=True)), + ('working_time', models.IntegerField(default=0)), + ('waiting_time', models.IntegerField(default=0)), + ('internal', models.BooleanField(default=False)), + ('show_ingredient_overview', models.BooleanField(default=True)), + ('private', models.BooleanField(default=False)), + ('source_url', models.CharField(blank=True, default=None, max_length=1024, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('name_search_vector', django.contrib.postgres.search.SearchVectorField(null=True)), + ('desc_search_vector', django.contrib.postgres.search.SearchVectorField(null=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('keywords', models.ManyToManyField(blank=True, to='cookbook.keyword')), + ('nutrition', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.nutritioninformation')), + ('properties', models.ManyToManyField(blank=True, to='cookbook.property')), + ('shared', models.ManyToManyField(blank=True, related_name='recipe_shared_with', to=settings.AUTH_USER_MODEL)), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('recipe'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='MealPlan', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('servings', models.DecimalField(decimal_places=4, default=1, max_digits=8)), + ('title', models.CharField(blank=True, default='', max_length=64)), + ('note', models.TextField(blank=True)), + ('from_date', models.DateTimeField()), + ('to_date', models.DateTimeField()), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('shared', models.ManyToManyField(blank=True, related_name='plan_share', to=settings.AUTH_USER_MODEL)), + ('meal_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.mealtype')), + ('recipe', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.recipe')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('meal_plan'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='food', + name='recipe', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.recipe'), + ), + migrations.CreateModel( + name='Comment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('recipe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.recipe')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('comment'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='RecipeBook', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('description', models.TextField(blank=True)), + ('order', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('filter', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.customfilter')), + ('shared', models.ManyToManyField(blank=True, related_name='shared_with', to=settings.AUTH_USER_MODEL)), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('book'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='RecipeBookEntry', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.recipebook')), + ('recipe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.recipe')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('book_entry'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='SearchPreference', + fields=[ + ('user', annoying.fields.AutoOneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), + ('search', models.CharField(choices=[('plain', 'Simple'), ('phrase', 'Phrase'), ('websearch', 'Web'), ('raw', 'Raw')], default='plain', max_length=32)), + ('lookup', models.BooleanField(default=False)), + ('trigram_threshold', models.DecimalField(decimal_places=2, default=0.2, max_digits=3)), + ('fulltext', models.ManyToManyField(blank=True, related_name='fulltext_fields', to='cookbook.searchfields')), + ('icontains', models.ManyToManyField(blank=True, related_name='icontains_fields', to='cookbook.searchfields')), + ('istartswith', models.ManyToManyField(blank=True, related_name='istartswith_fields', to='cookbook.searchfields')), + ('trigram', models.ManyToManyField(blank=True, related_name='trigram_fields', to='cookbook.searchfields')), + ('unaccent', models.ManyToManyField(blank=True, related_name='unaccent_fields', to='cookbook.searchfields')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='Space', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(default='Default', max_length=128)), + ('space_theme', models.CharField( + choices=[('BLANK', '-------'), ('TANDOOR', 'Tandoor'), ('BOOTSTRAP', 'Bootstrap'), ('DARKLY', 'Darkly'), ('FLATLY', 'Flatly'), ('SUPERHERO', 'Superhero'), + ('TANDOOR_DARK', 'Tandoor Dark (INCOMPLETE)')], default='BLANK', max_length=128)), + ('nav_bg_color', models.CharField(blank=True, default='', max_length=8)), + ('nav_text_color', models.CharField(choices=[('BLANK', '-------'), ('LIGHT', 'Light'), ('DARK', 'Dark')], default='BLANK', max_length=16)), + ('app_name', models.CharField(blank=True, max_length=40, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('message', models.CharField(blank=True, default='', max_length=512)), + ('max_recipes', models.IntegerField(default=0)), + ('max_file_storage_mb', models.IntegerField(default=0, help_text='Maximum file storage for space in MB. 0 for unlimited, -1 to disable file upload.')), + ('max_users', models.IntegerField(default=0)), + ('allow_sharing', models.BooleanField(default=True)), + ('no_sharing_limit', models.BooleanField(default=False)), + ('demo', models.BooleanField(default=False)), + ('ai_enabled', models.BooleanField(default=True)), + ('ai_credits_monthly', models.IntegerField(default=100)), + ('ai_credits_balance', models.DecimalField(decimal_places=4, default=0, max_digits=16)), + ('internal_note', models.TextField(blank=True, null=True)), + ('ai_default_provider', + models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_ai_default_provider', to='cookbook.aiprovider')), + ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('food_inherit', models.ManyToManyField(blank=True, to='cookbook.foodinheritfield')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('space'), models.Model), + ), + migrations.CreateModel( + name='ShoppingListRecipe', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(blank=True, default='', max_length=32)), + ('servings', models.DecimalField(decimal_places=4, default=1, max_digits=8)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('mealplan', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.mealplan')), + ('recipe', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.recipe')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('shopping_list_recipe'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='ShareLink', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4)), + ('request_count', models.IntegerField(default=0)), + ('abuse_blocked', models.BooleanField(default=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('recipe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.recipe')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('share_link'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='recipebook', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.AddField( + model_name='recipe', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.AddField( + model_name='propertytype', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.AddField( + model_name='property', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.AddField( + model_name='nutritioninformation', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.AddField( + model_name='mealtype', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.AddField( + model_name='mealplan', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.AddField( + model_name='keyword', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.CreateModel( + name='InviteLink', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4)), + ('email', models.EmailField(blank=True, max_length=254)), + ('valid_until', models.DateField(default=cookbook.models.default_valid_until)), + ('reusable', models.BooleanField(default=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('internal_note', models.TextField(blank=True, null=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.group')), + ('used_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='used_by', to=settings.AUTH_USER_MODEL)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('invite_link'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='Ingredient', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('note', models.CharField(blank=True, max_length=256, null=True)), + ('is_header', models.BooleanField(default=False)), + ('no_amount', models.BooleanField(default=False)), + ('always_use_plural_unit', models.BooleanField(default=False)), + ('always_use_plural_food', models.BooleanField(default=False)), + ('order', models.IntegerField(default=0)), + ('original_text', models.CharField(blank=True, default=None, max_length=512, null=True)), + ('food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + options={ + 'ordering': ['order', 'pk'], + }, + bases=(django_prometheus.models.ExportModelOperationsMixin('ingredient'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='ImportLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type', models.CharField(max_length=32)), + ('running', models.BooleanField(default=True)), + ('msg', models.TextField(default='')), + ('total_recipes', models.IntegerField(default=0)), + ('imported_recipes', models.IntegerField(default=0)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('keyword', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.keyword')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='food', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.CreateModel( + name='ExportLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type', models.CharField(max_length=32)), + ('running', models.BooleanField(default=True)), + ('msg', models.TextField(default='')), + ('total_recipes', models.IntegerField(default=0)), + ('exported_recipes', models.IntegerField(default=0)), + ('cache_duration', models.IntegerField(default=0)), + ('possibly_not_expired', models.BooleanField(default=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='customfilter', + name='space', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.CreateModel( + name='CookLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('rating', models.IntegerField(blank=True, null=True)), + ('servings', models.IntegerField(blank=True, null=True)), + ('comment', models.TextField(blank=True, null=True)), + ('created_at', models.DateTimeField(default=django.utils.timezone.now)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('recipe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.recipe')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('cook_log'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='ConnectorConfig', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)])), + ('type', models.CharField(choices=[('HomeAssistant', 'HomeAssistant')], default='HomeAssistant', max_length=128)), + ('enabled', models.BooleanField(default=True, help_text='Is Connector Enabled')), + ('on_shopping_list_entry_created_enabled', models.BooleanField(default=False)), + ('on_shopping_list_entry_updated_enabled', models.BooleanField(default=False)), + ('on_shopping_list_entry_deleted_enabled', models.BooleanField(default=False)), + ('supports_description_field', models.BooleanField(default=True, help_text='Does the todo entity support the description field')), + ('url', models.URLField(blank=True, null=True)), + ('token', models.CharField(blank=True, max_length=512, null=True)), + ('todo_entity', models.CharField(blank=True, max_length=128, null=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='BookmarkletImport', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('html', models.TextField()), + ('url', models.CharField(blank=True, max_length=256, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('bookmarklet_import'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='Automation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type', models.CharField( + choices=[('FOOD_ALIAS', 'Food Alias'), ('UNIT_ALIAS', 'Unit Alias'), ('KEYWORD_ALIAS', 'Keyword Alias'), ('DESCRIPTION_REPLACE', 'Description Replace'), + ('INSTRUCTION_REPLACE', 'Instruction Replace'), ('NEVER_UNIT', 'Never Unit'), ('TRANSPOSE_WORDS', 'Transpose Words'), ('FOOD_REPLACE', 'Food Replace'), + ('UNIT_REPLACE', 'Unit Replace'), ('NAME_REPLACE', 'Name Replace')], max_length=128)), + ('name', models.CharField(default='', max_length=128)), + ('description', models.TextField(blank=True, null=True)), + ('param_1', models.CharField(blank=True, max_length=128, null=True)), + ('param_2', models.CharField(blank=True, max_length=128, null=True)), + ('param_3', models.CharField(blank=True, max_length=128, null=True)), + ('order', models.IntegerField(default=1000)), + ('disabled', models.BooleanField(default=False)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('automations'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='aiprovider', + name='space', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + migrations.CreateModel( + name='AiLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('function', models.CharField(max_length=64)), + ('credit_cost', models.DecimalField(decimal_places=4, max_digits=16)), + ('credits_from_balance', models.BooleanField(default=False)), + ('input_tokens', models.IntegerField(default=0)), + ('output_tokens', models.IntegerField(default=0)), + ('start_time', models.DateTimeField(null=True)), + ('end_time', models.DateTimeField(null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ('ai_provider', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.aiprovider')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='Step', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(blank=True, default='', max_length=128)), + ('instruction', models.TextField(blank=True)), + ('time', models.IntegerField(blank=True, default=0)), + ('order', models.IntegerField(default=0)), + ('show_as_header', models.BooleanField(default=True)), + ('show_ingredients_table', models.BooleanField(default=True)), + ('search_vector', django.contrib.postgres.search.SearchVectorField(null=True)), + ('ingredients', models.ManyToManyField(blank=True, to='cookbook.ingredient')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ('step_recipe', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='cookbook.recipe')), + ], + options={ + 'ordering': ['order', 'pk'], + }, + bases=(django_prometheus.models.ExportModelOperationsMixin('step'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='recipe', + name='steps', + field=models.ManyToManyField(blank=True, to='cookbook.step'), + ), + migrations.CreateModel( + name='Storage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('method', models.CharField(choices=[('DB', 'Dropbox'), ('NEXTCLOUD', 'Nextcloud'), ('LOCAL', 'Local')], default='DB', max_length=128)), + ('username', models.CharField(blank=True, max_length=128, null=True)), + ('password', models.CharField(blank=True, max_length=128, null=True)), + ('token', models.CharField(blank=True, max_length=512, null=True)), + ('url', models.URLField(blank=True, null=True)), + ('path', models.CharField(blank=True, default='', max_length=256)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='RecipeImport', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('file_uid', models.CharField(default='', max_length=256)), + ('file_path', models.CharField(default='', max_length=512)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ('storage', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.storage')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='recipe', + name='storage', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='cookbook.storage'), + ), + migrations.CreateModel( + name='Supermarket', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)])), + ('description', models.TextField(blank=True, null=True)), + ('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='SupermarketCategory', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)])), + ('description', models.TextField(blank=True, null=True)), + ('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin, cookbook.models.MergeModelMixin), + ), + migrations.AddField( + model_name='food', + name='supermarket_category', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.supermarketcategory'), + ), + migrations.CreateModel( + name='SupermarketCategoryRelation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('order', models.IntegerField(default=0)), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='category_to_supermarket', to='cookbook.supermarketcategory')), + ('supermarket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='category_to_supermarket', to='cookbook.supermarket')), + ], + options={ + 'ordering': ('order',), + }, + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='supermarket', + name='categories', + field=models.ManyToManyField(through='cookbook.SupermarketCategoryRelation', to='cookbook.supermarketcategory'), + ), + migrations.CreateModel( + name='Sync', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('path', models.CharField(default='', max_length=512)), + ('active', models.BooleanField(default=True)), + ('last_checked', models.DateTimeField(null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ('storage', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.storage')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='SyncLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('status', models.CharField(max_length=32)), + ('msg', models.TextField(default='')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('sync', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.sync')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='TelegramBot', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('token', models.CharField(max_length=256)), + ('name', models.CharField(blank=True, default='', max_length=128)), + ('chat_id', models.CharField(blank=True, default='', max_length=128)), + ('webhook_token', models.UUIDField(default=uuid.uuid4)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='Unit', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)])), + ('plural_name', models.CharField(blank=True, default=None, max_length=128, null=True)), + ('description', models.TextField(blank=True, null=True)), + ('base_unit', models.TextField(blank=True, default=None, max_length=256, null=True)), + ('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('unit'), models.Model, cookbook.models.PermissionModelMixin, cookbook.models.MergeModelMixin), + ), + migrations.CreateModel( + name='ShoppingListEntry', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('order', models.IntegerField(default=0)), + ('checked', models.BooleanField(default=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('completed_at', models.DateTimeField(blank=True, null=True)), + ('delay_until', models.DateTimeField(blank=True, null=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('food', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shopping_entries', to='cookbook.food')), + ('ingredient', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.ingredient')), + ('list_recipe', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='entries', to='cookbook.shoppinglistrecipe')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ('unit', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.unit')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('shopping_list_entry'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='ingredient', + name='unit', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.unit'), + ), + migrations.AddField( + model_name='food', + name='preferred_shopping_unit', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_shopping_unit', to='cookbook.unit'), + ), + migrations.AddField( + model_name='food', + name='preferred_unit', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_unit', to='cookbook.unit'), + ), + migrations.AddField( + model_name='food', + name='properties_food_unit', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='cookbook.unit'), + ), + migrations.CreateModel( + name='UnitConversion', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('base_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('converted_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)), + ('base_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_base_relation', to='cookbook.unit')), + ('converted_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_converted_relation', to='cookbook.unit')), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('unit_conversion'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='UserFile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('file', models.FileField(upload_to='files/')), + ('file_size_kb', models.IntegerField(blank=True, default=0)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('user_files'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddField( + model_name='step', + name='file', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='custom_space_theme', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_theme', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='image', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_image', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='logo_color_128', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_logo_color_128', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='logo_color_144', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_logo_color_144', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='logo_color_180', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_logo_color_180', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='logo_color_192', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_logo_color_192', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='logo_color_32', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_logo_color_32', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='logo_color_512', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_logo_color_512', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='logo_color_svg', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_logo_color_svg', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='nav_logo', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_nav_logo', to='cookbook.userfile'), + ), + migrations.CreateModel( + name='UserPreference', + fields=[ + ('user', annoying.fields.AutoOneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), + ('theme', models.CharField(choices=[('TANDOOR', 'Tandoor'), ('BOOTSTRAP', 'Bootstrap'), ('DARKLY', 'Darkly'), ('FLATLY', 'Flatly'), ('SUPERHERO', 'Superhero'), + ('TANDOOR_DARK', 'Tandoor Dark (INCOMPLETE)')], default='TANDOOR', max_length=128)), + ('nav_bg_color', models.CharField(default='#ddbf86', max_length=8)), + ('nav_text_color', models.CharField(choices=[('LIGHT', 'Light'), ('DARK', 'Dark')], default='DARK', max_length=16)), + ('nav_show_logo', models.BooleanField(default=True)), + ('nav_sticky', models.BooleanField(default=True)), + ('max_owned_spaces', models.IntegerField(default=100)), + ('default_unit', models.CharField(default='g', max_length=32)), + ('use_fractions', models.BooleanField(default=False)), + ('use_kj', models.BooleanField(default=False)), + ('default_page', + models.CharField(choices=[('SEARCH', 'Search'), ('PLAN', 'Meal-Plan'), ('BOOKS', 'Books'), ('SHOPPING', 'Shopping')], default='SEARCH', max_length=64)), + ('ingredient_decimals', models.IntegerField(default=2)), + ('comments', models.BooleanField(default=True)), + ('shopping_auto_sync', models.IntegerField(default=5)), + ('mealplan_autoadd_shopping', models.BooleanField(default=False)), + ('mealplan_autoexclude_onhand', models.BooleanField(default=True)), + ('mealplan_autoinclude_related', models.BooleanField(default=True)), + ('shopping_add_onhand', models.BooleanField(default=False)), + ('filter_to_supermarket', models.BooleanField(default=False)), + ('left_handed', models.BooleanField(default=False)), + ('show_step_ingredients', models.BooleanField(default=True)), + ('default_delay', models.DecimalField(decimal_places=4, default=4, max_digits=8)), + ('shopping_recent_days', models.PositiveIntegerField(default=7)), + ('csv_delim', models.CharField(default=',', max_length=2)), + ('csv_prefix', models.CharField(blank=True, max_length=10)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='user_image', to='cookbook.userfile')), + ('plan_share', models.ManyToManyField(blank=True, related_name='plan_share_default', to=settings.AUTH_USER_MODEL)), + ('shopping_share', models.ManyToManyField(blank=True, related_name='shopping_share', to=settings.AUTH_USER_MODEL)), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='UserSpace', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('active', models.BooleanField(default=False)), + ('internal_note', models.TextField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('groups', models.ManyToManyField(to='auth.group')), + ('invite_link', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='cookbook.invitelink')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='ViewLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('recipe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.recipe')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('view_log'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddConstraint( + model_name='foodproperty', + constraint=models.UniqueConstraint(fields=('food', 'property'), name='property_unique_food'), + ), + migrations.AddConstraint( + model_name='recipebookentry', + constraint=models.UniqueConstraint(fields=('recipe', 'book'), name='rbe_unique_name_per_space'), + ), + migrations.AddIndex( + model_name='recipebook', + index=models.Index(fields=['name'], name='cookbook_re_name_94cc63_idx'), + ), + migrations.AddConstraint( + model_name='propertytype', + constraint=models.UniqueConstraint(fields=('space', 'name'), name='property_type_unique_name_per_space'), + ), + migrations.AddConstraint( + model_name='propertytype', + constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='property_type_unique_open_data_slug_per_space'), + ), + migrations.AddConstraint( + model_name='property', + constraint=models.UniqueConstraint(fields=('space', 'property_type', 'open_data_food_slug'), name='property_unique_import_food_per_space'), + ), + migrations.AddConstraint( + model_name='mealtype', + constraint=models.UniqueConstraint(fields=('space', 'name', 'created_by'), name='mt_unique_name_per_space'), + ), + migrations.AddIndex( + model_name='keyword', + index=models.Index(fields=['id', 'name'], name='cookbook_ke_id_ebc03f_idx'), + ), + migrations.AddConstraint( + model_name='keyword', + constraint=models.UniqueConstraint(fields=('space', 'name'), name='kw_unique_name_per_space'), + ), + migrations.AddConstraint( + model_name='customfilter', + constraint=models.UniqueConstraint(fields=('space', 'name'), name='cf_unique_name_per_space'), + ), + migrations.AddIndex( + model_name='cooklog', + index=models.Index(fields=['id'], name='cookbook_co_id_553a6d_idx'), + ), + migrations.AddIndex( + model_name='cooklog', + index=models.Index(fields=['recipe'], name='cookbook_co_recipe__8ec719_idx'), + ), + migrations.AddIndex( + model_name='cooklog', + index=models.Index(fields=['-created_at'], name='cookbook_co_created_f6e244_idx'), + ), + migrations.AddIndex( + model_name='cooklog', + index=models.Index(fields=['rating'], name='cookbook_co_rating_aa7662_idx'), + ), + migrations.AddIndex( + model_name='cooklog', + index=models.Index(fields=['created_by'], name='cookbook_co_created_7ea086_idx'), + ), + migrations.AddIndex( + model_name='cooklog', + index=models.Index(fields=['created_by', 'rating'], name='cookbook_co_created_f5ccd7_idx'), + ), + migrations.AddIndex( + model_name='recipe', + index=django.contrib.postgres.indexes.GinIndex(fields=['name_search_vector'], name='cookbook_re_name_se_5dbbd5_gin'), + ), + migrations.AddIndex( + model_name='recipe', + index=django.contrib.postgres.indexes.GinIndex(fields=['desc_search_vector'], name='cookbook_re_desc_se_fdee30_gin'), + ), + migrations.AddIndex( + model_name='recipe', + index=models.Index(fields=['id'], name='cookbook_re_id_b2bdcf_idx'), + ), + migrations.AddIndex( + model_name='recipe', + index=models.Index(fields=['name'], name='cookbook_re_name_b8a027_idx'), + ), + migrations.AddConstraint( + model_name='supermarketcategory', + constraint=models.UniqueConstraint(fields=('space', 'name'), name='smc_unique_name_per_space'), + ), + migrations.AddConstraint( + model_name='supermarketcategory', + constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='supermarket_category_unique_open_data_slug_per_space'), + ), + migrations.AddConstraint( + model_name='supermarketcategoryrelation', + constraint=models.UniqueConstraint(fields=('supermarket', 'category'), name='unique_sm_category_relation'), + ), + migrations.AddConstraint( + model_name='supermarket', + constraint=models.UniqueConstraint(fields=('space', 'name'), name='sm_unique_name_per_space'), + ), + migrations.AddConstraint( + model_name='supermarket', + constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='supermarket_unique_open_data_slug_per_space'), + ), + migrations.AddConstraint( + model_name='unit', + constraint=models.UniqueConstraint(fields=('space', 'name'), name='u_unique_name_per_space'), + ), + migrations.AddConstraint( + model_name='unit', + constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='unit_unique_open_data_slug_per_space'), + ), + migrations.AddIndex( + model_name='ingredient', + index=models.Index(fields=['id'], name='cookbook_in_id_2c1f57_idx'), + ), + migrations.AddIndex( + model_name='food', + index=models.Index(fields=['id'], name='cookbook_fo_id_3c379b_idx'), + ), + migrations.AddIndex( + model_name='food', + index=models.Index(fields=['name'], name='cookbook_fo_name_c848b6_idx'), + ), + migrations.AddConstraint( + model_name='food', + constraint=models.UniqueConstraint(fields=('space', 'name'), name='f_unique_name_per_space'), + ), + migrations.AddConstraint( + model_name='food', + constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='food_unique_open_data_slug_per_space'), + ), + migrations.AddConstraint( + model_name='unitconversion', + constraint=models.UniqueConstraint(fields=('space', 'base_unit', 'converted_unit', 'food'), name='f_unique_conversion_per_space'), + ), + migrations.AddConstraint( + model_name='unitconversion', + constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='unit_conversion_unique_open_data_slug_per_space'), + ), + migrations.AddIndex( + model_name='step', + index=django.contrib.postgres.indexes.GinIndex(fields=['search_vector'], name='cookbook_st_search__2ef7fa_gin'), + ), + migrations.AddIndex( + model_name='viewlog', + index=models.Index(fields=['recipe'], name='cookbook_vi_recipe__ce995d_idx'), + ), + migrations.AddIndex( + model_name='viewlog', + index=models.Index(fields=['-created_at'], name='cookbook_vi_created_bd2b5f_idx'), + ), + migrations.AddIndex( + model_name='viewlog', + index=models.Index(fields=['created_by'], name='cookbook_vi_created_f9385c_idx'), + ), + migrations.AddIndex( + model_name='viewlog', + index=models.Index(fields=['recipe', '-created_at', 'created_by'], name='cookbook_vi_recipe__1b051f_idx'), + ), + migrations.RunPython(create_fields), + ]