diff --git a/cotisations/admin.py b/cotisations/admin.py index afe4621c..4b47ccc8 100644 --- a/cotisations/admin.py +++ b/cotisations/admin.py @@ -30,7 +30,7 @@ from django.contrib import admin from reversion.admin import VersionAdmin from .models import Facture, Article, Banque, Paiement, Cotisation, Vente -from .models import CustomInvoice +from .models import CustomInvoice, CostEstimate class FactureAdmin(VersionAdmin): @@ -38,6 +38,11 @@ class FactureAdmin(VersionAdmin): pass +class CostEstimateAdmin(VersionAdmin): + """Admin class for cost estimates.""" + pass + + class CustomInvoiceAdmin(VersionAdmin): """Admin class for custom invoices.""" pass @@ -76,3 +81,4 @@ admin.site.register(Paiement, PaiementAdmin) admin.site.register(Vente, VenteAdmin) admin.site.register(Cotisation, CotisationAdmin) admin.site.register(CustomInvoice, CustomInvoiceAdmin) +admin.site.register(CostEstimate, CostEstimateAdmin) diff --git a/cotisations/forms.py b/cotisations/forms.py index 56e90c58..57bd7355 100644 --- a/cotisations/forms.py +++ b/cotisations/forms.py @@ -46,7 +46,10 @@ from django.shortcuts import get_object_or_404 from re2o.field_permissions import FieldPermissionFormMixin from re2o.mixins import FormRevMixin -from .models import Article, Paiement, Facture, Banque, CustomInvoice, Vente +from .models import ( + Article, Paiement, Facture, Banque, + CustomInvoice, Vente, CostEstimate +) from .payment_methods import balance @@ -153,6 +156,15 @@ class CustomInvoiceForm(FormRevMixin, ModelForm): fields = '__all__' +class CostEstimateForm(FormRevMixin, ModelForm): + """ + Form used to create a cost estimate. + """ + class Meta: + model = CostEstimate + exclude = ['paid', 'final_invoice'] + + class ArticleForm(FormRevMixin, ModelForm): """ Form used to create an article. diff --git a/cotisations/migrations/0037_costestimate.py b/cotisations/migrations/0037_costestimate.py new file mode 100644 index 00000000..3d97f3f3 --- /dev/null +++ b/cotisations/migrations/0037_costestimate.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-12-29 21:03 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('cotisations', '0036_custominvoice_remark'), + ] + + operations = [ + migrations.CreateModel( + name='CostEstimate', + fields=[ + ('custominvoice_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='cotisations.CustomInvoice')), + ('validity', models.DurationField(verbose_name='Period of validity')), + ('final_invoice', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='origin_cost_estimate', to='cotisations.CustomInvoice')), + ], + options={ + 'permissions': (('view_costestimate', 'Can view a cost estimate object'),), + }, + bases=('cotisations.custominvoice',), + ), + ] diff --git a/cotisations/migrations/0038_auto_20181231_1657.py b/cotisations/migrations/0038_auto_20181231_1657.py new file mode 100644 index 00000000..a9415bf0 --- /dev/null +++ b/cotisations/migrations/0038_auto_20181231_1657.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-12-31 22:57 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('cotisations', '0037_costestimate'), + ] + + operations = [ + migrations.AlterField( + model_name='costestimate', + name='final_invoice', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='origin_cost_estimate', to='cotisations.CustomInvoice'), + ), + migrations.AlterField( + model_name='costestimate', + name='validity', + field=models.DurationField(help_text='DD HH:MM:SS', verbose_name='Period of validity'), + ), + migrations.AlterField( + model_name='custominvoice', + name='paid', + field=models.BooleanField(default=False, verbose_name='Paid'), + ), + ] diff --git a/cotisations/models.py b/cotisations/models.py index 979b444a..623db068 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -284,7 +284,8 @@ class CustomInvoice(BaseInvoice): verbose_name=_("Address") ) paid = models.BooleanField( - verbose_name=_("Paid") + verbose_name=_("Paid"), + default=False ) remark = models.TextField( verbose_name=_("Remark"), @@ -293,6 +294,57 @@ class CustomInvoice(BaseInvoice): ) +class CostEstimate(CustomInvoice): + class Meta: + permissions = ( + ('view_costestimate', _("Can view a cost estimate object")), + ) + validity = models.DurationField( + verbose_name=_("Period of validity"), + help_text="DD HH:MM:SS" + ) + final_invoice = models.ForeignKey( + CustomInvoice, + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name="origin_cost_estimate", + primary_key=False + ) + + def create_invoice(self): + """Create a CustomInvoice from the CostEstimate.""" + if self.final_invoice is not None: + return self.final_invoice + invoice = CustomInvoice() + invoice.recipient = self.recipient + invoice.payment = self.payment + invoice.address = self.address + invoice.paid = False + invoice.remark = self.remark + invoice.date = timezone.now() + invoice.save() + self.final_invoice = invoice + self.save() + for sale in self.vente_set.all(): + Vente.objects.create( + facture=invoice, + name=sale.name, + prix=sale.prix, + number=sale.number, + ) + return invoice + + def can_delete(self, user_request, *args, **kwargs): + if not user_request.has_perm('cotisations.delete_costestimate'): + return False, _("You don't have the right " + "to delete a cost estimate.") + if self.final_invoice is not None: + return False, _("The cost estimate has an " + "invoice and cannot be deleted.") + return True, None + + # TODO : change Vente to Purchase class Vente(RevMixin, AclMixin, models.Model): """ diff --git a/cotisations/templates/cotisations/aff_cost_estimate.html b/cotisations/templates/cotisations/aff_cost_estimate.html new file mode 100644 index 00000000..d4a3f60d --- /dev/null +++ b/cotisations/templates/cotisations/aff_cost_estimate.html @@ -0,0 +1,101 @@ +{% comment %} +Re2o est un logiciel d'administration développé initiallement au rezometz. Il +se veut agnostique au réseau considéré, de manière à être installable en +quelques clics. + +Copyright © 2018 Hugo Levy-Falk + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +{% endcomment %} +{% load i18n %} +{% load acl %} +{% load logs_extra %} +{% load design %} + +
+ {% trans "Recipient" as tr_recip %} + {% include 'buttons/sort.html' with prefix='invoice' col='user' text=tr_user %} + | +{% trans "Designation" %} | +{% trans "Total price" %} | ++ {% trans "Payment method" as tr_payment_method %} + {% include 'buttons/sort.html' with prefix='invoice' col='payement' text=tr_payment_method %} + | ++ {% trans "Date" as tr_date %} + {% include 'buttons/sort.html' with prefix='invoice' col='date' text=tr_date %} + | ++ {% trans "Validity" as tr_validity %} + {% include 'buttons/sort.html' with prefix='invoice' col='validity' text=tr_validity %} + | ++ {% trans "Cost estimate ID" as tr_estimate_id %} + {% include 'buttons/sort.html' with prefix='invoice' col='id' text=tr_estimate_id %} + | ++ {% trans "Invoice created" as tr_invoice_created%} + {% include 'buttons/sort.html' with prefix='invoice' col='paid' text=tr_invoice_created %} + | ++ | + |
---|---|---|---|---|---|---|---|---|---|
{{ estimate.recipient }} | +{{ estimate.name }} | +{{ estimate.prix_total }} | +{{ estimate.payment }} | +{{ estimate.date }} | +{{ estimate.validity }} | +{{ estimate.id }} | ++ {% if estimate.final_invoice %} + + {% else %} + ' + {% endif %} + | ++ {% can_edit estimate %} + {% include 'buttons/edit.html' with href='cotisations:edit-cost-estimate' id=estimate.id %} + {% acl_end %} + {% history_button estimate %} + {% include 'buttons/suppr.html' with href='cotisations:del-cost-estimate' id=estimate.id %} + + + + + {% trans "PDF" %} + + | +