facturation: gestion des bordereaux de remise de règlements (#88698) #177
No reviewers
Labels
No Label
No Milestone
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: entrouvert/lingo#177
Loading…
Reference in New Issue
No description provided.
Delete Branch "wip/88698-invoicing-docket"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
WIP: facturation: gestion des bordereaux de remise de règlements (#88698)to facturation: gestion des bordereaux de remise de règlements (#88698)471e9bed2e
to5ab3d65d2c
5ab3d65d2c
toa51e00205c
(Je commence à relire.)
a51e00205c
to0deb65dba2
(Je fais assez moyennement confiance à gitea pour conserver mon brouillon de relecture — qui m’a pris plusieurs heures à constituer — d’ici demain. Par peur de perdre le travail en cours je pose ici ce début de relecture, qui concerne une première relecture des six premiers commits sur les onze proposés ici. J’essaie de boucler la relecture des cinq restants demain matin.)
———
Dans 0002, un
+ Counter.get_count(regie=regie, name='bar', kind='bucket')
où je crois tu voulais direkind='docket'
:)(Ce n’est pas visible dans le diff global.)
———
Agréable surprise de relecteur en voyant quel le gros du diff de la PR est en fait 0004 qui sépare les tests dans des fichiers différents. Par acquis de conscience, et parce que c’est le gros du diff de la PR, j’ai vérifié de part et d’autre (avant et après split) que ça correspondait. C’est ok pour moi. Ça me fait d’ailleurs me remémorer que j’ai encore du travail en cours côté authentic de ce point de vue là :)
———
0005, comme indiqué dans le commentaire inline gitea, je ne comprends pas trop la réalité fonctionnelle, et quel est le besoin qui motive d’afficher ces paiements effectués hors-bordereaux en particulier.
Edit : ah ok, je comprends à la lecture des commits suivants, on expose ces paiements sans bordereaux justement pour offrir la possibilité de les rattacher à un bordereau, ok.
———
J’étais pas super calé sur l’usage des FilterSet, ça m’a permis un petit rattrapage, merci :)
@ -848,0 +867,4 @@
def __init__(self, *args, **kwargs):
self.regie = kwargs.pop('regie')
if kwargs.get('data') is None:
# set initial through data, so form is valid on page load
Je ne connaissais pas l’astuce, ok :)
Oui, je ne suis pas super fière de moi, c'est un peu moche; mais en faisant avec initial ça ne valide pas le formulaire et donc pas de résultat du filtrage.
L'idée étant d'arriver sur la page avec déjà tous les paiements non remis listés
Oui je vois, rien à redire et de toute façon je n’ai pas mieux à proposer, ok pour moi. Je marque comme résolue cette conversation.
@ -0,0 +15,4 @@
name='docket_number_format',
field=models.CharField(
default='B{regie_id:02d}-{yy}-{mm}-{number:07d}',
max_length=100,
Pas compris l’intérêt de limiter autant ce format sur le modèle de régie, lequel est a priori instancié en un nombre d’objets très limité. N’est-ce pas uniquement la longueur de l’identifiant généré à partir de ce format qu’il convient de contrôler ?
pas réfléchi plus que ça, les autres compteurs aussi ont un max_length à 100, et les formatted_number ont un max_length à 200, ce qui devrait suffire
Ok.
@ -0,0 +44,4 @@
('number', models.PositiveIntegerField(default=0)),
('formatted_number', models.CharField(max_length=200)),
('date_end', models.DateField(verbose_name='End date')),
('draft', models.BooleanField()),
Peut-être
is_draft
(pour ne pas croire à tort que ce champ est un accesseur vers les brouillons antérieurs du bordereau) ?on a draft aussi sur les campagnes, et tu ne l'as pas relevé :)
je peux changer ici si tu insistes
Non, je n’ai pas vu que c’était ainsi par ailleurs, et je relève mais n’insiste pas :)
Laissons ainsi.
@ -0,0 +56,4 @@
],
),
migrations.AddField(
model_name='payment',
Je vais voir si je capte mieux dans la suite de la relecture, mais je ne comprends pas le choix de la FK dans ce sens et pas l’inverse. L’intuition me dit que c’est le paiement l’objet principal, vers lequel le bordereau, en tant qu’objet secondaire, pointe.
Edit: Ok, je comprends mieux à la lecture de la suite de la PR.
un payment ne peut être inclus que dans un seul bordereau :)
Oui j’ai capté ça en cours de route, c’est bon pour moi.
@ -401,4 +413,1 @@
data['cashier_role'] = Group.objects.get(name=role_name)
except Group.DoesNotExists:
raise RegieImportError('Missing role: %s' % role_name)
except Group.MultipleObjectsReturned:
Ok, je ne savais pas que la définition du
Group
dedjango.contrib.auth
impose l’unicité sur le nom, top.@ -1338,0 +1355,4 @@
date_end = models.DateField(_('End date'))
draft = models.BooleanField()
payment_types = models.ManyToManyField(PaymentType)
payment_types_info = models.JSONField(blank=True, default=dict)
Note pour moi-même, aller voir à quoi ça correspond dans le code ajouté par les commits successifs.
Ok, davantage capté, à la lecture des commits successifs, à quoi sert ce JSONField.
@ -0,0 +44,4 @@
{% block sidebar %}
<aside id="sidebar">
{% if not has_draft %}
Peut-être ici un {% else %} avec un message indiquant que l’action de création d’un nouveau bordereau n’est pas disponible car il y a déjà des bordereaux à l’état de brouillons ? (Je vois déjà arriver les tickets clients “L’action « Nouveau bordereau » a disparu”).
je fais ça dans un fixup (avec une copie d'écran attaché à la PR)
Top, je te remercie.
@ -736,0 +762,4 @@
def get_queryset(self):
self.filterset = RegieDocketPaymentFilterSet(
data=self.request.GET or None,
queryset=Payment.objects.filter(regie=self.regie, docket__isnull=True, cancelled_at__isnull=True)
J’ai du mal à comprendre le besoin fonctionnel d’exposer une liste des “paiements hors bordereaux” (“payments outside dockets”). Ça correspond à quoi en réalité ?
Edit: ok, pigé dans la suite de la relecture des commits successifs de cette PR.
@ -736,0 +854,4 @@
'payment_types': request.GET.getlist('payment_type'),
'date_end': request.GET.get('date_end'),
}
if request.GET
Ça correspond à quelle disjonction, ce test
request.GET
évalué à vrai ou non, sans chercher davantage à creuser ce que ce dictionnaire contiendrait ? Ça correspond à quels cas ?À vue de nez on dirait qu’on cherche à faire dans
def get(…):
ce qu’une CreateView opérerait normalement dansdef post(…):
.effectivement, je voulais qu'au click sur le bouton "créer", s'il y a des trucs dans request.GET, qui viennent du listing des paiements non remis et du filtrage qui a été fait, et qu'il n'y a pas d'erreur, faire ce qui est fait normalement en POST. En gros, zapper la page de présentation du formulaire qu'on doit submit, pour éviter de remontrer à l'usager un formulaire qu'il a déjà renseigné sur la page de listing
Ah oui ok, je comprends mieux, merci.
(La second partie de cette première relecture)
@ -1338,0 +1362,4 @@
def __str__(self):
if self.draft:
return '%s-%s' % (_('TEMPORARY'), self.pk)
Est-ce qu’on a pas intérêt à gérer (dans un autre ticket) aussi un format de brouillon paramétrable ? Est-ce qu’on est certain que le format fixé à 'TEMPORARY-' va convenir à coup sûr ?
on numérote les factures temporaires aussi comme ça, et on ne veut pas consommer un compteur pour un draft
Ah oui il y a la gestion des compteurs aussi, c’est vrai. Ok.
@ -0,0 +32,4 @@
{% for payment_type in docket.payment_types.all %}{{ payment_type }}{% if not forloop.last %}, {% endif %}{% endfor %}
</td>
<td>
{% if docket.active_count %}<span class="meta meta-success">{{ docket.active_count }} ({% blocktrans with amount=docket.active_amount|floatformat:"2" %}{{ amount }}€{% endblocktrans %})</span>{% endif %}
Ici juste ça va afficher un chiffre suivi d’un montant en euros entre parenthèses. Niveau UI c’est les classes
meta-success
etmeta-warning
qui permettent de distinguer si on parle de paiements actifs ou de paiements annulés ?Est-ce qu’on aurait pas intérêt à préciser à chaque fois, en toutes lettres, dans lequel des deux cas on se situe, genre
2 actifs (34.34 €)
ou7 annulés (187.87 €)
?ça a été vu avec stef, il a validé en l'état; sur les campagnes aussi on a juste des nombres et une différence de couleur
on pourra toujours revenir dessus plus tard si besoin :)
Ok, très bien alors, laissons comme ça.
@ -211,0 +218,4 @@
regie_views.regie_docket_list,
name='lingo-manager-invoicing-regie-docket-list',
),
path(
Je loupe peut-être un truc mais j’ai l’impression qu’il manquerait une vue pour éditer un bordereau existant (je vois bien des vues du genre DocketAdd, DocketDelete, DocketList et DocketDetails pas mais de vue DocketEdit). C’est volontaire genre c’est un objet qu’on n’est pas censé éditer directement ainsi (seulement le type de paiement via
RegieDocketPaymentTypeEditView
), ou bien c’est un oubli ?Ah, c’est la PR suivante, #88699, top.
@ -736,0 +810,4 @@
.annotate(
active_count=Coalesce(Subquery(active_count, output_field=IntegerField()), Value(0)),
cancelled_count=Coalesce(Subquery(cancelled_count, output_field=IntegerField()), Value(0)),
active_amount=Coalesce(Subquery(active_amount, output_field=IntegerField()), Value(0)),
On écrase les centimes ici en envoyant ça dans un
IntegerField
au lieu d’un flottant, non ? (pareil pour la ligne du dessous)bien vu, merci
fixup
Top, merci.
Je vais refaire un tour un peu plus macro pour voir si j’aurais loupé un truc à la première relecture, mais a priori j’ai plus grand chose à redire (et le ack va s’ensuivre).
J’ai refait un tour un peu plus en diagonale, rien à redire. Merci pour tes réponses détaillées à mes interrogations et incompréhensions initiales. Ack.
db1df8067c
to71d6242cb3
71d6242cb3
to9602043df4