0003-toulouse_axel-booking_info-endpoint-39126.patch
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è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 |
- |