make on_hand multiuser
This commit is contained in:
parent
b919fb4ae8
commit
7c89117e04
41
cookbook/migrations/0163_auto_20220105_0758.py
Normal file
41
cookbook/migrations/0163_auto_20220105_0758.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Generated by Django 3.2.10 on 2022-01-05 13:58
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
from cookbook.models import FoodInheritField
|
||||||
|
|
||||||
|
|
||||||
|
def rename_inherit_field(apps, schema_editor):
|
||||||
|
x = FoodInheritField.objects.filter(name='On Hand', field='food_onhand').first()
|
||||||
|
if x:
|
||||||
|
x.name = "Ignore Shopping"
|
||||||
|
x.field = "ignore_shopping"
|
||||||
|
x.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('cookbook', '0162_userpreference_csv_delim'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='food',
|
||||||
|
name='onhand_users',
|
||||||
|
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userpreference',
|
||||||
|
name='shopping_add_onhand',
|
||||||
|
field=models.BooleanField(default=True),
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='food',
|
||||||
|
old_name='food_onhand',
|
||||||
|
new_name='ignore_shopping',
|
||||||
|
),
|
||||||
|
migrations.RunPython(rename_inherit_field),
|
||||||
|
]
|
@ -332,6 +332,7 @@ class UserPreference(models.Model, PermissionModelMixin):
|
|||||||
mealplan_autoadd_shopping = models.BooleanField(default=False)
|
mealplan_autoadd_shopping = models.BooleanField(default=False)
|
||||||
mealplan_autoexclude_onhand = models.BooleanField(default=True)
|
mealplan_autoexclude_onhand = models.BooleanField(default=True)
|
||||||
mealplan_autoinclude_related = models.BooleanField(default=True)
|
mealplan_autoinclude_related = models.BooleanField(default=True)
|
||||||
|
shopping_add_onhand = models.BooleanField(default=True)
|
||||||
filter_to_supermarket = models.BooleanField(default=False)
|
filter_to_supermarket = models.BooleanField(default=False)
|
||||||
default_delay = models.DecimalField(default=4, max_digits=8, decimal_places=4)
|
default_delay = models.DecimalField(default=4, max_digits=8, decimal_places=4)
|
||||||
shopping_recent_days = models.PositiveIntegerField(default=7)
|
shopping_recent_days = models.PositiveIntegerField(default=7)
|
||||||
@ -489,10 +490,11 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
|||||||
node_order_by = ['name']
|
node_order_by = ['name']
|
||||||
name = models.CharField(max_length=128, validators=[MinLengthValidator(1)])
|
name = models.CharField(max_length=128, validators=[MinLengthValidator(1)])
|
||||||
recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL)
|
recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL)
|
supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL) # inherited field
|
||||||
food_onhand = models.BooleanField(default=False) # inherited field
|
ignore_shopping = models.BooleanField(default=False) # inherited field
|
||||||
|
onhand_users = models.ManyToManyField(User, blank=True)
|
||||||
description = models.TextField(default='', blank=True)
|
description = models.TextField(default='', blank=True)
|
||||||
inherit_fields = models.ManyToManyField(FoodInheritField, blank=True) # inherited field: is this name better as inherit instead of ignore inherit? which is more intuitive?
|
inherit_fields = models.ManyToManyField(FoodInheritField, blank=True)
|
||||||
|
|
||||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||||
objects = ScopedManager(space='space', _manager_class=TreeManager)
|
objects = ScopedManager(space='space', _manager_class=TreeManager)
|
||||||
|
@ -92,6 +92,15 @@ class CustomDecimalField(serializers.Field):
|
|||||||
raise ValidationError('A valid number is required')
|
raise ValidationError('A valid number is required')
|
||||||
|
|
||||||
|
|
||||||
|
class CustomOnHandField(serializers.BooleanField):
|
||||||
|
def get_attribute(self, instance):
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def to_representation(self, obj):
|
||||||
|
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [self.context['request'].user.id]
|
||||||
|
return obj.onhand_users.filter(id__in=shared_users).exists()
|
||||||
|
|
||||||
|
|
||||||
class SpaceFilterSerializer(serializers.ListSerializer):
|
class SpaceFilterSerializer(serializers.ListSerializer):
|
||||||
|
|
||||||
def to_representation(self, data):
|
def to_representation(self, data):
|
||||||
@ -371,12 +380,32 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
|
|||||||
recipe = RecipeSimpleSerializer(allow_null=True, required=False)
|
recipe = RecipeSimpleSerializer(allow_null=True, required=False)
|
||||||
shopping = serializers.SerializerMethodField('get_shopping_status')
|
shopping = serializers.SerializerMethodField('get_shopping_status')
|
||||||
inherit_fields = FoodInheritFieldSerializer(many=True, allow_null=True, required=False)
|
inherit_fields = FoodInheritFieldSerializer(many=True, allow_null=True, required=False)
|
||||||
|
food_onhand = CustomOnHandField()
|
||||||
|
|
||||||
recipe_filter = 'steps__ingredients__food'
|
recipe_filter = 'steps__ingredients__food'
|
||||||
|
|
||||||
def get_shopping_status(self, obj):
|
def get_shopping_status(self, obj):
|
||||||
return ShoppingListEntry.objects.filter(space=obj.space, food=obj, checked=False).count() > 0
|
return ShoppingListEntry.objects.filter(space=obj.space, food=obj, checked=False).count() > 0
|
||||||
|
|
||||||
|
# def get_food_onhand(self, obj):
|
||||||
|
# shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [self.context['request'].user.id]
|
||||||
|
# return obj.onhand_users.filter(id__in=shared_users).exists()
|
||||||
|
|
||||||
|
def run_validation(self, data):
|
||||||
|
validated_data = super().run_validation(data)
|
||||||
|
# convert boolean food_onhand to onhand_users
|
||||||
|
if (
|
||||||
|
self.root.instance.__class__.__name__ == 'Food'
|
||||||
|
and not (onhand := data.pop('food_onhand', None)) is None
|
||||||
|
):
|
||||||
|
# assuming if on hand for user also onhand for shopping_share users
|
||||||
|
shared_users = [user := self.context['request'].user] + list(user.userpreference.shopping_share.all())
|
||||||
|
if onhand:
|
||||||
|
validated_data['onhand_users'] = list(self.instance.onhand_users.all()) + shared_users
|
||||||
|
else:
|
||||||
|
validated_data['onhand_users'] = list(set(self.instance.onhand_users.all()) - set(shared_users))
|
||||||
|
return validated_data
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
validated_data['name'] = validated_data['name'].strip()
|
validated_data['name'] = validated_data['name'].strip()
|
||||||
validated_data['space'] = self.context['request'].space
|
validated_data['space'] = self.context['request'].space
|
||||||
|
Loading…
Reference in New Issue
Block a user