mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-12-18 13:32:28 +00:00
Add new application to manage note sheets
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
parent
ba017c38c0
commit
44994a3ae7
@ -26,6 +26,10 @@ if "note" in settings.INSTALLED_APPS:
|
|||||||
from note.api.urls import register_note_urls
|
from note.api.urls import register_note_urls
|
||||||
register_note_urls(router, 'note')
|
register_note_urls(router, 'note')
|
||||||
|
|
||||||
|
if "sheets" in settings.INSTALLED_APPS:
|
||||||
|
from sheets.api.urls import register_sheets_urls
|
||||||
|
register_sheets_urls(router, 'sheets')
|
||||||
|
|
||||||
if "treasury" in settings.INSTALLED_APPS:
|
if "treasury" in settings.INSTALLED_APPS:
|
||||||
from treasury.api.urls import register_treasury_urls
|
from treasury.api.urls import register_treasury_urls
|
||||||
register_treasury_urls(router, 'treasury')
|
register_treasury_urls(router, 'treasury')
|
||||||
|
4
apps/sheets/__init__.py
Normal file
4
apps/sheets/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Copyright (C) 2018-2022 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
default_app_config = 'sheets.apps.SheetsConfig'
|
46
apps/sheets/admin.py
Normal file
46
apps/sheets/admin.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Copyright (C) 2018-2022 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from django.contrib import admin
|
||||||
|
from note_kfet.admin import admin_site
|
||||||
|
from sheets.models import Sheet, Food, FoodOption, Meal, Order, OrderedMeal, OrderedFood, SheetOrderTransaction
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Sheet, site=admin_site)
|
||||||
|
class SheetAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Food, site=admin_site)
|
||||||
|
class FoodAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(FoodOption, site=admin_site)
|
||||||
|
class FoodOptionAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Meal, site=admin_site)
|
||||||
|
class MealAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Order, site=admin_site)
|
||||||
|
class OrderAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(OrderedMeal, site=admin_site)
|
||||||
|
class OrderedMealAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(OrderedFood, site=admin_site)
|
||||||
|
class OrderedFoodAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(SheetOrderTransaction, site=admin_site)
|
||||||
|
class SheetOrderTransactionAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
0
apps/sheets/api/__init__.py
Normal file
0
apps/sheets/api/__init__.py
Normal file
55
apps/sheets/api/serializers.py
Normal file
55
apps/sheets/api/serializers.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
|
from ..models import Sheet, Food, FoodOption, Meal, Order, OrderedMeal, OrderedFood, SheetOrderTransaction
|
||||||
|
|
||||||
|
|
||||||
|
class SheetSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Sheet
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class FoodSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Food
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class FoodOptionSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = FoodOption
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class MealSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Meal
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class OrderSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Order
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class OrderedMealSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = OrderedMeal
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class OrderedFoodSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = OrderedFood
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class SheetOrderTransactionSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = SheetOrderTransaction
|
||||||
|
fields = '__all__'
|
19
apps/sheets/api/urls.py
Normal file
19
apps/sheets/api/urls.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from sheets.api.views import SheetViewSet, FoodViewSet, FoodOptionViewSet, MealViewSet, OrderViewSet, \
|
||||||
|
OrderedMealViewSet, OrderedFoodViewSet, SheetOrderTransactionViewSet
|
||||||
|
|
||||||
|
|
||||||
|
def register_sheets_urls(router, path):
|
||||||
|
"""
|
||||||
|
Configure router for Sheets REST API.
|
||||||
|
"""
|
||||||
|
router.register(path + '/sheet', SheetViewSet)
|
||||||
|
router.register(path + '/food', FoodViewSet)
|
||||||
|
router.register(path + '/foodoption', FoodOptionViewSet)
|
||||||
|
router.register(path + '/meal', MealViewSet)
|
||||||
|
router.register(path + '/order', OrderViewSet)
|
||||||
|
router.register(path + '/orderedmeal', OrderedMealViewSet)
|
||||||
|
router.register(path + '/orderedfood', OrderedFoodViewSet)
|
||||||
|
router.register(path + '/sheetordertransaction', SheetOrderTransactionViewSet)
|
78
apps/sheets/api/views.py
Normal file
78
apps/sheets/api/views.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from api.viewsets import ReadProtectedModelViewSet
|
||||||
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
|
from rest_framework.filters import SearchFilter, OrderingFilter
|
||||||
|
|
||||||
|
from .serializers import SheetSerializer, FoodSerializer, FoodOptionSerializer, MealSerializer, OrderSerializer, \
|
||||||
|
OrderedMealSerializer, OrderedFoodSerializer, SheetOrderTransactionSerializer
|
||||||
|
from ..models import Sheet, Food, FoodOption, Meal, Order, OrderedMeal, OrderedFood, SheetOrderTransaction
|
||||||
|
|
||||||
|
|
||||||
|
class SheetViewSet(ReadProtectedModelViewSet):
|
||||||
|
queryset = Sheet.objects.order_by('id')
|
||||||
|
serializer_class = SheetSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter]
|
||||||
|
filterset_fields = ['name', 'date', ]
|
||||||
|
search_fields = ['$name', ]
|
||||||
|
|
||||||
|
|
||||||
|
class FoodViewSet(ReadProtectedModelViewSet):
|
||||||
|
queryset = Food.objects.order_by('id')
|
||||||
|
serializer_class = FoodSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter]
|
||||||
|
filterset_fields = ['name', 'sheet', 'price', 'club', 'available', ]
|
||||||
|
search_fields = ['$name', ]
|
||||||
|
|
||||||
|
|
||||||
|
class FoodOptionViewSet(ReadProtectedModelViewSet):
|
||||||
|
queryset = FoodOption.objects.order_by('id')
|
||||||
|
serializer_class = FoodOptionSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter]
|
||||||
|
filterset_fields = ['name', 'food', 'extra_cost', 'available', ]
|
||||||
|
search_fields = ['$name', '$food__name', ]
|
||||||
|
|
||||||
|
|
||||||
|
class MealViewSet(ReadProtectedModelViewSet):
|
||||||
|
queryset = Meal.objects.order_by('id')
|
||||||
|
serializer_class = MealSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter]
|
||||||
|
filterset_fields = ['name', 'content', 'price', 'available', ]
|
||||||
|
search_fields = ['$name', ]
|
||||||
|
|
||||||
|
|
||||||
|
class OrderViewSet(ReadProtectedModelViewSet):
|
||||||
|
queryset = Order.objects.order_by('id')
|
||||||
|
serializer_class = OrderSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter]
|
||||||
|
filterset_fields = ['sheet', 'note', 'date', 'gift', ]
|
||||||
|
search_fields = ['$sheet__name', '$note__alias__name', '$note__alias__normalized_name', ]
|
||||||
|
|
||||||
|
|
||||||
|
class OrderedMealViewSet(ReadProtectedModelViewSet):
|
||||||
|
queryset = OrderedMeal.objects.order_by('id')
|
||||||
|
serializer_class = OrderedMealSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend]
|
||||||
|
filterset_fields = ['order', 'meal', ]
|
||||||
|
|
||||||
|
|
||||||
|
class OrderedFoodViewSet(ReadProtectedModelViewSet):
|
||||||
|
queryset = OrderedFood.objects.order_by('id')
|
||||||
|
serializer_class = OrderedFoodSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend]
|
||||||
|
filterset_fields = ['order', 'meal', 'food', 'options', 'number', 'status', 'served_date', ]
|
||||||
|
|
||||||
|
|
||||||
|
class SheetOrderTransactionViewSet(ReadProtectedModelViewSet):
|
||||||
|
queryset = SheetOrderTransaction.objects.order_by('-created_at')
|
||||||
|
serializer_class = SheetOrderTransactionSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
|
filterset_fields = ['source', 'source_alias', 'source__alias__name', 'source__alias__normalized_name',
|
||||||
|
'destination', 'destination_alias', 'destination__alias__name',
|
||||||
|
'destination__alias__normalized_name', 'quantity', 'polymorphic_ctype', 'amount',
|
||||||
|
'created_at', 'valid', 'invalidity_reason', 'ordered_food', ]
|
||||||
|
search_fields = ['$reason', '$source_alias', '$source__alias__name', '$source__alias__normalized_name',
|
||||||
|
'$destination_alias', '$destination__alias__name', '$destination__alias__normalized_name',
|
||||||
|
'$invalidity_reason', ]
|
||||||
|
ordering_fields = ['created_at', 'amount', ]
|
10
apps/sheets/apps.py
Normal file
10
apps/sheets/apps.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Copyright (C) 2018-2022 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class SheetsConfig(AppConfig):
|
||||||
|
name = 'sheets'
|
||||||
|
verbose_name = _('note sheets')
|
156
apps/sheets/migrations/0001_initial.py
Normal file
156
apps/sheets/migrations/0001_initial.py
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
# Generated by Django 2.2.27 on 2022-08-18 10:25
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('note', '0006_trust'),
|
||||||
|
('member', '0009_auto_20220818_1225'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Food',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, verbose_name='food')),
|
||||||
|
('price', models.IntegerField(verbose_name='price')),
|
||||||
|
('available', models.BooleanField(default=True, help_text="If set to false, this option won't be offered (in case of out of stock)", verbose_name='available')),
|
||||||
|
('club', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='member.Club', verbose_name='destination club')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'food',
|
||||||
|
'verbose_name_plural': 'food',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='FoodOption',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, verbose_name='name')),
|
||||||
|
('extra_cost', models.IntegerField(default=0, verbose_name='extra cost')),
|
||||||
|
('available', models.BooleanField(default=True, help_text="If set to false, this option won't be offered (in case of out of stock)", verbose_name='available')),
|
||||||
|
('food', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sheets.Food', verbose_name='food')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'food option',
|
||||||
|
'verbose_name_plural': 'food options',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Meal',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, verbose_name='name')),
|
||||||
|
('price', models.IntegerField(verbose_name='price')),
|
||||||
|
('available', models.BooleanField(default=True, help_text="If set to false, this option won't be offered (in case of out of stock)", verbose_name='available')),
|
||||||
|
('content', models.ManyToManyField(to='sheets.Food', verbose_name='content')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'meal',
|
||||||
|
'verbose_name_plural': 'meals',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Order',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('date', models.DateTimeField(auto_now_add=True, verbose_name='date')),
|
||||||
|
('gift', models.IntegerField(verbose_name='gift')),
|
||||||
|
('note', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='note.Note', verbose_name='note')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'order',
|
||||||
|
'verbose_name_plural': 'orders',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='OrderedFood',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('remark', models.TextField(blank=True, default='', verbose_name='remark')),
|
||||||
|
('priority', models.CharField(blank=True, default='', max_length=64, verbose_name='priority request')),
|
||||||
|
('number', models.IntegerField(help_text='How many times the user ordered this.', verbose_name='number')),
|
||||||
|
('status', models.CharField(choices=[('QUEUED', 'queued'), ('READY', 'ready'), ('SERVED', 'served'), ('CANCELED', 'canceled')], max_length=8, verbose_name='status')),
|
||||||
|
('served_date', models.DateTimeField(default=None, null=True, verbose_name='served date')),
|
||||||
|
('food', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='sheets.Food', verbose_name='food')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'ordered food',
|
||||||
|
'verbose_name_plural': 'ordered food',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Sheet',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, verbose_name='name')),
|
||||||
|
('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='start date')),
|
||||||
|
('description', models.TextField(verbose_name='description')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'note sheet',
|
||||||
|
'verbose_name_plural': 'note sheets',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SheetOrderTransaction',
|
||||||
|
fields=[
|
||||||
|
('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Transaction')),
|
||||||
|
('ordered_food', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='sheets.OrderedFood', verbose_name='ordered food')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'sheet order transaction',
|
||||||
|
'verbose_name_plural': 'sheet order transactions',
|
||||||
|
},
|
||||||
|
bases=('note.transaction',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='OrderedMeal',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('meal', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='sheets.Meal', verbose_name='meal')),
|
||||||
|
('order', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='sheets.Order', verbose_name='order')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'ordered meal',
|
||||||
|
'verbose_name_plural': 'ordered meals',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='orderedfood',
|
||||||
|
name='meal',
|
||||||
|
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='sheets.OrderedMeal', verbose_name='ordered meal'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='orderedfood',
|
||||||
|
name='options',
|
||||||
|
field=models.ManyToManyField(blank=True, to='sheets.FoodOption', verbose_name='options'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='orderedfood',
|
||||||
|
name='order',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='sheets.Order', verbose_name='order'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='order',
|
||||||
|
name='sheet',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='sheets.Sheet', verbose_name='note sheet'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='meal',
|
||||||
|
name='sheet',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sheets.Sheet', verbose_name='note sheet'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='food',
|
||||||
|
name='sheet',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sheets.Sheet', verbose_name='note sheet'),
|
||||||
|
),
|
||||||
|
]
|
0
apps/sheets/migrations/__init__.py
Normal file
0
apps/sheets/migrations/__init__.py
Normal file
260
apps/sheets/models.py
Normal file
260
apps/sheets/models.py
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from member.models import Club
|
||||||
|
from note.models import Note, Transaction
|
||||||
|
|
||||||
|
|
||||||
|
class Sheet(models.Model):
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("name"),
|
||||||
|
)
|
||||||
|
|
||||||
|
date = models.DateTimeField(
|
||||||
|
verbose_name=_("start date"),
|
||||||
|
default=timezone.now,
|
||||||
|
)
|
||||||
|
|
||||||
|
description = models.TextField(
|
||||||
|
verbose_name=_("description"),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("note sheet")
|
||||||
|
verbose_name_plural = _("note sheets")
|
||||||
|
|
||||||
|
|
||||||
|
class Food(models.Model):
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("food"),
|
||||||
|
)
|
||||||
|
|
||||||
|
sheet = models.ForeignKey(
|
||||||
|
Sheet,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
verbose_name=_("note sheet"),
|
||||||
|
)
|
||||||
|
|
||||||
|
price = models.IntegerField(
|
||||||
|
verbose_name=_("price"),
|
||||||
|
)
|
||||||
|
|
||||||
|
club = models.ForeignKey(
|
||||||
|
Club,
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
verbose_name=_("destination club"),
|
||||||
|
)
|
||||||
|
|
||||||
|
available = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
verbose_name=_("available"),
|
||||||
|
help_text=_("If set to false, this option won't be offered (in case of out of stock)"),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("food")
|
||||||
|
verbose_name_plural = _("food")
|
||||||
|
|
||||||
|
|
||||||
|
class FoodOption(models.Model):
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("name"),
|
||||||
|
)
|
||||||
|
|
||||||
|
food = models.ForeignKey(
|
||||||
|
Food,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
verbose_name=_("food"),
|
||||||
|
)
|
||||||
|
|
||||||
|
extra_cost = models.IntegerField(
|
||||||
|
default=0,
|
||||||
|
verbose_name=_("extra cost"),
|
||||||
|
)
|
||||||
|
|
||||||
|
available = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
verbose_name=_("available"),
|
||||||
|
help_text=_("If set to false, this option won't be offered (in case of out of stock)"),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("food option")
|
||||||
|
verbose_name_plural = _("food options")
|
||||||
|
|
||||||
|
|
||||||
|
class Meal(models.Model):
|
||||||
|
sheet = models.ForeignKey(
|
||||||
|
Sheet,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
verbose_name=_("note sheet"),
|
||||||
|
)
|
||||||
|
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("name"),
|
||||||
|
)
|
||||||
|
|
||||||
|
content = models.ManyToManyField(
|
||||||
|
Food,
|
||||||
|
verbose_name=_("content"),
|
||||||
|
)
|
||||||
|
|
||||||
|
price = models.IntegerField(
|
||||||
|
verbose_name=_("price"),
|
||||||
|
)
|
||||||
|
|
||||||
|
available = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
verbose_name=_("available"),
|
||||||
|
help_text=_("If set to false, this option won't be offered (in case of out of stock)"),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("meal")
|
||||||
|
verbose_name_plural = _("meals")
|
||||||
|
|
||||||
|
|
||||||
|
class Order(models.Model):
|
||||||
|
sheet = models.ForeignKey(
|
||||||
|
Sheet,
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
verbose_name=_("note sheet"),
|
||||||
|
)
|
||||||
|
|
||||||
|
note = models.ForeignKey(
|
||||||
|
Note,
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
verbose_name=_("note"),
|
||||||
|
)
|
||||||
|
|
||||||
|
date = models.DateTimeField(
|
||||||
|
verbose_name=_("date"),
|
||||||
|
auto_now_add=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
gift = models.IntegerField(
|
||||||
|
verbose_name=_("gift"),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("order")
|
||||||
|
verbose_name_plural = _("orders")
|
||||||
|
|
||||||
|
|
||||||
|
class OrderedMeal(models.Model):
|
||||||
|
order = models.ForeignKey(
|
||||||
|
Order,
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
verbose_name=_("order"),
|
||||||
|
)
|
||||||
|
|
||||||
|
meal = models.ForeignKey(
|
||||||
|
Meal,
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
verbose_name=_("meal"),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("ordered meal")
|
||||||
|
verbose_name_plural = _("ordered meals")
|
||||||
|
|
||||||
|
|
||||||
|
class OrderedFood(models.Model):
|
||||||
|
order = models.ForeignKey(
|
||||||
|
Order,
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
verbose_name=_("order"),
|
||||||
|
)
|
||||||
|
|
||||||
|
meal = models.ForeignKey(
|
||||||
|
OrderedMeal,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
default=None,
|
||||||
|
verbose_name=_("ordered meal"),
|
||||||
|
)
|
||||||
|
|
||||||
|
food = models.ForeignKey(
|
||||||
|
Food,
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
verbose_name=_("food"),
|
||||||
|
)
|
||||||
|
|
||||||
|
options = models.ManyToManyField(
|
||||||
|
FoodOption,
|
||||||
|
blank=True,
|
||||||
|
verbose_name=_("options"),
|
||||||
|
)
|
||||||
|
|
||||||
|
remark = models.TextField(
|
||||||
|
blank=True,
|
||||||
|
default="",
|
||||||
|
verbose_name=_("remark"),
|
||||||
|
)
|
||||||
|
|
||||||
|
priority = models.CharField(
|
||||||
|
max_length=64,
|
||||||
|
blank=True,
|
||||||
|
default="",
|
||||||
|
verbose_name=_("priority request"),
|
||||||
|
)
|
||||||
|
|
||||||
|
number = models.IntegerField(
|
||||||
|
verbose_name=_("number"),
|
||||||
|
help_text=_("How many times the user ordered this."),
|
||||||
|
)
|
||||||
|
|
||||||
|
status = models.CharField(
|
||||||
|
max_length=8,
|
||||||
|
choices=[
|
||||||
|
('QUEUED', _("queued")),
|
||||||
|
('READY', _("ready")),
|
||||||
|
('SERVED', _("served")),
|
||||||
|
('CANCELED', _("canceled")),
|
||||||
|
],
|
||||||
|
verbose_name=_("status"),
|
||||||
|
)
|
||||||
|
|
||||||
|
served_date = models.DateTimeField(
|
||||||
|
null=True,
|
||||||
|
default=None,
|
||||||
|
verbose_name=_("served date")
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("ordered food")
|
||||||
|
verbose_name_plural = _("ordered food")
|
||||||
|
|
||||||
|
|
||||||
|
class SheetOrderTransaction(Transaction):
|
||||||
|
ordered_food = models.ForeignKey(
|
||||||
|
OrderedFood,
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
verbose_name=_("ordered food"),
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
return _("note sheet")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def price(self):
|
||||||
|
if self.ordered_food.meal:
|
||||||
|
return sum(ordered_food.price + sum(opt.extra_cost for opt in ordered_food.options.all())
|
||||||
|
for ordered_food in self.ordered_food.meal.orderedfood_set.exclude(status='CANCELED').all())
|
||||||
|
elif self.ordered_food.status == 'CANCELED':
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return self.ordered_food.food.price + sum(opt.extra_cost for opt in self.ordered_food.options.all())
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("sheet order transaction")
|
||||||
|
verbose_name_plural = _("sheet order transactions")
|
0
apps/sheets/tests/__init__.py
Normal file
0
apps/sheets/tests/__init__.py
Normal file
9
apps/sheets/urls.py
Normal file
9
apps/sheets/urls.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (C) 2018-2022 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
app_name = 'sheets'
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
]
|
2
apps/sheets/views.py
Normal file
2
apps/sheets/views.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Copyright (C) 2018-2022 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-10 22:34+0200\n"
|
"POT-Creation-Date: 2022-08-18 12:30+0200\n"
|
||||||
"PO-Revision-Date: 2022-04-11 22:05+0200\n"
|
"PO-Revision-Date: 2022-04-11 22:05+0200\n"
|
||||||
"Last-Translator: elkmaennchen <elkmaennchen@crans.org>\n"
|
"Last-Translator: elkmaennchen <elkmaennchen@crans.org>\n"
|
||||||
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
|
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
|
||||||
@ -60,6 +60,7 @@ msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
|
|||||||
#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:301
|
#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:301
|
||||||
#: apps/permission/models.py:330
|
#: apps/permission/models.py:330
|
||||||
#: apps/registration/templates/registration/future_profile_detail.html:16
|
#: apps/registration/templates/registration/future_profile_detail.html:16
|
||||||
|
#: apps/sheets/models.py:15 apps/sheets/models.py:68 apps/sheets/models.py:102
|
||||||
#: apps/wei/models.py:67 apps/wei/models.py:131 apps/wei/tables.py:282
|
#: apps/wei/models.py:67 apps/wei/models.py:131 apps/wei/tables.py:282
|
||||||
#: apps/wei/templates/wei/base.html:26
|
#: apps/wei/templates/wei/base.html:26
|
||||||
#: apps/wei/templates/wei/weimembership_form.html:14
|
#: apps/wei/templates/wei/weimembership_form.html:14
|
||||||
@ -95,7 +96,8 @@ msgstr "types d'activité"
|
|||||||
#: apps/activity/models.py:68
|
#: apps/activity/models.py:68
|
||||||
#: apps/activity/templates/activity/includes/activity_info.html:19
|
#: apps/activity/templates/activity/includes/activity_info.html:19
|
||||||
#: apps/note/models/transactions.py:81 apps/permission/models.py:110
|
#: apps/note/models/transactions.py:81 apps/permission/models.py:110
|
||||||
#: apps/permission/models.py:189 apps/wei/models.py:78 apps/wei/models.py:142
|
#: apps/permission/models.py:189 apps/sheets/models.py:24 apps/wei/models.py:78
|
||||||
|
#: apps/wei/models.py:142
|
||||||
msgid "description"
|
msgid "description"
|
||||||
msgstr "description"
|
msgstr "description"
|
||||||
|
|
||||||
@ -143,6 +145,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: apps/activity/models.py:109
|
#: apps/activity/models.py:109
|
||||||
#: apps/activity/templates/activity/includes/activity_info.html:25
|
#: apps/activity/templates/activity/includes/activity_info.html:25
|
||||||
|
#: apps/sheets/models.py:19
|
||||||
msgid "start date"
|
msgid "start date"
|
||||||
msgstr "date de début"
|
msgstr "date de début"
|
||||||
|
|
||||||
@ -171,7 +174,7 @@ msgid "entry time"
|
|||||||
msgstr "heure d'entrée"
|
msgstr "heure d'entrée"
|
||||||
|
|
||||||
#: apps/activity/models.py:178 apps/note/apps.py:14
|
#: apps/activity/models.py:178 apps/note/apps.py:14
|
||||||
#: apps/note/models/notes.py:77
|
#: apps/note/models/notes.py:77 apps/sheets/models.py:135
|
||||||
msgid "note"
|
msgid "note"
|
||||||
msgstr "note"
|
msgstr "note"
|
||||||
|
|
||||||
@ -2167,6 +2170,144 @@ msgstr ""
|
|||||||
msgid "Invalidate pre-registration"
|
msgid "Invalidate pre-registration"
|
||||||
msgstr "Invalider l'inscription"
|
msgstr "Invalider l'inscription"
|
||||||
|
|
||||||
|
#: apps/sheets/apps.py:10 apps/sheets/models.py:29
|
||||||
|
msgid "note sheets"
|
||||||
|
msgstr "feuilles de notes"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:28 apps/sheets/models.py:41 apps/sheets/models.py:97
|
||||||
|
#: apps/sheets/models.py:129 apps/sheets/models.py:246
|
||||||
|
msgid "note sheet"
|
||||||
|
msgstr "feuille de note"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:35 apps/sheets/models.py:61 apps/sheets/models.py:62
|
||||||
|
#: apps/sheets/models.py:74 apps/sheets/models.py:188
|
||||||
|
msgid "food"
|
||||||
|
msgstr "nourriture"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:45 apps/sheets/models.py:111
|
||||||
|
msgid "price"
|
||||||
|
msgstr "prix"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:51
|
||||||
|
msgid "destination club"
|
||||||
|
msgstr "club de destination"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:56 apps/sheets/models.py:84 apps/sheets/models.py:116
|
||||||
|
msgid "available"
|
||||||
|
msgstr "disponible"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:57 apps/sheets/models.py:85 apps/sheets/models.py:117
|
||||||
|
msgid "If set to false, this option won't be offered (in case of out of stock)"
|
||||||
|
msgstr ""
|
||||||
|
"Si mis à faux, cette option ne sera pas présentée (en cas de rupture de "
|
||||||
|
"stock)"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:79
|
||||||
|
msgid "extra cost"
|
||||||
|
msgstr "surcoût"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:89
|
||||||
|
msgid "food option"
|
||||||
|
msgstr "option de nourriture"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:90
|
||||||
|
msgid "food options"
|
||||||
|
msgstr "options de nourriture"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:107
|
||||||
|
msgid "content"
|
||||||
|
msgstr "contenu"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:121 apps/sheets/models.py:162
|
||||||
|
msgid "meal"
|
||||||
|
msgstr "menu"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:122
|
||||||
|
msgid "meals"
|
||||||
|
msgstr "menus"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:139
|
||||||
|
msgid "date"
|
||||||
|
msgstr "date"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:144
|
||||||
|
msgid "gift"
|
||||||
|
msgstr "don"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:148 apps/sheets/models.py:156
|
||||||
|
#: apps/sheets/models.py:174
|
||||||
|
msgid "order"
|
||||||
|
msgstr "commande"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:149
|
||||||
|
msgid "orders"
|
||||||
|
msgstr "commandes"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:166 apps/sheets/models.py:182
|
||||||
|
msgid "ordered meal"
|
||||||
|
msgstr "menu commandé"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:167
|
||||||
|
msgid "ordered meals"
|
||||||
|
msgstr "menus commandés"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:194
|
||||||
|
msgid "options"
|
||||||
|
msgstr "options"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:200
|
||||||
|
msgid "remark"
|
||||||
|
msgstr "remarques"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:207
|
||||||
|
msgid "priority request"
|
||||||
|
msgstr "demande de priorité"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:211
|
||||||
|
msgid "number"
|
||||||
|
msgstr "numéro"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:212
|
||||||
|
msgid "How many times the user ordered this."
|
||||||
|
msgstr "Combien de fois cet⋅te utilisateur⋅rice a commandé ceci."
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:218
|
||||||
|
msgid "queued"
|
||||||
|
msgstr "en attente"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:219
|
||||||
|
msgid "ready"
|
||||||
|
msgstr "prêt"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:220
|
||||||
|
msgid "served"
|
||||||
|
msgstr "servi"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:221
|
||||||
|
msgid "canceled"
|
||||||
|
msgstr "annulé"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:223
|
||||||
|
msgid "status"
|
||||||
|
msgstr "statut"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:229
|
||||||
|
msgid "served date"
|
||||||
|
msgstr "date de service"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:233 apps/sheets/models.py:234
|
||||||
|
#: apps/sheets/models.py:241
|
||||||
|
msgid "ordered food"
|
||||||
|
msgstr "nourriture commandée"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:259
|
||||||
|
msgid "sheet order transaction"
|
||||||
|
msgstr "transaction de commande sur feuille de note"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:260
|
||||||
|
msgid "sheet order transactions"
|
||||||
|
msgstr "transactions de commande sur feuille de note"
|
||||||
|
|
||||||
#: apps/treasury/apps.py:12 note_kfet/templates/base.html:96
|
#: apps/treasury/apps.py:12 note_kfet/templates/base.html:96
|
||||||
msgid "Treasury"
|
msgid "Treasury"
|
||||||
msgstr "Trésorerie"
|
msgstr "Trésorerie"
|
||||||
@ -3185,19 +3326,19 @@ msgstr "Répartir les 1A dans les bus"
|
|||||||
msgid "Attribute bus"
|
msgid "Attribute bus"
|
||||||
msgstr "Attribuer un bus"
|
msgstr "Attribuer un bus"
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:172
|
#: note_kfet/settings/base.py:173
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr "Allemand"
|
msgstr "Allemand"
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:173
|
#: note_kfet/settings/base.py:174
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr "Anglais"
|
msgstr "Anglais"
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:174
|
#: note_kfet/settings/base.py:175
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr "Espagnol"
|
msgstr "Espagnol"
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:175
|
#: note_kfet/settings/base.py:176
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr "Français"
|
msgstr "Français"
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ INSTALLED_APPS = [
|
|||||||
'permission',
|
'permission',
|
||||||
'registration',
|
'registration',
|
||||||
'scripts',
|
'scripts',
|
||||||
|
'sheets',
|
||||||
'treasury',
|
'treasury',
|
||||||
'wei',
|
'wei',
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user