mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2025-12-24 02:39:20 -05:00
food batch editor implementation
This commit is contained in:
22
cookbook/helper/batch_edit_helper.py
Normal file
22
cookbook/helper/batch_edit_helper.py
Normal file
@@ -0,0 +1,22 @@
|
||||
def add_to_relation(relation_model, base_field_name, base_ids, related_field_name, related_ids):
|
||||
"""
|
||||
given a model, the base and related field and the base and related ids, bulk create relation objects
|
||||
"""
|
||||
relation_objects = []
|
||||
for b in base_ids:
|
||||
for r in related_ids:
|
||||
relation_objects.append(relation_model(**{base_field_name: b, related_field_name: r}))
|
||||
relation_model.objects.bulk_create(relation_objects, ignore_conflicts=True, unique_fields=(base_field_name, related_field_name,))
|
||||
|
||||
|
||||
def remove_from_relation(relation_model, base_field_name, base_ids, related_field_name, related_ids):
|
||||
relation_model.objects.filter(**{f'{base_field_name}__in': base_ids, f'{related_field_name}__in': related_ids}).delete()
|
||||
|
||||
|
||||
def remove_all_from_relation(relation_model, base_field_name, base_ids):
|
||||
relation_model.objects.filter(**{f'{base_field_name}__in': base_ids}).delete()
|
||||
|
||||
|
||||
def set_relation(relation_model, base_field_name, base_ids, related_field_name, related_ids):
|
||||
remove_all_from_relation(relation_model, base_field_name, base_ids)
|
||||
add_to_relation(relation_model, base_field_name, base_ids, related_field_name, related_ids)
|
||||
@@ -1218,6 +1218,9 @@ class FoodBatchUpdateSerializer(serializers.Serializer):
|
||||
ignore_shopping = serializers.BooleanField(required=False, allow_null=True)
|
||||
on_hand = serializers.BooleanField(required=False, allow_null=True)
|
||||
|
||||
parent_remove = serializers.BooleanField(required=False, allow_null=True)
|
||||
parent_set = serializers.IntegerField(required=False, allow_null=True)
|
||||
|
||||
|
||||
class CustomFilterSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
||||
shared = UserSerializer(many=True, required=False)
|
||||
|
||||
@@ -66,6 +66,7 @@ from cookbook.forms import ImportForm, ImportExportBase
|
||||
from cookbook.helper import recipe_url_import as helper
|
||||
from cookbook.helper.HelperFunctions import str2bool, validate_import_url
|
||||
from cookbook.helper.ai_helper import has_monthly_token, can_perform_ai_request, AiCallbackHandler
|
||||
from cookbook.helper.batch_edit_helper import add_to_relation, remove_from_relation, remove_all_from_relation, set_relation
|
||||
from cookbook.helper.image_processing import handle_image
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.helper.open_data_importer import OpenDataImporter
|
||||
@@ -951,7 +952,6 @@ class FoodViewSet(LoggingMixin, TreeMixin):
|
||||
if 'category' in serializer.validated_data:
|
||||
foods.update(supermarket_category_id=serializer.validated_data['category'])
|
||||
|
||||
|
||||
if 'ignore_shopping' in serializer.validated_data and serializer.validated_data['ignore_shopping'] is not None:
|
||||
foods.update(ignore_shopping=serializer.validated_data['ignore_shopping'])
|
||||
|
||||
@@ -964,32 +964,66 @@ class FoodViewSet(LoggingMixin, TreeMixin):
|
||||
else:
|
||||
Food.onhand_users.through.objects.filter(food_id__in=safe_food_ids, user_id=request.user.id).delete()
|
||||
|
||||
if 'substitutes_add' in serializer.validated_data:
|
||||
substitute_relation = []
|
||||
for f in safe_food_ids:
|
||||
for s in serializer.validated_data['substitutes_add']:
|
||||
substitute_relation.append(Food.substitute.through(from_food_id=f, to_food_id=s))
|
||||
Food.substitute.through.objects.bulk_create(substitute_relation, ignore_conflicts=True, unique_fields=('from_food_id', 'to_food_id',))
|
||||
if 'substitute_children' in serializer.validated_data and serializer.validated_data['substitute_children'] is not None:
|
||||
foods.update(substitute_children=serializer.validated_data['substitute_children'])
|
||||
|
||||
if 'substitute_siblings' in serializer.validated_data and serializer.validated_data['substitute_siblings'] is not None:
|
||||
foods.update(substitute_siblings=serializer.validated_data['substitute_siblings'])
|
||||
|
||||
# ---------- substitutes -------------
|
||||
if 'substitute_add' in serializer.validated_data:
|
||||
add_to_relation(Food.substitute.through, 'from_food_id', safe_food_ids, 'to_food_id', serializer.validated_data['substitute_add'])
|
||||
|
||||
if 'substitute_remove' in serializer.validated_data:
|
||||
for s in serializer.validated_data['substitute_remove']:
|
||||
Food.substitute.through.objects.filter(from_food_id=safe_food_ids, to_food_id=s).delete()
|
||||
remove_from_relation(Food.substitute.through, 'from_food_id', safe_food_ids, 'to_food_id', serializer.validated_data['substitute_remove'])
|
||||
|
||||
if 'substitute_set' in serializer.validated_data and len(serializer.validated_data['substitute_set']) > 0:
|
||||
substitute_relation = []
|
||||
Food.substitute.through.objects.filter(from_food_id=safe_food_ids).delete()
|
||||
for f in safe_food_ids:
|
||||
for s in serializer.validated_data['substitute_set']:
|
||||
substitute_relation.append(Food.substitute.through(from_food_id=f, to_food_id=s))
|
||||
Food.substitute.through.objects.bulk_create(substitute_relation, ignore_conflicts=True, unique_fields=('from_food_id', 'to_food_id',))
|
||||
set_relation(Food.substitute.through, 'from_food_id', safe_food_ids, 'to_food_id', serializer.validated_data['substitute_set'])
|
||||
|
||||
if 'substitute_remove_all' in serializer.validated_data and serializer.validated_data['substitute_remove_all']:
|
||||
Food.substitute.through.objects.filter(from_food_id=safe_food_ids).delete()
|
||||
remove_all_from_relation(Food.substitute.through, 'from_food_id', safe_food_ids)
|
||||
|
||||
# ---------- inherit fields -------------
|
||||
if 'inherit_fields_add' in serializer.validated_data:
|
||||
add_to_relation(Food.inherit_fields.through, 'food_id', safe_food_ids, 'foodinheritfield_id', serializer.validated_data['inherit_fields_add'])
|
||||
|
||||
def add_substitute(relation_model, base_field, base_ids, related_field_name, related_ids ):
|
||||
pass
|
||||
if 'inherit_fields_remove' in serializer.validated_data:
|
||||
remove_from_relation(Food.inherit_fields.through, 'food_id', safe_food_ids, 'foodinheritfield_id', serializer.validated_data['inherit_fields_remove'])
|
||||
|
||||
if 'inherit_fields_set' in serializer.validated_data and len(serializer.validated_data['inherit_fields_set']) > 0:
|
||||
set_relation(Food.inherit_fields.through, 'food_id', safe_food_ids, 'foodinheritfield_id', serializer.validated_data['inherit_fields_set'])
|
||||
|
||||
if 'inherit_fields_remove_all' in serializer.validated_data and serializer.validated_data['inherit_fields_remove_all']:
|
||||
remove_all_from_relation(Food.inherit_fields.through, 'food_id', safe_food_ids)
|
||||
|
||||
# ---------- child inherit fields -------------
|
||||
if 'child_inherit_fields_add' in serializer.validated_data:
|
||||
add_to_relation(Food.child_inherit_fields.through, 'food_id', safe_food_ids, 'foodinheritfield_id', serializer.validated_data['child_inherit_fields_add'])
|
||||
|
||||
if 'child_inherit_fields_remove' in serializer.validated_data:
|
||||
remove_from_relation(Food.child_inherit_fields.through, 'food_id', safe_food_ids, 'foodinheritfield_id', serializer.validated_data['child_inherit_fields_remove'])
|
||||
|
||||
if 'child_inherit_fields_set' in serializer.validated_data and len(serializer.validated_data['child_inherit_fields_set']) > 0:
|
||||
set_relation(Food.child_inherit_fields.through, 'food_id', safe_food_ids, 'foodinheritfield_id', serializer.validated_data['child_inherit_fields_set'])
|
||||
|
||||
if 'child_inherit_fields_remove_all' in serializer.validated_data and serializer.validated_data['child_inherit_fields_remove_all']:
|
||||
remove_all_from_relation(Food.child_inherit_fields.through, 'food_id', safe_food_ids)
|
||||
|
||||
# ------- parent --------
|
||||
if self.model.node_order_by:
|
||||
node_location = 'sorted'
|
||||
else:
|
||||
node_location = 'last'
|
||||
|
||||
if 'parent_remove' in serializer.validated_data and serializer.validated_data['parent_remove']:
|
||||
for f in foods:
|
||||
f.move(Food.get_first_root_node(), f'{node_location}-sibling')
|
||||
|
||||
if 'parent_set' in serializer.validated_data:
|
||||
parent_food = Food.objects.filter(space=request.space, id=serializer.validated_data['parent_set']).first()
|
||||
if parent_food:
|
||||
for f in foods:
|
||||
f.move(parent_food, f'{node_location}-child')
|
||||
|
||||
return Response({}, 200)
|
||||
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
<v-checkbox :label="$t('RemoveAllType', {type: $t('Substitutes')})" hide-details
|
||||
v-model="batchUpdateRequest.foodBatchUpdate.substituteRemoveAll"></v-checkbox>
|
||||
|
||||
<v-select :items="boolUpdateOptions" :label="$t('substitute_siblings')" clearable v-model="batchUpdateRequest.foodBatchUpdate.substituteChildren"></v-select>
|
||||
<v-select :items="boolUpdateOptions" :label="$t('substitute_children')" clearable v-model="batchUpdateRequest.foodBatchUpdate.substituteSiblings"></v-select>
|
||||
|
||||
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
@@ -50,8 +53,13 @@
|
||||
<v-col cols="12" md="6">
|
||||
<v-card :title="$t('Hierarchy')" prepend-icon="fa-solid fa-folder-tree" variant="flat">
|
||||
<v-card-text>
|
||||
<v-select :items="boolUpdateOptions" :label="$t('substitute_siblings')" clearable v-model="batchUpdateRequest.foodBatchUpdate.substituteChildren"></v-select>
|
||||
<v-select :items="boolUpdateOptions" :label="$t('substitute_children')" clearable v-model="batchUpdateRequest.foodBatchUpdate.substituteSiblings"></v-select>
|
||||
<model-select model="Food" :label="$t('Parent')" :object="false" allow-create clearable v-model="batchUpdateRequest.foodBatchUpdate.parentSet">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-equals"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
|
||||
<v-select :items="boolUpdateOptions" :label="$t('RemoveParent')" clearable v-model="batchUpdateRequest.foodBatchUpdate.parentRemove"></v-select>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
|
||||
@@ -127,6 +127,18 @@ export interface FoodBatchUpdate {
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
onHand?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
parentRemove?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
parentSet?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,6 +186,8 @@ export function FoodBatchUpdateFromJSONTyped(json: any, ignoreDiscriminator: boo
|
||||
'substituteSiblings': json['substitute_siblings'] == null ? undefined : json['substitute_siblings'],
|
||||
'ignoreShopping': json['ignore_shopping'] == null ? undefined : json['ignore_shopping'],
|
||||
'onHand': json['on_hand'] == null ? undefined : json['on_hand'],
|
||||
'parentRemove': json['parent_remove'] == null ? undefined : json['parent_remove'],
|
||||
'parentSet': json['parent_set'] == null ? undefined : json['parent_set'],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -201,6 +215,8 @@ export function FoodBatchUpdateToJSON(value?: FoodBatchUpdate | null): any {
|
||||
'substitute_siblings': value['substituteSiblings'],
|
||||
'ignore_shopping': value['ignoreShopping'],
|
||||
'on_hand': value['onHand'],
|
||||
'parent_remove': value['parentRemove'],
|
||||
'parent_set': value['parentSet'],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user