mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-11-01 16:14:30 +01:00
Alpha version (without tests)
This commit is contained in:
@@ -4,10 +4,14 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django.db import models, transaction
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils import timezone
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from polymorphic.models import PolymorphicModel
|
||||
from member.models import Club
|
||||
from activity.models import Activity
|
||||
from note.models import Transaction
|
||||
|
||||
|
||||
class Allergen(models.Model):
|
||||
@@ -284,3 +288,199 @@ class QRCode(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
return _('QR-code number') + ' ' + str(self.qr_code_number)
|
||||
|
||||
|
||||
class Dish(models.Model):
|
||||
"""
|
||||
A dish is a food proposed during a meal
|
||||
"""
|
||||
main = models.ForeignKey(
|
||||
TransformedFood,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='dishes_as_main',
|
||||
verbose_name=_('main food'),
|
||||
)
|
||||
|
||||
price = models.PositiveIntegerField(
|
||||
verbose_name=_('price')
|
||||
)
|
||||
|
||||
activity = models.ForeignKey(
|
||||
Activity,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='dishes',
|
||||
verbose_name=_('activity'),
|
||||
)
|
||||
|
||||
available = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name=_('available'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Dish')
|
||||
verbose_name_plural = _('Dishes')
|
||||
unique_together = ('main', 'activity')
|
||||
|
||||
def __str__(self):
|
||||
return self.main.name + ' (' + str(self.activity) + ')'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"Check the type of activity"
|
||||
if self.activity.activity_type.name != 'Perm bouffe':
|
||||
raise ValidationError(_('(You cannot select this type of activity.'))
|
||||
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class Supplement(models.Model):
|
||||
"""
|
||||
A supplement is a food added to a dish
|
||||
"""
|
||||
dish = models.ForeignKey(
|
||||
Dish,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='supplements',
|
||||
verbose_name=_('dish'),
|
||||
)
|
||||
|
||||
food = models.ForeignKey(
|
||||
Food,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='supplements',
|
||||
verbose_name=_('food'),
|
||||
)
|
||||
|
||||
price = models.PositiveIntegerField(
|
||||
verbose_name=_('price')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Supplement')
|
||||
verbose_name_plural = _('Supplements')
|
||||
|
||||
def __str__(self):
|
||||
return _("Supplement {food} for {dish}").format(
|
||||
food=str(self.food), dish=str(self.dish))
|
||||
|
||||
|
||||
class Order(models.Model):
|
||||
"""
|
||||
An order is a dish ordered by a member during an activity
|
||||
"""
|
||||
user = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='food_orders',
|
||||
verbose_name=_('user'),
|
||||
)
|
||||
|
||||
activity = models.ForeignKey(
|
||||
Activity,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='food_orders',
|
||||
verbose_name=_('activity'),
|
||||
)
|
||||
|
||||
dish = models.ForeignKey(
|
||||
Dish,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='orders',
|
||||
verbose_name=_('dish'),
|
||||
)
|
||||
|
||||
supplements = models.ManyToManyField(
|
||||
Supplement,
|
||||
related_name='orders',
|
||||
verbose_name=_('supplements'),
|
||||
blank=True,
|
||||
)
|
||||
|
||||
request = models.TextField(
|
||||
blank=True,
|
||||
verbose_name=_('request'),
|
||||
help_text=_('A specific request (to remove an ingredient for example)')
|
||||
)
|
||||
|
||||
number = models.PositiveIntegerField(
|
||||
verbose_name=_('number'),
|
||||
default=1,
|
||||
)
|
||||
|
||||
ordered_at = models.DateTimeField(
|
||||
default=timezone.now,
|
||||
verbose_name=_('order date'),
|
||||
)
|
||||
|
||||
served = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_('served'),
|
||||
)
|
||||
|
||||
served_at = models.DateTimeField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name=_('served date'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Order')
|
||||
verbose_name_plural = _('Orders')
|
||||
unique_together = ('activity', 'number', )
|
||||
|
||||
@property
|
||||
def amount(self):
|
||||
return self.dish.price + sum(s.price for s in self.supplements.all())
|
||||
|
||||
def __str__(self):
|
||||
return _("Order of {dish} by {user}").format(
|
||||
dish=str(self.dish),
|
||||
user=str(self.user))
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
created = self.pk is None
|
||||
if created:
|
||||
last_order = Order.objects.filter(activity=self.activity).last()
|
||||
if last_order is None:
|
||||
self.number = 1
|
||||
else:
|
||||
self.number = last_order.number + 1
|
||||
|
||||
elif self.served:
|
||||
if FoodTransaction.objects.filter(order=self).exists():
|
||||
transaction = FoodTransaction.objects.get(order=self)
|
||||
transaction.valid = True
|
||||
transaction.save()
|
||||
else:
|
||||
transaction = FoodTransaction(
|
||||
source=self.user.note,
|
||||
destination=self.activity.organizer.note,
|
||||
amount=self.amount,
|
||||
quantity=1,
|
||||
valid=True,
|
||||
order=self,
|
||||
)
|
||||
transaction.save()
|
||||
else:
|
||||
if FoodTransaction.objects.filter(order=self).exists():
|
||||
transaction = FoodTransaction.objects.get(order=self)
|
||||
transaction.valid = False
|
||||
transaction.save()
|
||||
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class FoodTransaction(Transaction):
|
||||
"""
|
||||
Special type of :model:`note.Transaction` associated to a :model:`food.Order`.
|
||||
"""
|
||||
order = models.ForeignKey(
|
||||
Order,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='transaction',
|
||||
verbose_name=_('order')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("food transaction")
|
||||
verbose_name_plural = _("food transactions")
|
||||
|
||||
Reference in New Issue
Block a user