toulouse-maelis: manage online_payment without cache (#83257)
gitea/passerelle/pipeline/head Build queued... Details

This commit is contained in:
Nicolas Roche 2023-11-09 15:55:23 +01:00 committed by Nicolas Roche
parent 923427783c
commit aa9585071a
3 changed files with 211 additions and 15 deletions

View File

@ -4046,6 +4046,7 @@ class ToulouseMaelis(BaseResource, HTTPResource):
def get_invoices(self, family_id, regie_id):
self.assert_key_in_referential('Regie', regie_id, 'regie_id parameter')
known_invoice_ids = set()
try:
result = self.call(
'Invoice',
@ -4056,12 +4057,14 @@ class ToulouseMaelis(BaseResource, HTTPResource):
dateEnd=now().strftime(utils.json_date_format),
)
except SOAPServiceUnreachable:
pass
known_invoice_ids = None
else:
for item in result:
invoice_id = item['numInvoice']
known_invoice_ids.add(invoice_id)
invoice, created = self.invoice_set.get_or_create(
regie_id=regie_id,
invoice_id=item['numInvoice'],
invoice_id=invoice_id,
defaults={
'family_id': family_id,
'maelis_data': item,
@ -4091,7 +4094,18 @@ class ToulouseMaelis(BaseResource, HTTPResource):
"Mise à jour de %s sur la famille '%s': %s", repr(invoice), family_id, diff
)
return self.invoice_set.filter(regie_id=regie_id, family_id=family_id)
qs = self.invoice_set.filter(regie_id=regie_id, family_id=family_id)
qs.known_invoice_ids = known_invoice_ids
return qs
def make_no_online_payment_reason(self, qs, invoice):
if qs.known_invoice_ids is None:
# soap service is down
return 'Le service est temporairement indisponible.'
elif invoice.invoice_id not in qs.known_invoice_ids:
return 'La facture a été annulée.'
else:
return None
@endpoint(
display_category='Facture',
@ -4107,12 +4121,14 @@ class ToulouseMaelis(BaseResource, HTTPResource):
)
def invoices(self, request, regie_id, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
invoices = [
i.format_content()
for i in self.get_invoices(family_id, regie_id)
if i.status() in ['created', 'for_payment']
]
return {'has_invoice_for_payment': True, 'data': invoices}
data = []
qs = self.get_invoices(family_id, regie_id)
for invoice in qs:
if invoice.status() not in ['created', 'for_payment']:
continue
invoice.no_online_payment_reason = self.make_no_online_payment_reason(qs, invoice)
data.append(invoice.format_content())
return {'has_invoice_for_payment': True, 'data': data}
@endpoint(
display_category='Facture',
@ -4138,10 +4154,12 @@ class ToulouseMaelis(BaseResource, HTTPResource):
def get_invoice(self, regie_id, invoice_id):
real_invoice_id = invoice_id.split('-')[-1]
family_id = invoice_id[: -(len(real_invoice_id) + 1)]
qs = self.get_invoices(family_id, regie_id)
try:
invoice = self.get_invoices(family_id, regie_id).get(invoice_id=real_invoice_id)
invoice = qs.get(invoice_id=real_invoice_id)
except Invoice.DoesNotExist:
raise APIError('Invoice not found')
invoice.no_online_payment_reason = self.make_no_online_payment_reason(qs, invoice)
return invoice
@endpoint(
@ -4168,7 +4186,7 @@ class ToulouseMaelis(BaseResource, HTTPResource):
if invoice.status() == 'cancelling':
raise APIError('Invoice cancelling')
return {
'data': invoice.format_content(),
'data': invoice.format_content(no_online_payment_reason=invoice.no_online_payment_reason),
}
@endpoint(
@ -4321,6 +4339,8 @@ class Invoice(models.Model):
basket_generation_date = models.DateTimeField(null=True)
maelis_cancel_notification_date = models.DateTimeField(null=True)
no_online_payment_reason = None
def __repr__(self):
return '<Invoice "%s/%s">' % (self.regie_id, self.invoice_id)
@ -4351,7 +4371,7 @@ class Invoice(models.Model):
# new invoice
return 'created'
def format_content(self):
def format_content(self, no_online_payment_reason=None):
item = self.maelis_data
paid = self.status() in ['paid', 'notified']
amount_paid = item['amountInvoice'] if paid else item['amountPaid']
@ -4365,15 +4385,21 @@ class Invoice(models.Model):
'amount_paid': amount_paid,
'label': item['libelleTTF'],
'has_pdf': bool(item['pdfName']),
'online_payment': True,
'online_payment': not bool(self.no_online_payment_reason),
'paid': paid,
'payment_date': None,
'no_online_payment_reason': None,
'no_online_payment_reason': self.no_online_payment_reason,
'reference_id': item['numInvoice'],
'maelis_item': item,
}
if paid or self.status() == 'for_payment':
invoice.update({'pay_limit_date': '', 'online_payment': False})
invoice.update(
{
'pay_limit_date': '',
'online_payment': False,
'no_online_payment_reason': None,
}
)
if self.status() == 'for_payment':
invoice['no_online_payment_reason'] = 'Transation de payement en cours'
return invoice

View File

@ -0,0 +1,106 @@
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:readInvoicesResponse xmlns:ns2="ws.maelis.sigec.com">
<invoiceList>
<numInvoice>8</numInvoice>
<idInvoice>F10055591232</idInvoice>
<libelleTTF>CLAE JANVIER 2023</libelleTTF>
<regie>
<code>102</code>
<libelle>CANTINE / CLAE</libelle>
</regie>
<numFamily>1312</numFamily>
<name>SIMPSON MARGE</name>
<amountInvoice>952503.6</amountInvoice>
<amountPaid>952503.6</amountPaid>
<amountPaidTG>0</amountPaidTG>
<dateInvoice>2023-02-24T00:00:00+01:00</dateInvoice>
<dateDeadline>2023-03-24T00:00:00+01:00</dateDeadline>
<payer>
<num>261483</num>
<lastname>SIMPSON</lastname>
<firstname>MARGE</firstname>
<civility>MME</civility>
</payer>
<lineInvoiceList>
<numLine>1</numLine>
<numPers>261485</numPers>
<idActivity>A10049327692</idActivity>
<idUnit>A10049327693</idUnit>
<libelleLine>Calendrier CLAE SOIR 22/23</libelleLine>
<name>SIMPSON BART</name>
<dateStart>2023-01-02T00:00:00+01:00</dateStart>
<dateEnd>2023-02-28T00:00:00+01:00</dateEnd>
<quantity>11.0</quantity>
<unitPrice>22500.0</unitPrice>
<amountLine>247500</amountLine>
</lineInvoiceList>
<lineInvoiceList>
<numLine>2</numLine>
<numPers>261488</numPers>
<idActivity>A10049327692</idActivity>
<idUnit>A10049327693</idUnit>
<libelleLine>Calendrier CLAE SOIR 22/23</libelleLine>
<name>SIMPSON LISA</name>
<dateStart>2023-01-02T00:00:00+01:00</dateStart>
<dateEnd>2023-02-28T00:00:00+01:00</dateEnd>
<quantity>6.0</quantity>
<unitPrice>22500.0</unitPrice>
<amountLine>135000</amountLine>
</lineInvoiceList>
<lineInvoiceList>
<numLine>3</numLine>
<numPers>261485</numPers>
<idActivity>A10049327689</idActivity>
<idUnit>A10049327690</idUnit>
<libelleLine>Calendrier CLAE MATIN 22/23</libelleLine>
<name>SIMPSON BART</name>
<dateStart>2023-01-02T00:00:00+01:00</dateStart>
<dateEnd>2023-02-28T00:00:00+01:00</dateEnd>
<quantity>6.0</quantity>
<unitPrice>30000.0</unitPrice>
<amountLine>180000</amountLine>
</lineInvoiceList>
<lineInvoiceList>
<numLine>4</numLine>
<numPers>261489</numPers>
<idActivity>A10049327689</idActivity>
<idUnit>A10049327690</idUnit>
<libelleLine>Calendrier CLAE MATIN 22/23</libelleLine>
<name>SIMPSON MAGGIE</name>
<dateStart>2023-01-02T00:00:00+01:00</dateStart>
<dateEnd>2023-02-28T00:00:00+01:00</dateEnd>
<quantity>8.0</quantity>
<unitPrice>30000.0</unitPrice>
<amountLine>240000</amountLine>
</lineInvoiceList>
<lineInvoiceList>
<numLine>5</numLine>
<numPers>261490</numPers>
<idActivity>A10049327689</idActivity>
<idUnit>A10049327690</idUnit>
<libelleLine>Calendrier CLAE MATIN 22/23</libelleLine>
<name>SIMPSON HUGO</name>
<dateStart>2023-01-02T00:00:00+01:00</dateStart>
<dateEnd>2023-02-28T00:00:00+01:00</dateEnd>
<quantity>5.0</quantity>
<unitPrice>30000.0</unitPrice>
<amountLine>150000</amountLine>
</lineInvoiceList>
<lineInvoiceList>
<numLine>6</numLine>
<numPers>261485</numPers>
<idActivity>A10049327686</idActivity>
<idUnit>A10049327687</idUnit>
<libelleLine>Calendrier CLAE MIDI 22/23</libelleLine>
<name>SIMPSON BART</name>
<dateStart>2023-01-02T00:00:00+01:00</dateStart>
<dateEnd>2023-02-28T00:00:00+01:00</dateEnd>
<quantity>6.0</quantity>
<unitPrice>0.6</unitPrice>
<amountLine>3.6</amountLine>
</lineInvoiceList>
</invoiceList>
</ns2:readInvoicesResponse>
</soap:Body>
</soap:Envelope>

View File

@ -10659,6 +10659,70 @@ def test_invoice(invoice_service, con, app):
assert resp.json['data']['label'] == 'CLAE JANVIER 2023'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_invoice_online_payment_no_response(mocked_post, mocked_get, con, app, db):
mocked_get.side_effect = (INVOICE_SERVICE_WSDL,)
mocked_post.side_effect = [
FakedResponse(content=get_xml_file('R_read_invoices.xml'), status_code=200),
ReadTimeout('timeout'),
ReadTimeout('timeout'),
]
url = get_endpoint('regie/102/invoice/1312-30')
# Assert we get the invoice in cache
resp = app.get(url + '?NameID=ignored')
assert resp.json['err'] == 0
assert resp.json['data']['online_payment'] is True
assert resp.json['data']['no_online_payment_reason'] is None
# Maelis is no more available
resp = app.get(url + '?NameID=ignored')
assert resp.json['err'] == 0
assert resp.json['data']['online_payment'] is False
assert resp.json['data']['no_online_payment_reason'] == 'Le service est temporairement indisponible.'
# No change on invoice already paid
url = get_endpoint('regie/102/invoice/1312-8')
resp = app.get(url + '?NameID=ignored')
assert resp.json['err'] == 0
assert resp.json['data']['online_payment'] is False
assert resp.json['data']['no_online_payment_reason'] is None
def test_invoices_online_payment_no_invoice(invoice_service, con, app, caplog, freezer):
invoice_service.add_soap_response('readInvoices', get_xml_file('R_read_invoices.xml'))
invoice_service.add_soap_response('readInvoices', get_xml_file('R_read_invoices_canceled.xml'))
invoice_service.add_soap_response('readInvoices', get_xml_file('R_read_invoices.xml'))
url = get_endpoint('regie/102/invoices') + '?NameID=local'
Link.objects.create(resource=con, family_id='1312', name_id='local')
freezer.move_to('2023-03-03 18:00:00')
resp = app.get(url)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['online_payment'] is True
assert resp.json['data'][0]['no_online_payment_reason'] is None
# Maelis do not send the "canceled by agents" invoice
freezer.move_to('2023-03-03 18:10:00')
resp = app.get(url)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['online_payment'] is False
assert resp.json['data'][0]['no_online_payment_reason'] == 'La facture a été annulée.'
# Maelis re-send the invoice
freezer.move_to('2023-03-03 18:20:00')
resp = app.get(url)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['online_payment'] is True
assert resp.json['data'][0]['no_online_payment_reason'] is None
def test_invoice_if_cancelled(activity_service, invoice_service, con, app, freezer):
activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket.xml'))
activity_service.add_soap_response('validateBasket', get_xml_file('R_validate_basket.xml'))