Projet

Général

Profil

0003-toulouse_axel-booking_info-endpoint-39126.patch

Lauréline Guérin, 27 janvier 2020 11:22

Télécharger (34,3 ko)

Voir les différences:

Subject: [PATCH 3/3] toulouse_axel: booking_info endpoint (#39126)

 passerelle/contrib/toulouse_axel/models.py    | 104 +++++++
 passerelle/contrib/toulouse_axel/utils.py     |  26 ++
 .../xsd/Dui/Q_EnfantsActivites.xsd            |  24 ++
 .../xsd/Dui/Q_ReservationPeriode.xsd          |  55 ++++
 .../xsd/Dui/R_EnfantsActivites.xsd            |  96 +++++++
 .../xsd/Dui/R_ReservationPeriode.xsd          |  59 ++++
 tests/data/toulouse_axel/booking_info.xml     |  28 ++
 tests/data/toulouse_axel/child_activities.xml |  62 +++++
 tests/test_toulouse_axel.py                   | 259 +++++++++++++++++-
 tests/test_toulouse_axel_utils.py             |  62 +++++
 10 files changed, 774 insertions(+), 1 deletion(-)
 create mode 100644 passerelle/contrib/toulouse_axel/xsd/Dui/Q_EnfantsActivites.xsd
 create mode 100644 passerelle/contrib/toulouse_axel/xsd/Dui/Q_ReservationPeriode.xsd
 create mode 100644 passerelle/contrib/toulouse_axel/xsd/Dui/R_EnfantsActivites.xsd
 create mode 100644 passerelle/contrib/toulouse_axel/xsd/Dui/R_ReservationPeriode.xsd
 create mode 100644 tests/data/toulouse_axel/booking_info.xml
 create mode 100644 tests/data/toulouse_axel/child_activities.xml
 create mode 100644 tests/test_toulouse_axel_utils.py
passerelle/contrib/toulouse_axel/models.py
211 211
ref_facture_a_payer = Operation('RefFactureAPayer')
212 212
ref_facture_pdf = Operation('RefFacturePDF', prefix='')
213 213
list_dui_factures = Operation('ListeDuiFacturesPayeesRecettees', request_root_element='LISTFACTURE')
214
enfants_activites = Operation('EnfantsActivites', request_root_element='DUI')
215
reservation_periode = Operation('ReservationPeriode')
214 216

  
215 217

  
216 218
class ToulouseAxel(BaseResource):
......
882 884
                      'xml_response': e.xml_response})
883 885
        return {'data': True}
884 886

  
887
    def get_child_activities(self, dui, reference_year, child_id):
888
        try:
889
            result = enfants_activites(self, {
890
                'DUI': {
891
                    'IDDUI': dui,
892
                    'ANNEEREFERENCE': str(reference_year),
893
                    'TYPESACTIVITES': 'MAT,MIDI,SOIR,GARD',
894
                }
895
            })
896
        except AxelError as e:
897
            raise APIError(
898
                'Axel error: %s' % e,
899
                err_code='error',
900
                data={'xml_request': e.xml_request,
901
                      'xml_response': e.xml_response})
902

  
903
        child_activities_data = result.json_response['DATA']['PORTAIL']['DUI'].get('ENFANT', [])
904
        for child in child_activities_data:
905
            if child['IDPERSONNE'] == child_id:
906
                return child
907

  
908
        raise APIError('Child not found', err_code='not-found')
909

  
910
    @endpoint(
911
        description=_("Get information about CLAE booking"),
912
        perm='can_access',
913
        parameters={
914
            'NameID': {'description': _('Publik ID')},
915
            'idpersonne': {'description': _('Child ID')},
916
            'booking_date': {'description': _('Booking date')},
917
        })
918
    def clae_booking_info(self, request, NameID, idpersonne, booking_date):
919
        link = self.get_link(NameID)
920
        try:
921
            booking_date = datetime.datetime.strptime(booking_date, utils.json_date_format)
922
        except ValueError:
923
            raise APIError('bad date format', err_code='bad-request', http_status=400)
924

  
925
        reference_year = utils.get_reference_year_from_date(booking_date)
926

  
927
        # first get activities information for the child
928
        child_activities = self.get_child_activities(
929
            dui=link.dui,
930
            reference_year=reference_year,
931
            child_id=idpersonne)
932

  
933
        # then get booking of the requested week for the child
934
        activity_ids = [act['IDACTIVITE'] for act in child_activities.get('ACTIVITE', [])]
935
        start_date, end_date = utils.get_week_dates_from_date(booking_date)
936
        activity_data = []
937
        for activity_id in activity_ids:
938
            activity_data.append({
939
                'IDACTIVITE': activity_id,
940
                'ANNEEREFERENCE': str(reference_year),
941
                'DATEDEBUT': start_date.strftime(utils.xml_date_format),
942
                'DATEDFIN': end_date.strftime(utils.xml_date_format),
943
            })
944
        try:
945
            data = reservation_periode(self, {'PORTAIL': {
946
                'DUI': {
947
                    'IDDUI': link.dui,
948
                    'ENFANT': {
949
                        'IDPERSONNE': idpersonne,
950
                        'ACTIVITE': activity_data,
951
                    }
952
                }
953
            }})
954
        except AxelError as e:
955
            raise APIError(
956
                'Axel error: %s' % e,
957
                err_code='error',
958
                data={'xml_request': e.xml_request,
959
                      'xml_response': e.xml_response})
960

  
961
        child_booking = None
962
        for child in data.json_response['DATA']['PORTAIL']['DUI'].get('ENFANT', []):
963
            if child['IDPERSONNE'] == idpersonne:
964
                child_booking = child
965
                break
966
        if child_booking is None:
967
            # should not happen
968
            raise APIError('Child not found', err_code='not-found')
969

  
970
        # build the response payload: add booking to activities information
971
        booking_days = {}
972
        for booking in child_booking.get('ACTIVITE', []):
973
            booking_days[booking['IDACTIVITE']] = {
974
                'raw_value': booking['JOUR'],
975
                'days': {
976
                    'monday': utils.get_booking(booking['JOUR'][0]),
977
                    'tuesday': utils.get_booking(booking['JOUR'][1]),
978
                    'wednesday': utils.get_booking(booking['JOUR'][2]),
979
                    'thursday': utils.get_booking(booking['JOUR'][3]),
980
                    'friday': utils.get_booking(booking['JOUR'][4]),
981
                }
982
            }
983

  
984
        for activity in child_activities.get('ACTIVITE', []):
985
            activity['booking'] = booking_days.get(activity['IDACTIVITE'], {})
986

  
987
        return {'data': child_activities}
988

  
885 989

  
886 990
class Link(models.Model):
887 991
    resource = models.ForeignKey(ToulouseAxel, on_delete=models.CASCADE)
passerelle/contrib/toulouse_axel/utils.py
122 122
        pay_limit_date = datetime.datetime.strptime(invoice['DATEECHEANCE'], '%Y-%m-%d').date()
123 123
        data['online_payment'] = data['amount'] > 0 and pay_limit_date >= datetime.date.today()
124 124
    return data
125

  
126

  
127
def get_reference_year_from_date(booking_date):
128
    if booking_date.month <= 7:
129
        # between january and july, reference year is the year just before
130
        # (september)
131
        return booking_date.year - 1
132
    return booking_date.year
133

  
134

  
135
def get_week_dates_from_date(booking_date):
136
    day = booking_date.weekday()
137
    # return monday and friday of the week
138
    return (
139
        booking_date - datetime.timedelta(days=day),
140
        booking_date + datetime.timedelta(days=4 - day)
141
    )
142

  
143

  
144
def get_booking(value):
145
    # 0: no registration
146
    # 1: registration
147
    # 2: not applicable (example: GARDERIE is applicable only on wednesday)
148
    if value == '2':
149
        return None
150
    return value == '1'
passerelle/contrib/toulouse_axel/xsd/Dui/Q_EnfantsActivites.xsd
1
<?xml version="1.0" encoding="utf-8" ?>
2
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
3
	xmlns:all="urn:AllAxelTypes">
4

  
5
	<xsd:import schemaLocation="../AllAxelTypes.xsd" namespace="urn:AllAxelTypes" />
6

  
7

  
8
	<xsd:element name="IDDUI" type="all:IDENTREQUIREDType" />
9
	<xsd:element name="ANNEEREFERENCE" type="all:ANNEEType" />
10
	<xsd:element name="TYPESACTIVITES" type="xsd:string" />
11

  
12

  
13
	<xsd:element name="DUI">
14
		<xsd:complexType>
15
			<xsd:sequence>
16
				<xsd:element ref="IDDUI" minOccurs="1" maxOccurs="1" />
17
				<xsd:element ref="ANNEEREFERENCE" minOccurs="1"
18
					maxOccurs="1" />
19
				<xsd:element ref="TYPESACTIVITES" minOccurs="1"
20
					maxOccurs="1" />
21
			</xsd:sequence>
22
		</xsd:complexType>
23
	</xsd:element>
24
</xsd:schema>
passerelle/contrib/toulouse_axel/xsd/Dui/Q_ReservationPeriode.xsd
1
<?xml version="1.0" encoding="utf-8" ?>
2
<xsd:schema xmlns:all="urn:AllAxelTypes" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
3
	
4
	<xsd:import schemaLocation="../AllAxelTypes.xsd" namespace="urn:AllAxelTypes"  />
5
	
6
	<xsd:complexType name="activite">
7
		<xsd:sequence>
8
			<xsd:element ref="ANNEEREFERENCE" />
9
			<xsd:element ref="IDACTIVITE" />
10
			<xsd:element ref="DATEDEBUT" />
11
			<xsd:element ref="DATEDFIN" />
12
			<xsd:element ref="FILTRESD" minOccurs="0"/>
13
		</xsd:sequence> 
14
	</xsd:complexType>
15
	
16
	<xsd:complexType name="enfant">
17
		<xsd:sequence>
18
			<xsd:element ref="IDPERSONNE" />
19
			<xsd:element ref="ACTIVITE" minOccurs="1" maxOccurs="unbounded"/>
20
		</xsd:sequence> 
21
	</xsd:complexType>
22
	
23
	<xsd:complexType name="DUIType">
24
		<xsd:sequence>
25
			<xsd:element ref="IDDUI" />
26
			<xsd:element ref="ENFANT"  minOccurs="1" maxOccurs="unbounded"/>
27
		</xsd:sequence> 
28
	</xsd:complexType>
29
	
30
	<xsd:complexType name="PORTAILType">
31
		<xsd:sequence>
32
				<xsd:element ref="DUI"/>
33
		</xsd:sequence>	
34
	</xsd:complexType>
35
	
36
	<xsd:simpleType name="filtresd">
37
		<xsd:union memberTypes="all:ONType all:empty-string" />
38
	</xsd:simpleType>
39
	
40
	<xsd:element name="IDDUI" type="all:IDENTREQUIREDType"/>
41
	<xsd:element name="ENFANT" type="enfant"/>
42
	
43
	<xsd:element name="IDPERSONNE" type="all:IDENTREQUIREDType"/>
44
	
45
	<xsd:element name="ANNEEREFERENCE" type="all:ANNEEType"/>
46
	<xsd:element name="IDACTIVITE" type="all:IDREQUIREDType"/>
47
	<xsd:element name="DATEDEBUT" type="all:DATEREQUIREDType"/>
48
	<xsd:element name="DATEDFIN" type="all:DATEREQUIREDType"/>
49
	<xsd:element name="FILTRESD" type="filtresd"/>
50
			
51
	<xsd:element name="ACTIVITE" type="activite"/>
52
	<xsd:element name="DUI" type="DUIType"/>
53
	
54
	<xsd:element name="PORTAIL" type="PORTAILType"/>
55
</xsd:schema>
passerelle/contrib/toulouse_axel/xsd/Dui/R_EnfantsActivites.xsd
1
<?xml version="1.0" encoding="utf-8" ?>
2
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
3
	
4
	<xsd:import schemaLocation="../AllAxelTypes.xsd" namespace="urn:AllAxelTypes"  />
5

  
6
	<xsd:redefine schemaLocation="../R_ShemaResultat.xsd">
7
	    <xsd:simpleType name="TYPEType">
8
			<xsd:restriction base="TYPEType">
9
				<xsd:enumeration value="EnfantsActivites" />
10
			</xsd:restriction>
11
	    </xsd:simpleType>
12
		
13
		<xsd:complexType name="PORTAILType">
14
			<xsd:complexContent>
15
				<xsd:extension base="PORTAILType">
16
					<xsd:sequence>
17
							<xsd:element ref="DUI" />
18
					</xsd:sequence>	
19
				</xsd:extension>
20
			 </xsd:complexContent>
21
		</xsd:complexType>
22
	</xsd:redefine>
23
	
24
	<xsd:simpleType name="typeactivite">
25
		<xsd:restriction base="xsd:string">
26
			<xsd:minLength value="1"/>
27
			<xsd:maxLength value="4"/>
28
		</xsd:restriction>
29
	</xsd:simpleType>
30

  
31
	<xsd:complexType name="dui">
32
		<xsd:sequence>
33
			<xsd:element ref="IDDUI" />
34
			<xsd:element ref="NBENFANTINSCRIT" />
35
			<xsd:element ref="ENFANT" minOccurs="0" maxOccurs="unbounded"/>
36
		</xsd:sequence> 
37
	</xsd:complexType>
38
	
39
	<xsd:complexType name="enfant">
40
		<xsd:sequence>
41
			<xsd:element ref="NOM" />
42
			<xsd:element ref="PRENOM" />
43
			<xsd:element ref="DATENAISSANCE" />
44
			<xsd:element ref="IDPERSONNE" />
45
			<xsd:element ref="REGIME" />
46
			<xsd:element ref="LIBELLEECOLE" />
47
			<xsd:element ref="ACTIVITE" minOccurs="0" maxOccurs="unbounded"/>
48
		</xsd:sequence> 
49
	</xsd:complexType>
50
	
51
	<xsd:complexType name="activite">
52
		<xsd:sequence>
53
			<xsd:element ref="TYPEACTIVITE" />
54
			<xsd:element ref="IDACTIVITE" />
55
			<xsd:element ref="LIBELLEACTIVITE" />
56
			<xsd:element ref="DATEENTREE" />
57
			<xsd:element ref="DATESORTIE" />
58
			<xsd:element ref="TARIF" />
59
			<xsd:element ref="ISPAI" />
60
			<xsd:element ref="COUTREVIENT" />
61
			<xsd:element ref="DATEDEBUT" />
62
			<xsd:element ref="DATEFIN" />
63
		</xsd:sequence> 
64
	</xsd:complexType>
65
	
66
	<xsd:simpleType name="regime">
67
		<xsd:restriction base="xsd:string">
68
			<xsd:maxLength value="4" />
69
		</xsd:restriction>
70
	</xsd:simpleType>
71
	
72
	<xsd:element name="IDDUI" type="all:IDENTREQUIREDType"/>
73
	<xsd:element name="NBENFANTINSCRIT" type="xsd:positiveInteger"/>
74
	<xsd:element name="NOM" type="all:NOMREQUIREDType"/>
75
	<xsd:element name="PRENOM" type="all:PRENOMREQUIREDType"/>
76
	<xsd:element name="DATENAISSANCE" type="all:DATEType"/>
77
	<xsd:element name="IDPERSONNE" type="all:IDENTREQUIREDType"/>
78
	<xsd:element name="REGIME" type="regime" />
79
	<xsd:element name="LIBELLEECOLE" type="xsd:string"/>
80
		
81
	<xsd:element name="TYPEACTIVITE" type="typeactivite"/>
82
	<xsd:element name="IDACTIVITE" type="all:IDREQUIREDType"/>
83
	<xsd:element name="LIBELLEACTIVITE" type="xsd:string"/>
84
	<xsd:element name="DATEENTREE" type="all:DATEType"/>
85
	<xsd:element name="DATESORTIE" type="all:DATEType"/>
86
	<xsd:element name="TARIF" type="all:MONTANTType"/>
87
	<xsd:element name="ISPAI" type="all:OUINONType"/>
88
	<xsd:element name="COUTREVIENT" type="all:MONTANTType"/>
89
	<xsd:element name="DATEDEBUT" type="all:DATEREQUIREDType"/>
90
	<xsd:element name="DATEFIN" type="all:DATEREQUIREDType"/>
91
	
92
	<xsd:element name="ENFANT" type="enfant" />
93
	<xsd:element name="ACTIVITE" type="activite" />
94
	<xsd:element name="DUI" type="dui" />
95

  
96
</xsd:schema>
passerelle/contrib/toulouse_axel/xsd/Dui/R_ReservationPeriode.xsd
1
<?xml version="1.0" encoding="utf-8" ?>
2
<xsd:schema xmlns:all="urn:AllAxelTypes" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3

  
4
	<xsd:import schemaLocation="../AllAxelTypes.xsd" namespace="urn:AllAxelTypes"  />
5

  
6

  
7
	<xsd:redefine schemaLocation="../R_ShemaResultat.xsd">
8
	    <xsd:simpleType name="TYPEType">
9
			<xsd:restriction base="TYPEType">
10
				<xsd:enumeration value="ReservationPeriode" />
11
			</xsd:restriction>
12
	    </xsd:simpleType>
13
		
14
		<xsd:complexType name="PORTAILType">
15
			<xsd:complexContent>
16
				<xsd:extension base="PORTAILType">
17
					<xsd:sequence>
18
						<xsd:element ref="DUI" minOccurs="1" maxOccurs="1"/>
19
					</xsd:sequence>	
20
				</xsd:extension>
21
			 </xsd:complexContent>
22
		</xsd:complexType>
23
	</xsd:redefine>
24
	
25
		<xsd:complexType name="activite">
26
		<xsd:sequence>
27
			<xsd:element ref="ANNEEREFERENCE" />
28
			<xsd:element ref="IDACTIVITE" />
29
			<xsd:element ref="JOUR" />
30
		</xsd:sequence> 
31
	</xsd:complexType>
32
	
33
	<xsd:complexType name="enfant">
34
		<xsd:sequence>
35
			<xsd:element ref="IDPERSONNE" />
36
			<xsd:element ref="ACTIVITE" minOccurs="1" maxOccurs="unbounded"/>
37
		</xsd:sequence> 
38
	</xsd:complexType>
39
	
40
	<xsd:complexType name="DUIType">
41
		<xsd:sequence>
42
			<xsd:element ref="IDDUI" />
43
			<xsd:element ref="ENFANT"  minOccurs="1" maxOccurs="unbounded"/>
44
		</xsd:sequence> 
45
	</xsd:complexType>
46
		
47
	<xsd:element name="IDDUI" type="all:IDENTREQUIREDType"/>
48
	<xsd:element name="ENFANT" type="enfant"/>
49
	
50
	<xsd:element name="IDPERSONNE" type="all:IDENTREQUIREDType"/>
51
	
52
	<xsd:element name="ANNEEREFERENCE" type="all:ANNEEType"/>
53
	<xsd:element name="IDACTIVITE" type="all:IDREQUIREDType"/>
54
	<xsd:element name="JOUR" type="xsd:string"/>
55
			
56
	<xsd:element name="ACTIVITE" type="activite"/>
57
	<xsd:element name="DUI" type="DUIType"/>
58
	
59
</xsd:schema>
tests/data/toulouse_axel/booking_info.xml
1
<PORTAIL>
2
  <DUI>
3
    <IDDUI>XXX</IDDUI>
4
    <ENFANT>
5
      <IDPERSONNE>3535</IDPERSONNE>
6
      <ACTIVITE>
7
        <ANNEEREFERENCE>2019</ANNEEREFERENCE>
8
        <IDACTIVITE>A19P1M1</IDACTIVITE>
9
        <JOUR>00000</JOUR>
10
      </ACTIVITE>
11
      <ACTIVITE>
12
        <ANNEEREFERENCE>2019</ANNEEREFERENCE>
13
        <IDACTIVITE>A19P1M2</IDACTIVITE>
14
        <JOUR>11111</JOUR>
15
      </ACTIVITE>
16
      <ACTIVITE>
17
        <ANNEEREFERENCE>2019</ANNEEREFERENCE>
18
        <IDACTIVITE>A19P1M3</IDACTIVITE>
19
        <JOUR>11211</JOUR>
20
      </ACTIVITE>
21
      <ACTIVITE>
22
        <ANNEEREFERENCE>2019</ANNEEREFERENCE>
23
        <IDACTIVITE>A19P1M4</IDACTIVITE>
24
        <JOUR>22122</JOUR>
25
      </ACTIVITE>
26
    </ENFANT>
27
  </DUI>
28
</PORTAIL>
tests/data/toulouse_axel/child_activities.xml
1
<PORTAIL>
2
  <DUI>
3
    <IDDUI>XXX</IDDUI>
4
    <NBENFANTINSCRIT>1</NBENFANTINSCRIT>
5
    <ENFANT>
6
      <NOM>foo</NOM>
7
      <PRENOM>foo</PRENOM>
8
      <DATENAISSANCE>01/01/2019</DATENAISSANCE>
9
      <IDPERSONNE>3535</IDPERSONNE>
10
      <REGIME>SV</REGIME>
11
      <LIBELLEECOLE>MATERNELLE 1</LIBELLEECOLE>
12
      <ACTIVITE>
13
        <TYPEACTIVITE>MAT</TYPEACTIVITE>
14
        <IDACTIVITE>A19P1M1</IDACTIVITE>
15
        <LIBELLEACTIVITE>Temps du matin</LIBELLEACTIVITE>
16
        <DATEENTREE>01/08/2019</DATEENTREE>
17
        <DATESORTIE>31/07/2020</DATESORTIE>
18
        <TARIF>0.42</TARIF>
19
        <ISPAI>NON</ISPAI>
20
        <COUTREVIENT>99999</COUTREVIENT>
21
        <DATEDEBUT>01/08/2019</DATEDEBUT>
22
        <DATEFIN>31/07/2020</DATEFIN>
23
      </ACTIVITE>
24
      <ACTIVITE>
25
        <TYPEACTIVITE>MIDI</TYPEACTIVITE>
26
        <IDACTIVITE>A19P1M2</IDACTIVITE>
27
        <LIBELLEACTIVITE>Temps du midi</LIBELLEACTIVITE>
28
        <DATEENTREE>01/08/2019</DATEENTREE>
29
        <DATESORTIE>31/07/2020</DATESORTIE>
30
        <TARIF>0.43</TARIF>
31
        <ISPAI>NON</ISPAI>
32
        <COUTREVIENT>99999</COUTREVIENT>
33
        <DATEDEBUT>01/08/2019</DATEDEBUT>
34
        <DATEFIN>31/07/2020</DATEFIN>
35
      </ACTIVITE>
36
      <ACTIVITE>
37
        <TYPEACTIVITE>SOIR</TYPEACTIVITE>
38
        <IDACTIVITE>A19P1M3</IDACTIVITE>
39
        <LIBELLEACTIVITE>Temps du soir</LIBELLEACTIVITE>
40
        <DATEENTREE>01/08/2019</DATEENTREE>
41
        <DATESORTIE>31/07/2020</DATESORTIE>
42
        <TARIF>0.44</TARIF>
43
        <ISPAI>NON</ISPAI>
44
        <COUTREVIENT>99999</COUTREVIENT>
45
        <DATEDEBUT>01/08/2019</DATEDEBUT>
46
        <DATEFIN>31/07/2020</DATEFIN>
47
      </ACTIVITE>
48
      <ACTIVITE>
49
        <TYPEACTIVITE>GARD</TYPEACTIVITE>
50
        <IDACTIVITE>A19P1M4</IDACTIVITE>
51
        <LIBELLEACTIVITE>Temps mercredi apr&#232;s midi</LIBELLEACTIVITE>
52
        <DATEENTREE>01/08/2019</DATEENTREE>
53
        <DATESORTIE>31/07/2020</DATESORTIE>
54
        <TARIF>0.45</TARIF>
55
        <ISPAI>NON</ISPAI>
56
        <COUTREVIENT>99999</COUTREVIENT>
57
        <DATEDEBUT>01/08/2019</DATEDEBUT>
58
        <DATEFIN>31/07/2020</DATEFIN>
59
      </ACTIVITE>
60
    </ENFANT>
61
  </DUI>
62
</PORTAIL>
tests/test_toulouse_axel.py
1
# -*- coding: utf-8 -*-
1 2
# passerelle - uniform access to multiple data sources and services
2
# Copyright (C) 2019 Entr'ouvert
3
# Copyright (C) 2020 Entr'ouvert
3 4
#
4 5
# This program is free software: you can redistribute it and/or modify it
5 6
# under the terms of the GNU Affero General Public License as published
......
32 33
    Lock,
33 34
    OperationResult,
34 35
    ToulouseAxel,
36
    enfants_activites,
35 37
    form_maj_famille_dui,
36 38
    form_paiement_dui,
37 39
    list_dui_factures,
......
40 42
    ref_facture_a_payer,
41 43
    ref_facture_pdf,
42 44
    ref_verif_dui,
45
    reservation_periode,
43 46
)
44 47
from passerelle.utils.jsonresponse import APIError
45 48
import utils
......
93 96
    return ref_famille_dui.response_converter.decode(ET.fromstring(resp))['DATA']['PORTAIL']['DUI']
94 97

  
95 98

  
99
@pytest.fixture
100
def child_activities_data():
101
    filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
102
    with open(filepath) as xml:
103
        content = xml.read()
104
    resp = '''
105
    <?xml version="1.0"?>
106
    <PORTAILSERVICE>
107
      <RESULTAT>
108
        <TYPE>EnfantsActivites</TYPE>
109
        <STATUS>OK</STATUS>
110
        <DATE>10/10/2010 10:10:01</DATE>
111
        <COMMENTAIRES><![CDATA[]]></COMMENTAIRES>
112
      </RESULTAT>
113
      <DATA>
114
        %s
115
      </DATA>
116
    </PORTAILSERVICE>
117
    '''.strip() % content
118
    return enfants_activites.response_converter.decode(ET.fromstring(resp))['DATA']['PORTAIL']['DUI']
119

  
120

  
96 121
@pytest.fixture
97 122
def flat_update_params():
98 123
    filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/flat_update_family_info.json')
......
363 388
            })
364 389

  
365 390

  
391
@pytest.mark.parametrize('content', [
392
    '<PORTAIL><DUI/></PORTAIL>',
393
])
394
def test_operation_enfants_activites(resource, content):
395
    with mock_getdata(content, 'EnfantsActivites'):
396
        with pytest.raises(AxelError):
397
            enfants_activites(resource, {
398
                'DUI': {
399
                    'IDDUI': 'XXX',
400
                    'ANNEEREFERENCE': '2042',
401
                    'TYPESACTIVITES': 'MAT,MIDI,SOIR,GARD',
402
                }
403
            })
404

  
405

  
406
@pytest.mark.parametrize('content', [
407
    '<PORTAIL><DUI/></PORTAIL>',
408
])
409
def test_operation_reservation_periode(resource, content):
410
    with mock_getdata(content, 'ReservationPeriode'):
411
        with pytest.raises(AxelError):
412
            reservation_periode(resource, {
413
                'PORTAIL': {
414
                    'DUI': {
415
                        'IDDUI': 'XXX',
416
                    }
417
                }
418
            })
419

  
420

  
366 421
def test_management_dates_endpoint_axel_error(app, resource):
367 422
    with mock.patch('passerelle.contrib.toulouse_axel.models.ref_date_gestion_dui') as operation:
368 423
        operation.side_effect = AxelError('FooBar')
......
1688 1743
            }
1689 1744
        }
1690 1745
    }
1746

  
1747

  
1748
def test_clae_booking_info_endpoint_axel_error(app, resource):
1749
    Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
1750
    with mock.patch('passerelle.contrib.toulouse_axel.models.enfants_activites') as operation:
1751
        operation.side_effect = AxelError('FooBar')
1752
        resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
1753
    assert resp.json['err_desc'] == "Axel error: FooBar"
1754
    assert resp.json['err'] == 'error'
1755

  
1756
    filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
1757
    with open(filepath) as xml:
1758
        content = xml.read()
1759
    with mock_getdata(content, 'EnfantsActivites'):
1760
        with mock.patch('passerelle.contrib.toulouse_axel.models.reservation_periode') as operation:
1761
            operation.side_effect = AxelError('FooBar')
1762
            resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
1763
    assert resp.json['err_desc'] == "Axel error: FooBar"
1764
    assert resp.json['err'] == 'error'
1765

  
1766

  
1767
@pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020'])
1768
def test_clae_booking_info_endpoint_bad_date_format(app, resource, value):
1769
    Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
1770
    resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&booking_date=%s' % value, status=400)
1771
    assert resp.json['err_desc'] == "bad date format"
1772
    assert resp.json['err'] == 'bad-request'
1773

  
1774

  
1775
def test_clae_booking_info_endpoint_no_result(app, resource, child_activities_data):
1776
    resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
1777
    assert resp.json['err_desc'] == "Person not found"
1778
    assert resp.json['err'] == 'not-found'
1779

  
1780
    Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
1781
    filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
1782
    with open(filepath) as xml:
1783
        content = xml.read()
1784
    with mock_getdata(content, 'EnfantsActivites'):
1785
        with mock.patch('passerelle.contrib.toulouse_axel.models.reservation_periode') as operation:
1786
            operation.side_effect = AxelError('FooBar')
1787
            resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=4242&booking_date=2020-01-20')
1788
    assert resp.json['err_desc'] == "Child not found"
1789
    assert resp.json['err'] == 'not-found'
1790

  
1791
    content = """<PORTAIL>
1792
  <DUI>
1793
    <IDDUI>XXX</IDDUI>
1794
    <ENFANT>
1795
      <IDPERSONNE>4242</IDPERSONNE>
1796
      <ACTIVITE>
1797
        <ANNEEREFERENCE>2019</ANNEEREFERENCE>
1798
        <IDACTIVITE>A19P1M1</IDACTIVITE>
1799
        <JOUR>00000</JOUR>
1800
      </ACTIVITE>
1801
    </ENFANT>
1802
  </DUI>
1803
</PORTAIL>"""
1804
    activities = child_activities_data['ENFANT'][0]
1805
    with mock_getdata(content, 'ReservationPeriode'):
1806
        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities):
1807
            resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
1808
    assert resp.json['err_desc'] == "Child not found"
1809
    assert resp.json['err'] == 'not-found'
1810

  
1811

  
1812
def test_clae_booking_info_endpoint(app, resource, child_activities_data):
1813
    Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
1814
    filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/booking_info.xml')
1815
    with open(filepath) as xml:
1816
        content = xml.read()
1817
    activities = child_activities_data['ENFANT'][0]
1818
    with mock_getdata(content, 'ReservationPeriode'):
1819
        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities):
1820
            resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
1821
    assert resp.json['err'] == 0
1822
    assert resp.json['data'] == {
1823
        'ACTIVITE': [
1824
            {
1825
                'COUTREVIENT': '99999',
1826
                'DATEDEBUT': '2019-08-01',
1827
                'DATEENTREE': '2019-08-01',
1828
                'DATEFIN': '2020-07-31',
1829
                'DATESORTIE': '2020-07-31',
1830
                'IDACTIVITE': 'A19P1M1',
1831
                'ISPAI': False,
1832
                'LIBELLEACTIVITE': 'Temps du matin',
1833
                'TARIF': '0.42',
1834
                'TYPEACTIVITE': 'MAT',
1835
                'booking': {
1836
                    'days': {
1837
                        'friday': False,
1838
                        'monday': False,
1839
                        'thursday': False,
1840
                        'tuesday': False,
1841
                        'wednesday': False
1842
                    },
1843
                    'raw_value': '00000'
1844
                }
1845
            },
1846
            {
1847
                'COUTREVIENT': '99999',
1848
                'DATEDEBUT': '2019-08-01',
1849
                'DATEENTREE': '2019-08-01',
1850
                'DATEFIN': '2020-07-31',
1851
                'DATESORTIE': '2020-07-31',
1852
                'IDACTIVITE': 'A19P1M2',
1853
                'ISPAI': False,
1854
                'LIBELLEACTIVITE': 'Temps du midi',
1855
                'TARIF': '0.43',
1856
                'TYPEACTIVITE': 'MIDI',
1857
                'booking': {
1858
                    'days': {
1859
                        'friday': True,
1860
                        'monday': True,
1861
                        'thursday': True,
1862
                        'tuesday': True,
1863
                        'wednesday': True
1864
                    },
1865
                    'raw_value': '11111'
1866
                }
1867
            },
1868
            {
1869
                'COUTREVIENT': '99999',
1870
                'DATEDEBUT': '2019-08-01',
1871
                'DATEENTREE': '2019-08-01',
1872
                'DATEFIN': '2020-07-31',
1873
                'DATESORTIE': '2020-07-31',
1874
                'IDACTIVITE': 'A19P1M3',
1875
                'ISPAI': False,
1876
                'LIBELLEACTIVITE': 'Temps du soir',
1877
                'TARIF': '0.44',
1878
                'TYPEACTIVITE': 'SOIR',
1879
                'booking': {
1880
                    'days': {
1881
                        'friday': True,
1882
                        'monday': True,
1883
                        'thursday': True,
1884
                        'tuesday': True,
1885
                        'wednesday': None
1886
                    },
1887
                    'raw_value': '11211'
1888
                }
1889
            },
1890
            {
1891
                'COUTREVIENT': '99999',
1892
                'DATEDEBUT': '2019-08-01',
1893
                'DATEENTREE': '2019-08-01',
1894
                'DATEFIN': '2020-07-31',
1895
                'DATESORTIE': '2020-07-31',
1896
                'IDACTIVITE': 'A19P1M4',
1897
                'ISPAI': False,
1898
                'LIBELLEACTIVITE': u'Temps mercredi après midi',
1899
                'TARIF': '0.45',
1900
                'TYPEACTIVITE': 'GARD',
1901
                'booking': {
1902
                    'days': {
1903
                        'friday': None,
1904
                        'monday': None,
1905
                        'thursday': None,
1906
                        'tuesday': None,
1907
                        'wednesday': True
1908
                    },
1909
                    'raw_value': '22122'
1910
                }
1911
            }
1912
        ],
1913
        'DATENAISSANCE': '2019-01-01',
1914
        'IDPERSONNE': '3535',
1915
        'LIBELLEECOLE': 'MATERNELLE 1',
1916
        'NOM': 'foo',
1917
        'PRENOM': 'foo',
1918
        'REGIME': 'SV'
1919
    }
1920

  
1921
    # test wrong and missing IDACTIVITE
1922
    content = """<PORTAIL>
1923
  <DUI>
1924
    <IDDUI>XXX</IDDUI>
1925
    <ENFANT>
1926
      <IDPERSONNE>3535</IDPERSONNE>
1927
      <ACTIVITE>
1928
        <ANNEEREFERENCE>2019</ANNEEREFERENCE>
1929
        <IDACTIVITE>UNKNOWN</IDACTIVITE>
1930
        <JOUR>00000</JOUR>
1931
      </ACTIVITE>
1932
    </ENFANT>
1933
  </DUI>
1934
</PORTAIL>"""
1935
    activities = child_activities_data['ENFANT'][0]
1936
    with mock_getdata(content, 'ReservationPeriode'):
1937
        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities):
1938
            resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
1939
    assert resp.json['err'] == 0
1940
    assert resp.json['data']['ACTIVITE'][0]['IDACTIVITE'] == 'A19P1M1'
1941
    assert resp.json['data']['ACTIVITE'][0]['booking'] == {}
1942
    assert resp.json['data']['ACTIVITE'][1]['IDACTIVITE'] == 'A19P1M2'
1943
    assert resp.json['data']['ACTIVITE'][1]['booking'] == {}
1944
    assert resp.json['data']['ACTIVITE'][2]['IDACTIVITE'] == 'A19P1M3'
1945
    assert resp.json['data']['ACTIVITE'][2]['booking'] == {}
1946
    assert resp.json['data']['ACTIVITE'][3]['IDACTIVITE'] == 'A19P1M4'
1947
    assert resp.json['data']['ACTIVITE'][3]['booking'] == {}
tests/test_toulouse_axel_utils.py
1
# passerelle - uniform access to multiple data sources and services
2
# Copyright (C) 2020 Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
import datetime
18
import pytest
19

  
20
from passerelle.contrib.toulouse_axel.utils import (
21
    get_booking,
22
    get_reference_year_from_date,
23
    get_week_dates_from_date,
24
    json_date_format,
25
)
26

  
27

  
28
@pytest.mark.parametrize('value, expected', [
29
    ('0', False),
30
    ('1', True),
31
    ('2', None),
32
    ('foo', False),
33
])
34
def test_get_booking(value, expected):
35
    assert get_booking(value) is expected
36

  
37

  
38
@pytest.mark.parametrize('value, expected', [
39
    ('2020-01-01', 2019),
40
    ('2020-07-31', 2019),
41
    ('2020-08-01', 2020),
42
    ('2020-12-31', 2020),
43
])
44
def test_get_reference_year_from_date(value, expected):
45
    in_date = datetime.datetime.strptime(value, json_date_format)
46
    assert get_reference_year_from_date(in_date) == expected
47

  
48

  
49
@pytest.mark.parametrize('in_value, start_value, end_value', [
50
    ('2020-01-06', '2020-01-06', '2020-01-10'),  # monday
51
    ('2020-01-07', '2020-01-06', '2020-01-10'),  # tuesday
52
    ('2020-01-08', '2020-01-06', '2020-01-10'),  # wednesday
53
    ('2020-01-09', '2020-01-06', '2020-01-10'),  # thursday
54
    ('2020-01-10', '2020-01-06', '2020-01-10'),  # friday
55
    ('2020-01-11', '2020-01-06', '2020-01-10'),  # saturday
56
    ('2020-01-12', '2020-01-06', '2020-01-10'),  # sunday
57
])
58
def test_get_week_dates_from_date(in_value, start_value, end_value):
59
    in_date = datetime.datetime.strptime(in_value, json_date_format)
60
    start_date = datetime.datetime.strptime(start_value, json_date_format)
61
    end_date = datetime.datetime.strptime(end_value, json_date_format)
62
    assert get_week_dates_from_date(in_date) == (start_date, end_date)
0
-