toulouse-maelis: make payInvoices call asynchronous (#76394)
gitea/passerelle/pipeline/head This commit looks good
Details
gitea/passerelle/pipeline/head This commit looks good
Details
This commit is contained in:
parent
324b787f33
commit
29f4774d2b
|
@ -26,7 +26,7 @@ from urllib.parse import urljoin
|
||||||
import zeep
|
import zeep
|
||||||
from dateutil import rrule
|
from dateutil import rrule
|
||||||
from django.core.serializers.json import DjangoJSONEncoder
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
from django.db import models
|
from django.db import models, transaction
|
||||||
from django.db.models import JSONField
|
from django.db.models import JSONField
|
||||||
from django.http import Http404, HttpResponse
|
from django.http import Http404, HttpResponse
|
||||||
from django.utils import dateformat
|
from django.utils import dateformat
|
||||||
|
@ -278,6 +278,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
|
||||||
else:
|
else:
|
||||||
self.logger.info('Réferentiels mis à jour.')
|
self.logger.info('Réferentiels mis à jour.')
|
||||||
|
|
||||||
|
def notify_invoices_paid(self):
|
||||||
|
invoices = self.invoice_set.filter(
|
||||||
|
maelis_notification_date__isnull=True,
|
||||||
|
lingo_notification_date__lt=now() - datetime.timedelta(minutes=15),
|
||||||
|
)
|
||||||
|
for invoice in invoices:
|
||||||
|
invoice.notify()
|
||||||
|
|
||||||
|
def hourly(self):
|
||||||
|
self.notify_invoices_paid()
|
||||||
|
|
||||||
def get_referential(self, referential_name, id=None, q=None, limit=None, distinct=True):
|
def get_referential(self, referential_name, id=None, q=None, limit=None, distinct=True):
|
||||||
if id is not None:
|
if id is not None:
|
||||||
queryset = self.referential.filter(referential_name=referential_name, item_id=id)
|
queryset = self.referential.filter(referential_name=referential_name, item_id=id)
|
||||||
|
@ -3978,21 +3989,26 @@ class ToulouseMaelis(BaseResource, HTTPResource):
|
||||||
)
|
)
|
||||||
def pay_invoice(self, request, regie_id, invoice_id, post_data, **kwargs):
|
def pay_invoice(self, request, regie_id, invoice_id, post_data, **kwargs):
|
||||||
invoice = self.get_invoice(regie_id, invoice_id)
|
invoice = self.get_invoice(regie_id, invoice_id)
|
||||||
|
if invoice.status() != 'created':
|
||||||
|
raise APIError('Invoice already paid')
|
||||||
|
|
||||||
result = self.call(
|
invoice.lingo_data = post_data
|
||||||
'Invoice',
|
invoice.lingo_notification_date = now()
|
||||||
'payInvoices',
|
invoice.save(update_fields=['updated', 'lingo_notification_date', 'lingo_data'])
|
||||||
numDossier=invoice.family_id,
|
self.add_job(
|
||||||
codeRegie=regie_id,
|
'notify_invoice_paid_job',
|
||||||
amount=str(
|
regie_id=regie_id,
|
||||||
Decimal(invoice.maelis_data['amountInvoice']) - Decimal(invoice.maelis_data['amountPaid'])
|
invoice_id=invoice.invoice_id,
|
||||||
),
|
natural_id='%s/%s' % (regie_id, invoice.invoice_id),
|
||||||
datePaiement=post_data['transaction_date'],
|
|
||||||
refTransaction=post_data['transaction_id'],
|
|
||||||
numInvoices=[invoice.invoice_id],
|
|
||||||
numPerson=invoice.maelis_data['payer']['num'],
|
|
||||||
)
|
)
|
||||||
return {'data': result}
|
return {'data': 'ok'}
|
||||||
|
|
||||||
|
def notify_invoice_paid_job(self, regie_id, invoice_id):
|
||||||
|
try:
|
||||||
|
invoice = self.invoice_set.get(regie_id=regie_id, invoice_id=invoice_id)
|
||||||
|
except Invoice.DoesNotExist:
|
||||||
|
return
|
||||||
|
invoice.notify()
|
||||||
|
|
||||||
@endpoint(
|
@endpoint(
|
||||||
display_category='Facture',
|
display_category='Facture',
|
||||||
|
@ -4125,6 +4141,32 @@ class Invoice(models.Model):
|
||||||
invoice.update({'pay_limit_date': '', 'online_payment': False})
|
invoice.update({'pay_limit_date': '', 'online_payment': False})
|
||||||
return invoice
|
return invoice
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def notify(self):
|
||||||
|
obj = Invoice.objects.select_for_update().get(pk=self.pk)
|
||||||
|
if obj.maelis_notification_date is not None:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
result = obj.resource.call(
|
||||||
|
'Invoice',
|
||||||
|
'payInvoices',
|
||||||
|
numDossier=obj.family_id,
|
||||||
|
codeRegie=obj.regie_id,
|
||||||
|
amount=str(
|
||||||
|
Decimal(obj.maelis_data['amountInvoice']) - Decimal(obj.maelis_data['amountPaid'])
|
||||||
|
),
|
||||||
|
datePaiement=obj.lingo_data['transaction_date'],
|
||||||
|
refTransaction=obj.lingo_data['transaction_id'],
|
||||||
|
numInvoices=[obj.invoice_id],
|
||||||
|
numPerson=obj.maelis_data['payer']['num'],
|
||||||
|
)
|
||||||
|
except SOAPServiceUnreachable:
|
||||||
|
return False
|
||||||
|
obj.maelis_notification_date = now()
|
||||||
|
obj.maelis_notification_data = result
|
||||||
|
obj.save()
|
||||||
|
return True
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('resource', 'regie_id', 'invoice_id')
|
ordering = ('resource', 'regie_id', 'invoice_id')
|
||||||
unique_together = [['resource', 'regie_id', 'invoice_id']]
|
unique_together = [['resource', 'regie_id', 'invoice_id']]
|
||||||
|
|
|
@ -28,6 +28,7 @@ from zeep import Settings
|
||||||
from zeep.helpers import serialize_object
|
from zeep.helpers import serialize_object
|
||||||
|
|
||||||
from passerelle.apps.base_adresse.models import BaseAdresse, CityModel
|
from passerelle.apps.base_adresse.models import BaseAdresse, CityModel
|
||||||
|
from passerelle.base.models import Job
|
||||||
from passerelle.contrib.toulouse_maelis.models import Link, Referential, ToulouseMaelis
|
from passerelle.contrib.toulouse_maelis.models import Link, Referential, ToulouseMaelis
|
||||||
from passerelle.contrib.toulouse_maelis.utils import get_public_criterias
|
from passerelle.contrib.toulouse_maelis.utils import get_public_criterias
|
||||||
from passerelle.utils.jsonresponse import APIError
|
from passerelle.utils.jsonresponse import APIError
|
||||||
|
@ -9021,6 +9022,9 @@ def test_invoices_history(invoice_service, con, app):
|
||||||
'reference_id': '8',
|
'reference_id': '8',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
invoice = con.invoice_set.get(regie_id=104, invoice_id=8)
|
||||||
|
assert invoice.status() == 'notified'
|
||||||
|
|
||||||
|
|
||||||
def test_invoices_history_not_linked_error(con, app):
|
def test_invoices_history_not_linked_error(con, app):
|
||||||
url = get_endpoint('regie/104/invoices/history')
|
url = get_endpoint('regie/104/invoices/history')
|
||||||
|
@ -9074,7 +9078,41 @@ def test_invoice_not_found_invoice(invoice_service, con, app):
|
||||||
assert resp.json['err_desc'] == 'Invoice not found'
|
assert resp.json['err_desc'] == 'Invoice not found'
|
||||||
|
|
||||||
|
|
||||||
def test_pay_invoice(invoice_service, con, app):
|
def test_pay_invoice(invoice_service, con, app, freezer):
|
||||||
|
invoice_service.add_soap_response('readInvoices', get_xml_file('R_read_invoices.xml'))
|
||||||
|
|
||||||
|
resp = app.get(get_endpoint('regie/104/invoice/1312-30') + '?family_id=1312')
|
||||||
|
assert resp.json['err'] == 0
|
||||||
|
assert resp.json['data']['amount_paid'] == '0'
|
||||||
|
assert resp.json['data']['paid'] is False
|
||||||
|
assert resp.json['data']['amount'] == '162.3'
|
||||||
|
assert resp.json['data']['online_payment'] is True
|
||||||
|
assert resp.json['data']['pay_limit_date'] == '2023-04-30'
|
||||||
|
|
||||||
|
url = get_endpoint('regie/104/invoice/1312-30/pay/')
|
||||||
|
data = {
|
||||||
|
'transaction_date': '2023-03-03T18:38:00',
|
||||||
|
'transaction_id': 'xxx',
|
||||||
|
}
|
||||||
|
|
||||||
|
freezer.move_to('2023-03-03 18:39:00')
|
||||||
|
resp = app.post_json(url + '?NameID=ignored', params=data)
|
||||||
|
assert resp.json['err'] == 0
|
||||||
|
invoice = con.invoice_set.get(regie_id=104, invoice_id=30)
|
||||||
|
assert invoice.lingo_notification_date.strftime('%Y-%m-%d %H:%M:%S') == '2023-03-03 18:39:00'
|
||||||
|
assert invoice.maelis_notification_date is None
|
||||||
|
assert invoice.status() == 'paid'
|
||||||
|
|
||||||
|
resp = app.get(get_endpoint('regie/104/invoice/1312-30') + '?family_id=1312')
|
||||||
|
assert resp.json['err'] == 0
|
||||||
|
assert resp.json['data']['amount_paid'] == '162.3'
|
||||||
|
assert resp.json['data']['paid'] is True
|
||||||
|
assert resp.json['data']['amount'] == '0.0'
|
||||||
|
assert resp.json['data']['online_payment'] is False
|
||||||
|
assert resp.json['data']['pay_limit_date'] == ''
|
||||||
|
|
||||||
|
|
||||||
|
def test_pay_invoice_job(invoice_service, con, app, freezer):
|
||||||
def request_check(request):
|
def request_check(request):
|
||||||
assert dict(serialize_object(request)) == {
|
assert dict(serialize_object(request)) == {
|
||||||
'numDossier': 1312,
|
'numDossier': 1312,
|
||||||
|
@ -9092,15 +9130,82 @@ def test_pay_invoice(invoice_service, con, app):
|
||||||
invoice_service.add_soap_response(
|
invoice_service.add_soap_response(
|
||||||
'payInvoices', get_xml_file('R_pay_invoices.xml'), request_check=request_check
|
'payInvoices', get_xml_file('R_pay_invoices.xml'), request_check=request_check
|
||||||
)
|
)
|
||||||
|
|
||||||
url = get_endpoint('regie/104/invoice/1312-30/pay/')
|
url = get_endpoint('regie/104/invoice/1312-30/pay/')
|
||||||
data = {
|
data = {
|
||||||
'transaction_date': '2023-03-03T18:38:00',
|
'transaction_date': '2023-03-03T18:38:00',
|
||||||
'transaction_id': 'xxx',
|
'transaction_id': 'xxx',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
freezer.move_to('2023-03-03 18:39:00')
|
||||||
resp = app.post_json(url + '?NameID=ignored', params=data)
|
resp = app.post_json(url + '?NameID=ignored', params=data)
|
||||||
assert resp.json['err'] == 0
|
assert resp.json['err'] == 0
|
||||||
assert resp.json['data'] == 4
|
invoice = con.invoice_set.get(regie_id=104, invoice_id=30)
|
||||||
|
assert invoice.lingo_notification_date.strftime('%Y-%m-%d %H:%M:%S') == '2023-03-03 18:39:00'
|
||||||
|
assert invoice.maelis_notification_date is None
|
||||||
|
assert invoice.maelis_notification_data is None
|
||||||
|
assert invoice.status() == 'paid'
|
||||||
|
job = Job.objects.get(method_name='notify_invoice_paid_job', natural_id='104/30')
|
||||||
|
assert job.status == 'registered'
|
||||||
|
|
||||||
|
freezer.move_to('2023-03-03 18:40:00')
|
||||||
|
con.jobs()
|
||||||
|
invoice = con.invoice_set.get(regie_id=104, invoice_id=30)
|
||||||
|
assert invoice.maelis_notification_date.strftime('%Y-%m-%d %H:%M:%S') == '2023-03-03 18:40:00'
|
||||||
|
assert invoice.maelis_notification_data == 4
|
||||||
|
assert invoice.status() == 'notified'
|
||||||
|
job = Job.objects.get(method_name='notify_invoice_paid_job', natural_id='104/30')
|
||||||
|
assert job.status == 'completed'
|
||||||
|
assert job.update_timestamp > job.creation_timestamp
|
||||||
|
|
||||||
|
|
||||||
|
def test_pay_invoice_cron(invoice_service, con, app, freezer):
|
||||||
|
def request_check(request):
|
||||||
|
assert dict(serialize_object(request)) == {
|
||||||
|
'numDossier': 1312,
|
||||||
|
'numPerson': 261483,
|
||||||
|
'lastName': None,
|
||||||
|
'firstName': None,
|
||||||
|
'codeRegie': 104,
|
||||||
|
'amount': 162.3,
|
||||||
|
'datePaiement': datetime.datetime(2023, 3, 3, 18, 38),
|
||||||
|
'refTransaction': 'xxx',
|
||||||
|
'numInvoices': [30],
|
||||||
|
}
|
||||||
|
|
||||||
|
invoice_service.add_soap_response('readInvoices', get_xml_file('R_read_invoices.xml'))
|
||||||
|
invoice_service.add_soap_response(
|
||||||
|
'payInvoices', get_xml_file('R_pay_invoices.xml'), request_check=request_check
|
||||||
|
)
|
||||||
|
|
||||||
|
url = get_endpoint('regie/104/invoice/1312-30/pay/')
|
||||||
|
data = {
|
||||||
|
'transaction_date': '2023-03-03T18:38:00',
|
||||||
|
'transaction_id': 'xxx',
|
||||||
|
}
|
||||||
|
|
||||||
|
freezer.move_to('2023-03-03 18:39:00')
|
||||||
|
resp = app.post_json(url + '?NameID=ignored', params=data)
|
||||||
|
assert resp.json['err'] == 0
|
||||||
|
invoice = con.invoice_set.get(regie_id=104, invoice_id=30)
|
||||||
|
assert invoice.lingo_notification_date.strftime('%Y-%m-%d %H:%M:%S') == '2023-03-03 18:39:00'
|
||||||
|
assert invoice.maelis_notification_date is None
|
||||||
|
assert invoice.maelis_notification_data is None
|
||||||
|
assert invoice.status() == 'paid'
|
||||||
|
|
||||||
|
freezer.move_to('2023-03-03 18:40:00')
|
||||||
|
con.notify_invoices_paid()
|
||||||
|
invoice = con.invoice_set.get(regie_id=104, invoice_id=30)
|
||||||
|
assert invoice.maelis_notification_date is None
|
||||||
|
assert invoice.maelis_notification_data is None
|
||||||
|
assert invoice.status() == 'paid'
|
||||||
|
|
||||||
|
freezer.move_to('2023-03-03 18:55:00')
|
||||||
|
con.notify_invoices_paid()
|
||||||
|
invoice = con.invoice_set.get(regie_id=104, invoice_id=30)
|
||||||
|
assert invoice.maelis_notification_date.strftime('%Y-%m-%d %H:%M:%S') == '2023-03-03 18:55:00'
|
||||||
|
assert invoice.maelis_notification_data == 4
|
||||||
|
assert invoice.status() == 'notified'
|
||||||
|
|
||||||
|
|
||||||
def test_pay_invoice_wrong_referential_key_error(con, app):
|
def test_pay_invoice_wrong_referential_key_error(con, app):
|
||||||
|
@ -9129,6 +9234,19 @@ def test_pay_invoice_not_found_invoice(invoice_service, con, app):
|
||||||
assert resp.json['err_desc'] == 'Invoice not found'
|
assert resp.json['err_desc'] == 'Invoice not found'
|
||||||
|
|
||||||
|
|
||||||
|
def test_pay_historical_invoice(invoice_service, con, app):
|
||||||
|
invoice_service.add_soap_response('readInvoices', get_xml_file('R_read_invoices.xml'))
|
||||||
|
url = get_endpoint('regie/104/invoice/1312-8/pay/')
|
||||||
|
data = {
|
||||||
|
'transaction_date': '2023-03-03T18:38:00',
|
||||||
|
'transaction_id': 'xxx',
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = app.post_json(url + '?NameID=ignored', params=data)
|
||||||
|
assert resp.json['err'] == 1
|
||||||
|
assert resp.json['err_desc'] == 'Invoice already paid'
|
||||||
|
|
||||||
|
|
||||||
def test_invoice_pdf(invoice_service, con, app):
|
def test_invoice_pdf(invoice_service, con, app):
|
||||||
def request_check(request):
|
def request_check(request):
|
||||||
assert request.codeRegie == 104
|
assert request.codeRegie == 104
|
||||||
|
|
Loading…
Reference in New Issue