From 3dab63a0f3d3c33ae0acdd56d64b89ce37cf8b9f Mon Sep 17 00:00:00 2001 From: Nicolas ROCHE Date: Wed, 26 Apr 2023 20:54:36 +0200 Subject: [PATCH] toulouse-maelis: record wcs-demand with subscription ids (#76398) --- .../toulouse_maelis/activity_schemas.py | 17 ++++++ .../migrations/0012_subscription.py | 53 ++++++++++++++++++ passerelle/contrib/toulouse_maelis/models.py | 56 +++++++++++++++++++ tests/test_toulouse_maelis.py | 38 +++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 passerelle/contrib/toulouse_maelis/migrations/0012_subscription.py diff --git a/passerelle/contrib/toulouse_maelis/activity_schemas.py b/passerelle/contrib/toulouse_maelis/activity_schemas.py index 7c9bcfab..a2bcf434 100644 --- a/passerelle/contrib/toulouse_maelis/activity_schemas.py +++ b/passerelle/contrib/toulouse_maelis/activity_schemas.py @@ -179,6 +179,23 @@ SUBSCRIPTION_SCHEMA = { }, }, }, + 'form_api_url': { + 'description': "Adresse de la vue API du formulaire Publik : {{ form_api_url }}", + 'oneOf': [ + {'type': 'string'}, + {'type': 'null'}, + ], + }, + 'form_number': { + 'description': 'Numéro de la demande Publik : {{ form_number }}', + 'oneOf': [ + { + 'type': 'string', + 'pattern': '^[0-9]+-[0-9]+$', + }, + {'type': 'null'}, + ], + }, }, 'required': [ 'person_id', diff --git a/passerelle/contrib/toulouse_maelis/migrations/0012_subscription.py b/passerelle/contrib/toulouse_maelis/migrations/0012_subscription.py new file mode 100644 index 00000000..226e942a --- /dev/null +++ b/passerelle/contrib/toulouse_maelis/migrations/0012_subscription.py @@ -0,0 +1,53 @@ +# Generated by Django 3.2.18 on 2023-04-26 13:34 + +import django.core.serializers.json +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('toulouse_maelis', '0011_invoice_start_payment_date'), + ] + + operations = [ + migrations.CreateModel( + name='Subscription', + fields=[ + ( + 'id', + models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ('wcs_form_number', models.CharField(max_length=16)), + ('wcs_form_api_url', models.CharField(max_length=256)), + ('regie_id', models.CharField(max_length=128)), + ('family_id', models.CharField(max_length=128)), + ('maelis_data', models.JSONField(encoder=django.core.serializers.json.DjangoJSONEncoder)), + ('basket_removal_date', models.DateTimeField(null=True)), + ( + 'wcs_trigger_payload', + models.JSONField(encoder=django.core.serializers.json.DjangoJSONEncoder, null=True), + ), + ('wcs_trigger_response', models.JSONField(null=True)), + ('wcs_trigger_date', models.DateTimeField(null=True)), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), + ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), + ( + 'invoice', + models.ForeignKey( + null=True, on_delete=django.db.models.deletion.CASCADE, to='toulouse_maelis.invoice' + ), + ), + ( + 'resource', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to='toulouse_maelis.toulousemaelis' + ), + ), + ], + options={ + 'ordering': ('resource', 'wcs_form_number'), + 'unique_together': {('resource', 'wcs_form_number')}, + }, + ), + ] diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py index e29d0d31..816fc58d 100644 --- a/passerelle/contrib/toulouse_maelis/models.py +++ b/passerelle/contrib/toulouse_maelis/models.py @@ -3399,6 +3399,34 @@ class ToulouseMaelis(BaseResource, HTTPResource): response = self.call('Activity', 'addPersonUnitBasket', **payload) if not response['controlResult']['controlOK']: raise APIError(response['controlResult']['message']) + + # record subscription in order to trigger w.c.s. demand + basket = response.get('basket') + if post_data.get('form_api_url') and post_data.get('form_number') and basket: + regie_id = basket.get('codeRegie') + if regie_id: + related_lines = [] + for line in basket.get('lignes') or []: + if ( + str(line['personneInfo']['numPerson']) == post_data['person_id'] + and line['inscription']['idAct'] == post_data['activity_id'] + and line['inscription']['idUnit'] == post_data['unit_id'] + and line['inscription']['idLieu'] == post_data['place_id'] + ): + if line.get('idIns'): + # subscription ids will be used to match an invoice + related_lines.append(line) + if related_lines: + # remove unrelated basket lines from response + response['basket']['lignes'] = related_lines + + self.subscription_set.create( + wcs_form_api_url=post_data['form_api_url'], + wcs_form_number=post_data['form_number'], + regie_id=regie_id, + family_id=family_id, + maelis_data=response, + ) return {'data': response} @endpoint( @@ -4311,3 +4339,31 @@ class Invoice(models.Model): class Meta: ordering = ('resource', 'regie_id', 'invoice_id') unique_together = [['resource', 'regie_id', 'invoice_id']] + + +class Subscription(models.Model): + '''WCS demand performing basket subscription''' + + resource = models.ForeignKey(ToulouseMaelis, on_delete=models.CASCADE) + wcs_form_number = models.CharField(max_length=16) + wcs_form_api_url = models.CharField(max_length=256) + regie_id = models.CharField(blank=False, max_length=128) + family_id = models.CharField(blank=False, max_length=128) + maelis_data = JSONField(encoder=DjangoJSONEncoder) + basket_removal_date = models.DateTimeField(null=True) + invoice = models.ForeignKey(Invoice, null=True, on_delete=models.CASCADE) + wcs_trigger_payload = JSONField(encoder=DjangoJSONEncoder, null=True) + wcs_trigger_response = JSONField(null=True) + wcs_trigger_date = models.DateTimeField(null=True) + created = models.DateTimeField('Created', auto_now_add=True) + updated = models.DateTimeField('Updated', auto_now=True) + + def __repr__(self): + return '' % (self.wcs_form_number, self.pk) + + def status(self): + return 'pending_basket' + + class Meta: + ordering = ('resource', 'wcs_form_number') + unique_together = [['resource', 'wcs_form_number']] diff --git a/tests/test_toulouse_maelis.py b/tests/test_toulouse_maelis.py index 41515655..e0de9efd 100644 --- a/tests/test_toulouse_maelis.py +++ b/tests/test_toulouse_maelis.py @@ -7589,6 +7589,7 @@ def test_add_person_basket_subscription(family_service, activity_service, con, a ], }, } + assert con.subscription_set.count() == 0 params['recurrent_week'] = None resp = app.post_json(url + '?NameID=local', params=params) @@ -7631,6 +7632,43 @@ def test_add_person_basket_subscription_with_recurrent_week(family_service, acti assert resp.json['err'] == 0 +def test_basket_subscription_providing_wcs_demand(family_service, activity_service, con, app): + family_service.add_soap_response('readFamily', get_xml_file('R_read_family_for_subscription.xml')) + activity_service.add_soap_response('getPersonUnitInfo', get_xml_file('R_get_person_unit_info.xml')) + activity_service.add_soap_response('addPersonUnitBasket', get_xml_file('R_add_person_unit_basket.xml')) + Link.objects.create(resource=con, family_id='1312', name_id='local') + + url = get_endpoint('add-person-basket-subscription') + params = { + 'person_id': '266145', + 'activity_id': 'A10053179798', + 'unit_id': 'A10053179809', + 'place_id': 'A10053179757', + 'start_date': '2023-02-01', + 'end_date': '2023-06-30', + 'form_api_url': 'https://wcs.example.com/api/forms/exemple-inscription-loisirs-1/12/', + 'form_number': '13-12', + } + resp = app.post_json(url + '?NameID=local', params=params) + assert resp.json['err'] == 0 + assert resp.json['data']['controlResult']['controlOK'] is True + assert resp.json['data']['basket']['codeRegie'] == 109 + # unrelated basket lines was removed from response + assert all([x['personneInfo']['numPerson'] == 266145 for x in resp.json['data']['basket']['lignes']]) + + subscription = con.subscription_set.get(wcs_form_number='13-12') + assert ( + subscription.wcs_form_api_url == 'https://wcs.example.com/api/forms/exemple-inscription-loisirs-1/12/' + ) + assert subscription.created is not None + assert subscription.regie_id == '109' + assert subscription.family_id == '1312' + assert subscription.invoice is None + assert subscription.status() == 'pending_basket' + assert subscription.maelis_data == resp.json['data'] + assert [x['idIns'] for x in subscription.maelis_data['basket']['lignes']] == ['S10055641658'] + + def test_add_person_basket_subscription_error(family_service, activity_service, con, app): family_service.add_soap_response('readFamily', get_xml_file('R_read_family.xml')) activity_service.add_soap_response(