toulouse-maelis: manage online_payment without cache (#83257)
gitea/passerelle/pipeline/head Build queued...
Details
gitea/passerelle/pipeline/head Build queued...
Details
This commit is contained in:
parent
923427783c
commit
aa9585071a
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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'))
|
||||
|
|
Loading…
Reference in New Issue