added bulk api endpoint for SLE checking
This commit is contained in:
parent
2b1eda12d1
commit
2697e42af7
@ -57,7 +57,8 @@ class ExtendedRecipeMixin(serializers.ModelSerializer):
|
||||
api_serializer = None
|
||||
# extended values are computationally expensive and not needed in normal circumstances
|
||||
try:
|
||||
if str2bool(self.context['request'].query_params.get('extended', False)) and self.__class__ == api_serializer:
|
||||
if str2bool(
|
||||
self.context['request'].query_params.get('extended', False)) and self.__class__ == api_serializer:
|
||||
return fields
|
||||
except (AttributeError, KeyError):
|
||||
pass
|
||||
@ -81,12 +82,14 @@ class ExtendedRecipeMixin(serializers.ModelSerializer):
|
||||
class OpenDataModelMixin(serializers.ModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
if 'open_data_slug' in validated_data and validated_data['open_data_slug'] is not None and validated_data['open_data_slug'].strip() == '':
|
||||
if 'open_data_slug' in validated_data and validated_data['open_data_slug'] is not None and validated_data[
|
||||
'open_data_slug'].strip() == '':
|
||||
validated_data['open_data_slug'] = None
|
||||
return super().create(validated_data)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
if 'open_data_slug' in validated_data and validated_data['open_data_slug'] is not None and validated_data['open_data_slug'].strip() == '':
|
||||
if 'open_data_slug' in validated_data and validated_data['open_data_slug'] is not None and validated_data[
|
||||
'open_data_slug'].strip() == '':
|
||||
validated_data['open_data_slug'] = None
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
@ -122,7 +125,8 @@ class CustomOnHandField(serializers.Field):
|
||||
if not self.context["request"].user.is_authenticated:
|
||||
return []
|
||||
shared_users = []
|
||||
if c := caches['default'].get(f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}', None):
|
||||
if c := caches['default'].get(
|
||||
f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}', None):
|
||||
shared_users = c
|
||||
else:
|
||||
try:
|
||||
@ -312,7 +316,8 @@ class SpaceSerializer(WritableNestedModelSerializer):
|
||||
'id', 'name', 'created_by', 'created_at', 'message', 'max_recipes', 'max_file_storage_mb', 'max_users',
|
||||
'allow_sharing', 'demo', 'food_inherit', 'user_count', 'recipe_count', 'file_size_mb',
|
||||
'image', 'nav_logo', 'space_theme', 'custom_space_theme', 'nav_bg_color', 'nav_text_color', 'use_plural',
|
||||
'logo_color_32', 'logo_color_128', 'logo_color_144', 'logo_color_180', 'logo_color_192', 'logo_color_512', 'logo_color_svg',)
|
||||
'logo_color_32', 'logo_color_128', 'logo_color_144', 'logo_color_180', 'logo_color_192', 'logo_color_512',
|
||||
'logo_color_svg',)
|
||||
read_only_fields = (
|
||||
'id', 'created_by', 'created_at', 'max_recipes', 'max_file_storage_mb', 'max_users', 'allow_sharing',
|
||||
'demo',)
|
||||
@ -332,7 +337,8 @@ class UserSpaceSerializer(WritableNestedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = UserSpace
|
||||
fields = ('id', 'user', 'space', 'groups', 'active', 'internal_note', 'invite_link', 'created_at', 'updated_at',)
|
||||
fields = (
|
||||
'id', 'user', 'space', 'groups', 'active', 'internal_note', 'invite_link', 'created_at', 'updated_at',)
|
||||
read_only_fields = ('id', 'invite_link', 'created_at', 'updated_at', 'space')
|
||||
|
||||
|
||||
@ -348,7 +354,8 @@ class MealTypeSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
||||
validated_data['name'] = validated_data['name'].strip()
|
||||
space = validated_data.pop('space', self.context['request'].space)
|
||||
validated_data['created_by'] = self.context['request'].user
|
||||
obj, created = MealType.objects.get_or_create(name__iexact=validated_data['name'], space=space, defaults=validated_data)
|
||||
obj, created = MealType.objects.get_or_create(name__iexact=validated_data['name'], space=space,
|
||||
defaults=validated_data)
|
||||
return obj
|
||||
|
||||
class Meta:
|
||||
@ -382,13 +389,15 @@ class UserPreferenceSerializer(WritableNestedModelSerializer):
|
||||
class Meta:
|
||||
model = UserPreference
|
||||
fields = (
|
||||
'user', 'image', 'theme', 'nav_bg_color', 'nav_text_color', 'nav_show_logo', 'default_unit', 'default_page', 'use_fractions', 'use_kj',
|
||||
'user', 'image', 'theme', 'nav_bg_color', 'nav_text_color', 'nav_show_logo', 'default_unit', 'default_page',
|
||||
'use_fractions', 'use_kj',
|
||||
'plan_share', 'nav_sticky',
|
||||
'ingredient_decimals', 'comments', 'shopping_auto_sync', 'mealplan_autoadd_shopping',
|
||||
'food_inherit_default', 'default_delay',
|
||||
'mealplan_autoinclude_related', 'mealplan_autoexclude_onhand', 'shopping_share', 'shopping_recent_days',
|
||||
'csv_delim', 'csv_prefix',
|
||||
'filter_to_supermarket', 'shopping_add_onhand', 'left_handed', 'show_step_ingredients', 'food_children_exist'
|
||||
'filter_to_supermarket', 'shopping_add_onhand', 'left_handed', 'show_step_ingredients',
|
||||
'food_children_exist'
|
||||
)
|
||||
|
||||
|
||||
@ -477,10 +486,13 @@ class UnitSerializer(UniqueFieldsMixin, ExtendedRecipeMixin, OpenDataModelMixin)
|
||||
if x := validated_data.get('name', None):
|
||||
validated_data['plural_name'] = x.strip()
|
||||
|
||||
if unit := Unit.objects.filter(Q(name__iexact=validated_data['name']) | Q(plural_name__iexact=validated_data['name']), space=space).first():
|
||||
if unit := Unit.objects.filter(
|
||||
Q(name__iexact=validated_data['name']) | Q(plural_name__iexact=validated_data['name']),
|
||||
space=space).first():
|
||||
return unit
|
||||
|
||||
obj, created = Unit.objects.get_or_create(name__iexact=validated_data['name'], space=space, defaults=validated_data)
|
||||
obj, created = Unit.objects.get_or_create(name__iexact=validated_data['name'], space=space,
|
||||
defaults=validated_data)
|
||||
return obj
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
@ -500,7 +512,8 @@ class SupermarketCategorySerializer(UniqueFieldsMixin, WritableNestedModelSerial
|
||||
def create(self, validated_data):
|
||||
validated_data['name'] = validated_data['name'].strip()
|
||||
space = validated_data.pop('space', self.context['request'].space)
|
||||
obj, created = SupermarketCategory.objects.get_or_create(name__iexact=validated_data['name'], space=space, defaults=validated_data)
|
||||
obj, created = SupermarketCategory.objects.get_or_create(name__iexact=validated_data['name'], space=space,
|
||||
defaults=validated_data)
|
||||
return obj
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
@ -525,7 +538,8 @@ class SupermarketSerializer(UniqueFieldsMixin, SpacedModelSerializer, OpenDataMo
|
||||
def create(self, validated_data):
|
||||
validated_data['name'] = validated_data['name'].strip()
|
||||
space = validated_data.pop('space', self.context['request'].space)
|
||||
obj, created = Supermarket.objects.get_or_create(name__iexact=validated_data['name'], space=space, defaults=validated_data)
|
||||
obj, created = Supermarket.objects.get_or_create(name__iexact=validated_data['name'], space=space,
|
||||
defaults=validated_data)
|
||||
return obj
|
||||
|
||||
class Meta:
|
||||
@ -540,7 +554,8 @@ class PropertyTypeSerializer(OpenDataModelMixin, WritableNestedModelSerializer,
|
||||
def create(self, validated_data):
|
||||
validated_data['name'] = validated_data['name'].strip()
|
||||
space = validated_data.pop('space', self.context['request'].space)
|
||||
obj, created = PropertyType.objects.get_or_create(name__iexact=validated_data['name'], space=space, defaults=validated_data)
|
||||
obj, created = PropertyType.objects.get_or_create(name__iexact=validated_data['name'], space=space,
|
||||
defaults=validated_data)
|
||||
return obj
|
||||
|
||||
class Meta:
|
||||
@ -665,12 +680,14 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
|
||||
|
||||
properties = validated_data.pop('properties', None)
|
||||
|
||||
obj, created = Food.objects.get_or_create(name=name, plural_name=plural_name, space=space, properties_food_unit=properties_food_unit,
|
||||
obj, created = Food.objects.get_or_create(name=name, plural_name=plural_name, space=space,
|
||||
properties_food_unit=properties_food_unit,
|
||||
defaults=validated_data)
|
||||
|
||||
if properties and len(properties) > 0:
|
||||
for p in properties:
|
||||
obj.properties.add(Property.objects.create(property_type_id=p['property_type']['id'], property_amount=p['property_amount'], space=space))
|
||||
obj.properties.add(Property.objects.create(property_type_id=p['property_type']['id'],
|
||||
property_amount=p['property_amount'], space=space))
|
||||
|
||||
return obj
|
||||
|
||||
@ -702,7 +719,8 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
|
||||
'properties', 'properties_food_amount', 'properties_food_unit', 'fdc_id',
|
||||
'food_onhand', 'supermarket_category',
|
||||
'image', 'parent', 'numchild', 'numrecipe', 'inherit_fields', 'full_name', 'ignore_shopping',
|
||||
'substitute', 'substitute_siblings', 'substitute_children', 'substitute_onhand', 'child_inherit_fields', 'open_data_slug',
|
||||
'substitute', 'substitute_siblings', 'substitute_children', 'substitute_onhand', 'child_inherit_fields',
|
||||
'open_data_slug',
|
||||
)
|
||||
read_only_fields = ('id', 'numchild', 'parent', 'image', 'numrecipe')
|
||||
|
||||
@ -726,7 +744,8 @@ class IngredientSimpleSerializer(WritableNestedModelSerializer):
|
||||
uch = UnitConversionHelper(self.context['request'].space)
|
||||
conversions = []
|
||||
for c in uch.get_conversions(obj):
|
||||
conversions.append({'food': c.food.name, 'unit': c.unit.name, 'amount': c.amount}) # TODO do formatting in helper
|
||||
conversions.append(
|
||||
{'food': c.food.name, 'unit': c.unit.name, 'amount': c.amount}) # TODO do formatting in helper
|
||||
return conversions
|
||||
else:
|
||||
return []
|
||||
@ -828,7 +847,8 @@ class UnitConversionSerializer(WritableNestedModelSerializer, OpenDataModelMixin
|
||||
|
||||
class Meta:
|
||||
model = UnitConversion
|
||||
fields = ('id', 'name', 'base_amount', 'base_unit', 'converted_amount', 'converted_unit', 'food', 'open_data_slug')
|
||||
fields = (
|
||||
'id', 'name', 'base_amount', 'base_unit', 'converted_amount', 'converted_unit', 'food', 'open_data_slug')
|
||||
|
||||
|
||||
class NutritionInformationSerializer(serializers.ModelSerializer):
|
||||
@ -898,7 +918,8 @@ class RecipeSerializer(RecipeBaseSerializer):
|
||||
fields = (
|
||||
'id', 'name', 'description', 'image', 'keywords', 'steps', 'working_time',
|
||||
'waiting_time', 'created_by', 'created_at', 'updated_at', 'source_url',
|
||||
'internal', 'show_ingredient_overview', 'nutrition', 'properties', 'food_properties', 'servings', 'file_path', 'servings_text', 'rating',
|
||||
'internal', 'show_ingredient_overview', 'nutrition', 'properties', 'food_properties', 'servings',
|
||||
'file_path', 'servings_text', 'rating',
|
||||
'last_cooked',
|
||||
'private', 'shared',
|
||||
)
|
||||
@ -977,7 +998,8 @@ class RecipeBookEntrySerializer(serializers.ModelSerializer):
|
||||
def create(self, validated_data):
|
||||
book = validated_data['book']
|
||||
recipe = validated_data['recipe']
|
||||
if not book.get_owner() == self.context['request'].user and not self.context['request'].user in book.get_shared():
|
||||
if not book.get_owner() == self.context['request'].user and not self.context[
|
||||
'request'].user in book.get_shared():
|
||||
raise NotFound(detail=None, code=None)
|
||||
obj, created = RecipeBookEntry.objects.get_or_create(book=book, recipe=recipe)
|
||||
return obj
|
||||
@ -1066,7 +1088,8 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ShoppingListRecipe
|
||||
fields = ('id', 'recipe_name', 'name', 'recipe', 'mealplan', 'servings', 'mealplan_note', 'mealplan_from_date', 'mealplan_type')
|
||||
fields = ('id', 'recipe_name', 'name', 'recipe', 'mealplan', 'servings', 'mealplan_note', 'mealplan_from_date',
|
||||
'mealplan_type')
|
||||
read_only_fields = ('id',)
|
||||
|
||||
|
||||
@ -1132,6 +1155,11 @@ class ShoppingListEntrySerializer(WritableNestedModelSerializer):
|
||||
read_only_fields = ('id', 'created_by', 'created_at',)
|
||||
|
||||
|
||||
class ShoppingListEntryBulkSerializer(serializers.Serializer):
|
||||
ids = serializers.ListField()
|
||||
checked = serializers.BooleanField()
|
||||
|
||||
|
||||
# TODO deprecate
|
||||
class ShoppingListEntryCheckedSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
@ -1284,7 +1312,8 @@ class InviteLinkSerializer(WritableNestedModelSerializer):
|
||||
class Meta:
|
||||
model = InviteLink
|
||||
fields = (
|
||||
'id', 'uuid', 'email', 'group', 'valid_until', 'used_by', 'reusable', 'internal_note', 'created_by', 'created_at',)
|
||||
'id', 'uuid', 'email', 'group', 'valid_until', 'used_by', 'reusable', 'internal_note', 'created_by',
|
||||
'created_at',)
|
||||
read_only_fields = ('id', 'uuid', 'created_by', 'created_at',)
|
||||
|
||||
|
||||
|
@ -103,7 +103,8 @@ from cookbook.serializer import (AccessTokenSerializer, AutomationSerializer,
|
||||
SupermarketCategorySerializer, SupermarketSerializer,
|
||||
SyncLogSerializer, SyncSerializer, UnitConversionSerializer,
|
||||
UnitSerializer, UserFileSerializer, UserPreferenceSerializer,
|
||||
UserSerializer, UserSpaceSerializer, ViewLogSerializer)
|
||||
UserSerializer, UserSpaceSerializer, ViewLogSerializer,
|
||||
ShoppingListEntryBulkSerializer)
|
||||
from cookbook.views.import_export import get_integration
|
||||
from recipes import settings
|
||||
from recipes.settings import FDC_API_KEY, DRF_THROTTLE_RECIPE_URL_IMPORT
|
||||
@ -1175,6 +1176,22 @@ class ShoppingListEntryViewSet(viewsets.ModelViewSet):
|
||||
# TODO once old shopping list is removed this needs updated to sharing users in preferences
|
||||
return self.queryset
|
||||
|
||||
@decorators.action(
|
||||
detail=False,
|
||||
methods=['POST'],
|
||||
serializer_class=ShoppingListEntryBulkSerializer,
|
||||
)
|
||||
def bulk(self, request):
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
ShoppingListEntry.objects.filter(
|
||||
Q(created_by=self.request.user)
|
||||
| Q(shoppinglist__shared=self.request.user)
|
||||
| Q(created_by__in=list(self.request.user.get_shopping_share()))
|
||||
).filter(space=request.space, id__in=serializer.validated_data['ids']).update(checked=serializer.validated_data['checked'])
|
||||
return Response(serializer.data)
|
||||
else:
|
||||
return Response(serializer.errors, 400)
|
||||
|
||||
# TODO deprecate
|
||||
class ShoppingListViewSet(viewsets.ModelViewSet):
|
||||
|
@ -299,10 +299,19 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
|
||||
this.registerChange((checked ? 'CHECKED' : 'UNCHECKED'), entries)
|
||||
}
|
||||
|
||||
let entry_id_list = []
|
||||
for (let i in entries) {
|
||||
this.entries[i].checked = checked
|
||||
this.updateObject(this.entries[i])
|
||||
Vue.set(this.entries[i], 'checked', checked)
|
||||
Vue.set(this.entries[i], 'update_at', moment().format())
|
||||
entry_id_list.push(i)
|
||||
}
|
||||
|
||||
let apiClient = new ApiApiFactory()
|
||||
apiClient.bulkShoppingListEntry({'ids': entry_id_list, 'checked': checked}).then((r) => {
|
||||
|
||||
}).catch((err) => {
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* function to handle user "delaying" and "undelaying" shopping entries
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user