eo_facture: autoriser les contrats sans clients (#74608)
gitea/barbacompta/pipeline/head This commit looks good Details

This commit is contained in:
Pierre Ducroquet 2023-02-16 16:04:44 +01:00
parent c235781e7c
commit d2b03f4a1b
6 changed files with 54 additions and 19 deletions

View File

@ -152,8 +152,11 @@ class ClientAdmin(admin.ModelAdmin):
def show_client(obj):
url = reverse('admin:eo_facture_client_change', args=[obj.client.id])
return format_html('<a href="{0}">{1}</a>', url, obj.client)
if obj.client:
url = reverse('admin:eo_facture_client_change', args=[obj.client.id])
return format_html('<a href="{0}">{1}</a>', url, obj.client)
else:
return ""
show_client.short_description = 'Client'

View File

@ -21,6 +21,7 @@ from decimal import Decimal
from django import forms
from django.contrib.admin import widgets
from django.core.exceptions import ValidationError
from django.db.models import Q
from django.db.transaction import atomic
from . import models
@ -149,7 +150,11 @@ class FactureForm(forms.ModelForm):
pass # invalid input from client; ignore and fallback to empty Contrat queryset
if client_id:
self.fields['contrat'].queryset = models.Contrat.objects.filter(client_id=client_id)
self.fields['contrat'].queryset = models.Contrat.objects.filter(
Q(client_id=client_id) | Q(client__isnull=True)
)
else:
self.fields['contrat'].queryset = models.Contrat.objects.filter(client__isnull=True)
def clean_proforma(self):
if not self.instance.proforma and 'proforma' in self.changed_data:
@ -205,6 +210,7 @@ class ContratForm(forms.ModelForm):
self.fields['periodicite_debut'].widget.attrs['data-depends-on'] = 'periodicite'
if 'periodicite_fin' in self.fields:
self.fields['periodicite_fin'].widget.attrs['data-depends-on'] = 'periodicite'
self.fields['client'].required = False
class Meta:
fields = '__all__'

View File

@ -0,0 +1,24 @@
# Generated by Django 3.2.17 on 2023-02-16 15:46
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('eo_facture', '0018_client_notes_privees'),
]
operations = [
migrations.AlterField(
model_name='contrat',
name='client',
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='contrats',
to='eo_facture.client',
),
),
]

View File

@ -126,7 +126,7 @@ def one_hundred_percent_this_year():
class Contrat(models.Model):
client = models.ForeignKey(Client, related_name="contrats", on_delete=models.CASCADE)
client = models.ForeignKey(Client, related_name="contrats", on_delete=models.CASCADE, null=True)
intitule = models.CharField(max_length=150)
description = models.TextField(blank=True)
public_description = models.TextField(
@ -230,12 +230,6 @@ class Contrat(models.Model):
montant_par_annee[today_year] += adjust
return montant_par_annee
def nom_client(self):
"""
Le nom du client qui a signé ce contrat avec EO.
"""
return self.client.nom
def clean(self):
self.numero_marche = self.numero_marche.strip()
@ -489,7 +483,7 @@ class Facture(models.Model):
if not self.intitule:
self.intitule = self.contrat.intitule
if self.client:
if self.client != self.contrat.client:
if self.client != self.contrat.client and self.contrat.client is not None:
raise ValidationError("Le client de la facture et du contrat doivent être identiques.")
else:
self.client = self.contrat.client
@ -737,11 +731,14 @@ class Ligne(models.Model):
ordering = ("order",)
def __str__(self):
return "%s pour %s %s" % (
self.intitule,
self.montant,
self.facture.client.monnaie,
)
if self.facture.client:
return "%s pour %s %s" % (
self.intitule,
self.montant,
self.facture.client.monnaie,
)
else:
return "%s pour %s" % (self.intitule, self.montant)
def encaissements_avec_solde_non_affecte():

View File

@ -3,6 +3,7 @@
{% block extrahead %}{{ block.super }}
{% if add and not original.client %}
{% if not original.contrat or original.contrat.client %}
<script type="text/javascript">
window.addEventListener("load", function(){
let client_selector = document.getElementById("id_client");
@ -18,6 +19,7 @@ window.addEventListener("load", function(){
});
</script>
{% endif %}
{% endif %}
{% endblock %}
{% block object-tools %}

View File

@ -154,9 +154,12 @@ class StringWithHref(str):
def client_and_link(c):
s = str(c)
url = reverse("admin:eo_facture_client_change", args=(c.id,))
return StringWithHref(s, url)
if c is not None:
s = str(c)
url = reverse("admin:eo_facture_client_change", args=(c.id,))
return StringWithHref(s, url)
else:
return ""
def dict_of_list():