From 1c4ea1a3faea13cd88e0d70450a161a1a2e5b3c0 Mon Sep 17 00:00:00 2001 From: Laetitia Getti Date: Fri, 17 Mar 2023 16:04:09 +0100 Subject: [PATCH] =?UTF-8?q?possibilit=C3=A9=20de=20commander=201=20produit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- la_chariotte/order/__init__.py | 0 la_chariotte/order/admin.py | 7 + la_chariotte/order/apps.py | 6 + la_chariotte/order/migrations/0001_initial.py | 31 ++++ .../migrations/0002_grouped_order_name.py | 18 ++ la_chariotte/order/migrations/0003_item.py | 22 +++ .../order/migrations/0004_item_ordered_nb.py | 18 ++ ...d_nb_alter_order_grouped_order_and_more.py | 32 ++++ .../order/migrations/0006_item_ordered_nb.py | 18 ++ la_chariotte/order/migrations/__init__.py | 0 la_chariotte/order/models.py | 28 +++ .../templates/order/grouped_order_detail.html | 36 ++++ .../templates/order/grouped_order_orga.html | 34 ++++ la_chariotte/order/templates/order/index.html | 25 +++ la_chariotte/order/tests.py | 3 + la_chariotte/order/urls.py | 11 ++ la_chariotte/order/views.py | 56 ++++++ la_chariotte/readMe.md | 166 ++++++++++++++++++ la_chariotte/settings.py | 11 +- la_chariotte/urls.py | 3 +- 20 files changed, 521 insertions(+), 4 deletions(-) create mode 100644 la_chariotte/order/__init__.py create mode 100644 la_chariotte/order/admin.py create mode 100644 la_chariotte/order/apps.py create mode 100644 la_chariotte/order/migrations/0001_initial.py create mode 100644 la_chariotte/order/migrations/0002_grouped_order_name.py create mode 100644 la_chariotte/order/migrations/0003_item.py create mode 100644 la_chariotte/order/migrations/0004_item_ordered_nb.py create mode 100644 la_chariotte/order/migrations/0005_remove_item_ordered_nb_alter_order_grouped_order_and_more.py create mode 100644 la_chariotte/order/migrations/0006_item_ordered_nb.py create mode 100644 la_chariotte/order/migrations/__init__.py create mode 100644 la_chariotte/order/models.py create mode 100644 la_chariotte/order/templates/order/grouped_order_detail.html create mode 100644 la_chariotte/order/templates/order/grouped_order_orga.html create mode 100644 la_chariotte/order/templates/order/index.html create mode 100644 la_chariotte/order/tests.py create mode 100644 la_chariotte/order/urls.py create mode 100644 la_chariotte/order/views.py create mode 100644 la_chariotte/readMe.md diff --git a/la_chariotte/order/__init__.py b/la_chariotte/order/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/la_chariotte/order/admin.py b/la_chariotte/order/admin.py new file mode 100644 index 0000000..817ee91 --- /dev/null +++ b/la_chariotte/order/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin + +from .models import Grouped_order, Order, Item + +admin.site.register(Grouped_order) +admin.site.register(Order) +admin.site.register(Item) diff --git a/la_chariotte/order/apps.py b/la_chariotte/order/apps.py new file mode 100644 index 0000000..4cd66cc --- /dev/null +++ b/la_chariotte/order/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class OrderConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'la_chariotte.order' diff --git a/la_chariotte/order/migrations/0001_initial.py b/la_chariotte/order/migrations/0001_initial.py new file mode 100644 index 0000000..d72f72e --- /dev/null +++ b/la_chariotte/order/migrations/0001_initial.py @@ -0,0 +1,31 @@ +# Generated by Django 4.1.7 on 2023-03-14 15:33 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Grouped_order', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('orga', models.CharField(max_length=100)), + ('date', models.DateField(verbose_name='Date de livraison')), + ], + ), + migrations.CreateModel( + name='Order', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('author', models.CharField(max_length=100, verbose_name='Personne qui passe la commande')), + ('grouped_order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='order.grouped_order')), + ], + ), + ] diff --git a/la_chariotte/order/migrations/0002_grouped_order_name.py b/la_chariotte/order/migrations/0002_grouped_order_name.py new file mode 100644 index 0000000..87ff618 --- /dev/null +++ b/la_chariotte/order/migrations/0002_grouped_order_name.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.7 on 2023-03-14 16:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='grouped_order', + name='name', + field=models.CharField(max_length=100, null=True), + ), + ] diff --git a/la_chariotte/order/migrations/0003_item.py b/la_chariotte/order/migrations/0003_item.py new file mode 100644 index 0000000..3de7cad --- /dev/null +++ b/la_chariotte/order/migrations/0003_item.py @@ -0,0 +1,22 @@ +# Generated by Django 4.1.7 on 2023-03-15 15:24 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0002_grouped_order_name'), + ] + + operations = [ + migrations.CreateModel( + name='Item', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('grouped_order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='order.grouped_order')), + ], + ), + ] diff --git a/la_chariotte/order/migrations/0004_item_ordered_nb.py b/la_chariotte/order/migrations/0004_item_ordered_nb.py new file mode 100644 index 0000000..382f464 --- /dev/null +++ b/la_chariotte/order/migrations/0004_item_ordered_nb.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.7 on 2023-03-15 16:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0003_item'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='ordered_nb', + field=models.IntegerField(default=0), + ), + ] diff --git a/la_chariotte/order/migrations/0005_remove_item_ordered_nb_alter_order_grouped_order_and_more.py b/la_chariotte/order/migrations/0005_remove_item_ordered_nb_alter_order_grouped_order_and_more.py new file mode 100644 index 0000000..70d001d --- /dev/null +++ b/la_chariotte/order/migrations/0005_remove_item_ordered_nb_alter_order_grouped_order_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 4.1.7 on 2023-03-17 14:25 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0004_item_ordered_nb'), + ] + + operations = [ + migrations.RemoveField( + model_name='item', + name='ordered_nb', + ), + migrations.AlterField( + model_name='order', + name='grouped_order', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='order_set', to='order.grouped_order'), + ), + migrations.CreateModel( + name='OrderedItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nb', models.PositiveSmallIntegerField(default=0)), + ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ordered_items', to='order.item')), + ('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orders', to='order.order')), + ], + ), + ] diff --git a/la_chariotte/order/migrations/0006_item_ordered_nb.py b/la_chariotte/order/migrations/0006_item_ordered_nb.py new file mode 100644 index 0000000..6989454 --- /dev/null +++ b/la_chariotte/order/migrations/0006_item_ordered_nb.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.7 on 2023-03-17 14:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0005_remove_item_ordered_nb_alter_order_grouped_order_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='ordered_nb', + field=models.IntegerField(default=0), + ), + ] diff --git a/la_chariotte/order/migrations/__init__.py b/la_chariotte/order/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/la_chariotte/order/models.py b/la_chariotte/order/models.py new file mode 100644 index 0000000..7714ad6 --- /dev/null +++ b/la_chariotte/order/models.py @@ -0,0 +1,28 @@ +from django.db import models + +class Grouped_order(models.Model): + name = models.CharField(max_length=100, null=True) # optionnal + orga = models.CharField(max_length=100) # a changer, utiliser ForeignKey de user + date = models.DateField('Date de livraison') + def __str__(self): + return self.name if self.name else f"Commande groupée {self.pk} du {self.date} organisée par {self.orga}" + +class Order(models.Model): + grouped_order = models.ForeignKey(Grouped_order, on_delete=models.CASCADE,related_name="order_set") + author = models.CharField(max_length=100, verbose_name='Personne qui passe la commande') # a changer, utiliser ForeignKey de user + def __str__(self): + return f"Commande de {self.author} pour la commande groupée {self.grouped_order.pk}" + +class Item(models.Model): + name = models.CharField(max_length=100) + grouped_order = models.ForeignKey(Grouped_order, on_delete=models.CASCADE) # à transformer en manytomany quand il y aura un catalogue + ordered_nb = models.IntegerField(default=0) + + def __str__(self): + return f"{self.name} dans la commande groupée {self.grouped_order.pk}" + +class OrderedItem(models.Model): + """Item in one specific Order, and its number""" + nb = models.PositiveSmallIntegerField(default=0) # works up to 32767 + order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="ordered_items") + item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name="orders") diff --git a/la_chariotte/order/templates/order/grouped_order_detail.html b/la_chariotte/order/templates/order/grouped_order_detail.html new file mode 100644 index 0000000..db14d26 --- /dev/null +++ b/la_chariotte/order/templates/order/grouped_order_detail.html @@ -0,0 +1,36 @@ + + + + + Commandes groupées {{ grouped_order.id }} + + +

Détail de la commande groupée {{ grouped_order.id }}, avec la liste des produits associés

+
+

{{ grouped_order }} +

Organisateur·ice : {{ grouped_order.orga }}

+

Date de livraison : {{ grouped_order.date }}

+ + les produits disponibles pour cette commande groupée : + + +
+ {% csrf_token %} +
+

{{ grouped_order }}

+ {% if error_message %}

{{ error_message }}

{% endif %} + {% for item in grouped_order.item_set.all %} + +
+ {% endfor %} +
+ +
+ + diff --git a/la_chariotte/order/templates/order/grouped_order_orga.html b/la_chariotte/order/templates/order/grouped_order_orga.html new file mode 100644 index 0000000..636891a --- /dev/null +++ b/la_chariotte/order/templates/order/grouped_order_orga.html @@ -0,0 +1,34 @@ + + + + + Commandes groupées {{ grouped_order.id }} + + +

Vue d'organisation de la commande groupée {{ grouped_order.id }}, avec les produits commandés et les commandes individuelles

+
+

{{ grouped_order }} +

Organisateur·ice : {{ grouped_order.orga }}

+

Date de livraison : {{ grouped_order.date }}

+ + les produits commandés pour cette commande groupée : + + + les commandes passées pour cette commande groupée : + + + Retour à la page de commande + + diff --git a/la_chariotte/order/templates/order/index.html b/la_chariotte/order/templates/order/index.html new file mode 100644 index 0000000..433e46a --- /dev/null +++ b/la_chariotte/order/templates/order/index.html @@ -0,0 +1,25 @@ + + + + + Commandes groupées - index + + +

Index des commandes que l'utilisateur·ice connecté·e organise

+

Pour l'instant, index de toutes les commandes groupées qui existent

+ + {% if grouped_order_list %} + + {% else %} +

Pas de commande groupée pour l'instant

+ {% endif %} + + diff --git a/la_chariotte/order/tests.py b/la_chariotte/order/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/la_chariotte/order/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/la_chariotte/order/urls.py b/la_chariotte/order/urls.py new file mode 100644 index 0000000..74c6383 --- /dev/null +++ b/la_chariotte/order/urls.py @@ -0,0 +1,11 @@ +from django.urls import path + +from . import views + +app_name = 'order' +urlpatterns = [ + path('', views.IndexView.as_view(), name='index'), + path('/', views.GroupedOrderDetailView.as_view(), name='grouped_order_detail'), + path('/orga', views.GroupedOrderOrgaView.as_view(), name='grouped_order_orga'), + path('/commander/', views.order, name='order'), +] \ No newline at end of file diff --git a/la_chariotte/order/views.py b/la_chariotte/order/views.py new file mode 100644 index 0000000..9c90b4b --- /dev/null +++ b/la_chariotte/order/views.py @@ -0,0 +1,56 @@ +from django.shortcuts import render, get_object_or_404, get_list_or_404 +from django.http import HttpResponse, Http404, HttpResponseRedirect +from django.urls import reverse +from django.views import generic + +from .models import Grouped_order, Item, Order, OrderedItem + + +class IndexView(generic.ListView): + """Vue de toutes les commandes groupées existantes - plus tard, de toutes les commandes groupées de l'utilisateur connecté""" + template_name = 'order/index.html' + context_object_name = 'grouped_order_list' + + def get_queryset(self): + """Return some 10 grouped orders.""" # changer envoyer les plus proches d'aujourd'hui dans le futur + return Grouped_order.objects.order_by('-date')[:10] + + +class GroupedOrderDetailView(generic.DetailView): + """Vue de détail d'une commande groupée - possibilité de commander si elle est en cours""" + model = Grouped_order + template_name = 'order/grouped_order_detail.html' + + +class GroupedOrderOrgaView(generic.DetailView): + """Vue de supervision d'une commande groupée""" + model = Grouped_order + template_name = 'order/grouped_order_orga.html' + + +def order(request, grouped_order_id): # crée une commande (order) pour cette commande groupée, avec l'item selectionné dedans + grouped_order = get_object_or_404(Grouped_order, pk=grouped_order_id) + try: + selected_item = grouped_order.item_set.get(pk=request.POST['item']) + except (KeyError, Item.DoesNotExist): + # Redisplay the order form for this grouped order. + return render(request, 'order/grouped_order_detail.html', { + 'grouped_order': grouped_order, + 'error_message': "You didn't select an item.", + }) + else: + order = Order.objects.create(author="Auteur teur",grouped_order=grouped_order) + OrderedItem.objects.create(nb=1,order=order,item=selected_item) + compute_ordered_nb(selected_item) + # Always return an HttpResponseRedirect after successfully dealing + # with POST data. This prevents data from being posted twice if a + # user hits the Back button. + return HttpResponseRedirect(reverse('order:grouped_order_orga', args=(grouped_order.pk,))) + +def compute_ordered_nb(item): + """Calcule le nombre de produits de ce produit commandés (pour cette commande groupée)""" + ordered_nb = 0 + for order in item.orders.all(): + ordered_nb += order.nb + item.ordered_nb = ordered_nb + item.save() diff --git a/la_chariotte/readMe.md b/la_chariotte/readMe.md new file mode 100644 index 0000000..6e6799f --- /dev/null +++ b/la_chariotte/readMe.md @@ -0,0 +1,166 @@ +Exemple de MCD en markdown avec mermaid : + + +```mermaid +erDiagram +CourseSubmission{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +CharField title +DateField date +FSMField state +} +CourseSubmissionProduct{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +PositiveSmallIntegerField quantity +} +Pricing{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +CharField name +} +Product{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +CharField name +CharField code +BooleanField submission_enabled +} +ProductPrice{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +PositiveSmallIntegerField year +CharField price_type +DecimalField price_flat +PositiveSmallIntegerField price_percent +DecimalField price_percent_minimum +CharField unit +} +ProductPriceRange{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +PositiveSmallIntegerField range_start +PositiveSmallIntegerField range_end +DecimalField unit_price +DecimalField minimum +} +ProductPricePackLine_included_products{ +AutoField id +} +ProductPricePackLine{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +CharField quantity_type +PositiveSmallIntegerField quantity +} +Contract{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +DateField start +DateField end +FileField file +} +Transaction_products{ +AutoField id +} +Transaction{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +PositiveIntegerField debit +PositiveIntegerField credit +BooleanField unlimited_credit +} +Quote{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +CharField external_ref +FSMField state +} +QuoteLine{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +TextField label +DecimalField unit_price +DecimalField quantity +} +Invoice{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +CharField external_ref +FSMField state +} +InvoiceLine{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +TextField label +DecimalField unit_price +DecimalField quantity +} +User{ +CharField password +DateTimeField last_login +BooleanField is_superuser +CharField username +CharField first_name +CharField last_name +EmailField email +BooleanField is_staff +BooleanField is_active +DateTimeField date_joined +UUIDField id +DateTimeField created_on +DateTimeField updated_on +ManyToManyField groups +ManyToManyField user_permissions +} +Organization{ +UUIDField id +DateTimeField created_on +DateTimeField updated_on +CharField code +CharField representative +FileField signature +FileField logo +} +CourseSubmission||--|{User : user +CourseSubmission||--|{Organization : organization +CourseSubmissionProduct||--|{CourseSubmission : course_submission +CourseSubmissionProduct||--|{Product : product +ProductPrice||--|{Pricing : pricing +ProductPrice||--|{Product : product +ProductPriceRange||--|{ProductPrice : product_price +ProductPricePackLine_included_products||--|{ProductPricePackLine : productpricepackline +ProductPricePackLine_included_products||--|{Product : product +ProductPricePackLine||--|{ProductPrice : product_price +ProductPricePackLine}|--|{Product : included_products +Contract||--|{Organization : organization +Contract||--|{Pricing : pricing +Transaction_products||--|{Transaction : transaction +Transaction_products||--|{Product : product +Transaction||--|{Invoice : invoice +Transaction||--|{CourseSubmission : course_submission +Transaction}|--|{Product : products +Quote||--|{Organization : organization +QuoteLine||--|{Quote : quote +QuoteLine||--|{Product : product +Invoice||--|{Organization : organization +InvoiceLine||--|{Invoice : invoice +InvoiceLine||--|{Product : product +Organization||--|{User : representative_user +Organization||--|{Organization : parent + +``` diff --git a/la_chariotte/settings.py b/la_chariotte/settings.py index 68ea23d..fe657cb 100644 --- a/la_chariotte/settings.py +++ b/la_chariotte/settings.py @@ -31,6 +31,7 @@ ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ + 'la_chariotte.order', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -75,8 +76,12 @@ WSGI_APPLICATION = 'la_chariotte.wsgi.application' DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'chariotte-db', + 'USER': 'laetitia', + 'PASSWORD': 'toto', + 'HOST': '127.0.0.1', + 'PORT': '5432', } } @@ -105,7 +110,7 @@ AUTH_PASSWORD_VALIDATORS = [ LANGUAGE_CODE = 'en-us' -TIME_ZONE = 'UTC' +TIME_ZONE = 'Europe/Paris' USE_I18N = True diff --git a/la_chariotte/urls.py b/la_chariotte/urls.py index 1da3016..ebc0a7d 100644 --- a/la_chariotte/urls.py +++ b/la_chariotte/urls.py @@ -14,8 +14,9 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path +from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), + path('commande/', include('la_chariotte.order.urls')), ]