fixed several shopping list issues

This commit is contained in:
vabene1111
2020-09-22 12:01:11 +02:00
parent 9b36f51d16
commit 678cfaca12
6 changed files with 82 additions and 39 deletions

View File

@ -61,12 +61,14 @@ def is_object_owner(user, obj):
# TODO this could be improved/cleaned up by adding get_owner methods to all models that allow owner checks # TODO this could be improved/cleaned up by adding get_owner methods to all models that allow owner checks
if not user.is_authenticated: if not user.is_authenticated:
return False return False
if user.is_superuser:
return True
if owner := getattr(obj, 'created_by', None): if owner := getattr(obj, 'created_by', None):
return owner == user return owner == user
if owner := getattr(obj, 'user', None): if owner := getattr(obj, 'user', None):
return owner == user return owner == user
if getattr(obj, 'get_owner', None):
return obj.get_owner() == user
if user.is_superuser:
return True
return False return False

View File

@ -0,0 +1,24 @@
# Generated by Django 3.0.7 on 2020-09-22 09:43
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0081_auto_20200921_2349'),
]
operations = [
migrations.AlterField(
model_name='invitelink',
name='valid_until',
field=models.DateField(default=datetime.date(2020, 10, 6)),
),
migrations.AlterField(
model_name='shoppinglistentry',
name='amount',
field=models.DecimalField(decimal_places=16, default=0, max_digits=32),
),
]

View File

@ -275,18 +275,30 @@ class ShoppingListRecipe(models.Model):
def __str__(self): def __str__(self):
return f'Shopping list recipe {self.id} - {self.recipe}' return f'Shopping list recipe {self.id} - {self.recipe}'
def get_owner(self):
try:
return self.shoppinglist_set.first().created_by
except AttributeError:
return None
class ShoppingListEntry(models.Model): class ShoppingListEntry(models.Model):
list_recipe = models.ForeignKey(ShoppingListRecipe, on_delete=models.CASCADE, null=True, blank=True) list_recipe = models.ForeignKey(ShoppingListRecipe, on_delete=models.CASCADE, null=True, blank=True)
food = models.ForeignKey(Food, on_delete=models.CASCADE) food = models.ForeignKey(Food, on_delete=models.CASCADE)
unit = models.ForeignKey(Unit, on_delete=models.CASCADE, null=True, blank=True) unit = models.ForeignKey(Unit, on_delete=models.CASCADE, null=True, blank=True)
amount = models.IntegerField(default=1) amount = models.DecimalField(default=0, decimal_places=16, max_digits=32)
order = models.IntegerField(default=0) order = models.IntegerField(default=0)
checked = models.BooleanField(default=False) checked = models.BooleanField(default=False)
def __str__(self): def __str__(self):
return f'Shopping list entry {self.id}' return f'Shopping list entry {self.id}'
def get_owner(self):
try:
return self.shoppinglist_set.first().created_by
except AttributeError:
return None
class ShoppingList(models.Model): class ShoppingList(models.Model):
uuid = models.UUIDField(default=uuid.uuid4) uuid = models.UUIDField(default=uuid.uuid4)

View File

@ -208,6 +208,7 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer):
class ShoppingListEntrySerializer(WritableNestedModelSerializer): class ShoppingListEntrySerializer(WritableNestedModelSerializer):
food = FoodSerializer(allow_null=True) food = FoodSerializer(allow_null=True)
unit = UnitSerializer(allow_null=True) unit = UnitSerializer(allow_null=True)
amount = CustomDecimalField()
class Meta: class Meta:
model = ShoppingListEntry model = ShoppingListEntry

View File

@ -313,23 +313,13 @@
}, },
*/ */
mounted: function () { mounted: function () {
if (this.shopping_list_id) {
this.loadShoppingList() this.loadShoppingList()
} else {
//TODO default share users
this.shopping_list = {
"recipes": [],
"entries": [],
"entries_display": [],
"shared": [],
"created_by": 1
}
this.loading = false
}
{% if request.user.userpreference.shopping_auto_sync > 0 %} {% if request.user.userpreference.shopping_auto_sync > 0 %}
setInterval(() => { setInterval(() => {
if ((this.shopping_list_id !== null) && !this.edit_mode) {
this.loadShoppingList(true) this.loadShoppingList(true)
}
}, {{ request.user.userpreference.shopping_auto_sync }} * 1000 ) }, {{ request.user.userpreference.shopping_auto_sync }} * 1000 )
{% endif %} {% endif %}
}, },
@ -352,7 +342,9 @@
}) })
}, },
loadShoppingList: function (autosync = false) { loadShoppingList: function (autosync = false) {
this.$http.get("{% url 'api:shoppinglist-detail' shopping_list_id %}" + ((autosync) ? '?autosync=true' : '')).then((response) => {
if (this.shopping_list_id) {
this.$http.get("{% url 'api:shoppinglist-detail' 123456 %}".replace('123456', this.shopping_list_id) + ((autosync) ? '?autosync=true' : '')).then((response) => {
if (!autosync) { if (!autosync) {
this.shopping_list = response.body this.shopping_list = response.body
this.loading = false this.loading = false
@ -363,14 +355,26 @@
} }
for (let se of this.shopping_list.entries) { for (let se of this.shopping_list.entries) {
if (check_map[se.id] !== undefined) {
se.checked = check_map[se.id].checked se.checked = check_map[se.id].checked
} }
} }
}
}).catch((err) => { }).catch((err) => {
console.log(err) console.log(err)
this.makeToast('{% trans 'Error' %}', '{% trans 'There was an error loading a resource!' %}' + err.bodyText, 'danger') this.makeToast('{% trans 'Error' %}', '{% trans 'There was an error loading a resource!' %}' + err.bodyText, 'danger')
}) })
} else {
this.shopping_list = {
"recipes": [],
"entries": [],
"entries_display": [],
"shared": [],
"created_by": 1
}
this.loading = false
}
}, },
updateShoppingList: function () { updateShoppingList: function () {
this.loading = true this.loading = true
@ -382,7 +386,7 @@
recipe_promises.push(this.$http.post("{% url 'api:shoppinglistrecipe-list' %}", this.shopping_list.recipes[i], {}).then((response) => { recipe_promises.push(this.$http.post("{% url 'api:shoppinglistrecipe-list' %}", this.shopping_list.recipes[i], {}).then((response) => {
let old_id = this.shopping_list.recipes[i].id let old_id = this.shopping_list.recipes[i].id
console.log("list recipe create respose ", response.body) console.log("list recipe create respose ", response.body)
this.shopping_list.recipes[i] = response.body this.$set(this.shopping_list.recipes, i, response.body)
for (let e of this.shopping_list.entries.filter(item => item.list_recipe === old_id)) { for (let e of this.shopping_list.entries.filter(item => item.list_recipe === old_id)) {
console.log("found recipe updating ID") console.log("found recipe updating ID")
e.list_recipe = this.shopping_list.recipes[i].id e.list_recipe = this.shopping_list.recipes[i].id
@ -403,6 +407,7 @@
this.makeToast('{% trans 'Updated' %}', '{% trans 'Object created successfully!' %}', 'success') this.makeToast('{% trans 'Updated' %}', '{% trans 'Object created successfully!' %}', 'success')
this.loading = false this.loading = false
this.shopping_list = response.body this.shopping_list = response.body
this.shopping_list_id = this.shopping_list.id
}).catch((err) => { }).catch((err) => {
console.log(err) console.log(err)
this.makeToast('{% trans 'Error' %}', '{% trans 'There was an error creating a resource!' %}' + err.bodyText, 'danger') this.makeToast('{% trans 'Error' %}', '{% trans 'There was an error creating a resource!' %}' + err.bodyText, 'danger')
@ -485,7 +490,7 @@
return '{% url 'view_recipe' 123456 %}'.replace('123456', id) return '{% url 'view_recipe' 123456 %}'.replace('123456', id)
}, },
addRecipeToList: function (recipe) { addRecipeToList: function (recipe) {
console.log(this.shopping_list)
let slr = { let slr = {
"created": true, "created": true,
@ -494,12 +499,12 @@
"recipe_name": recipe.name, "recipe_name": recipe.name,
"multiplier": 1 "multiplier": 1
} }
this.shopping_list.recipes.push(slr) this.shopping_list.recipes.push(slr)
for (let s of recipe.steps) { for (let s of recipe.steps) {
for (let i of s.ingredients) { for (let i of s.ingredients) {
if (!i.is_header && i.food !== null) {
if (!i.is_header) {
this.shopping_list.entries.push({ this.shopping_list.entries.push({
'list_recipe': slr.id, 'list_recipe': slr.id,
'food': i.food, 'food': i.food,
@ -510,7 +515,6 @@
} }
} }
} }
}, },
searchKeywords: function (query) { searchKeywords: function (query) {
this.keywords_loading = true this.keywords_loading = true

View File

@ -252,7 +252,7 @@ class ShoppingListRecipeViewSet(viewsets.ModelViewSet):
class ShoppingListEntryViewSet(viewsets.ModelViewSet): class ShoppingListEntryViewSet(viewsets.ModelViewSet):
queryset = ShoppingListEntry.objects.all() queryset = ShoppingListEntry.objects.all()
serializer_class = ShoppingListEntrySerializer serializer_class = ShoppingListEntrySerializer
permission_classes = [CustomIsUser] # TODO add custom validation permission_classes = [CustomIsOwner] # TODO add custom validation
# TODO custom get qs # TODO custom get qs