fixed several shopping list issues
This commit is contained in:
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
24
cookbook/migrations/0082_auto_20200922_1143.py
Normal file
24
cookbook/migrations/0082_auto_20200922_1143.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user