MambuPy 2.3.3__tar.gz → 2.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/__init__.py +1 -1
- {mambupy-2.3.3/mambupy → mambupy-2.5.0/MambuPy}/api/__init__.py +1 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/connector/mambuconnector.py +101 -0
- {mambupy-2.3.3/mambupy → mambupy-2.5.0/MambuPy}/api/connector/rest.py +65 -56
- mambupy-2.5.0/MambuPy/api/connector/rest_helpers.py +63 -0
- mambupy-2.5.0/MambuPy/api/connector/rest_holidays.py +133 -0
- mambupy-2.5.0/MambuPy/api/mambuholiday.py +272 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambuloan.py +59 -3
- {mambupy-2.3.3/mambupy → mambupy-2.5.0/MambuPy}/api/mambustruct.py +14 -2
- {mambupy-2.3.3/mambupy → mambupy-2.5.0/MambuPy}/api/vos.py +9 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy.egg-info/PKG-INFO +1 -1
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy.egg-info/SOURCES.txt +6 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/PKG-INFO +1 -1
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/__init__.py +1 -1
- {mambupy-2.3.3/MambuPy → mambupy-2.5.0/mambupy}/api/__init__.py +1 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/connector/mambuconnector.py +101 -0
- {mambupy-2.3.3/MambuPy → mambupy-2.5.0/mambupy}/api/connector/rest.py +65 -56
- mambupy-2.5.0/mambupy/api/connector/rest_helpers.py +63 -0
- mambupy-2.5.0/mambupy/api/connector/rest_holidays.py +133 -0
- mambupy-2.5.0/mambupy/api/mambuholiday.py +272 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambuloan.py +59 -3
- {mambupy-2.3.3/MambuPy → mambupy-2.5.0/mambupy}/api/mambustruct.py +14 -2
- {mambupy-2.3.3/MambuPy → mambupy-2.5.0/mambupy}/api/vos.py +9 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/LICENSE +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/classes.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/connector/__init__.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/entities.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/interfaces.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambubranch.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambucentre.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambuclient.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambucustomfield.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambugroup.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambuproduct.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mamburole.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambutask.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambutransaction.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/api/mambuuser.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/mambuconfig.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/mambugeturl.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/mambuutil.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/__init__.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_activities.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_addresses.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_branches.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_centres.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_clients.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_customfields.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_dummies.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_groups.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_loans.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_mambu.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_orm.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_tasks.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/orm/schema_users.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/rest/__init__.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/rest/mambuactivity.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/utils/__init__.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/utils/update_user_roles.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy/utils/userdeactivate.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy.egg-info/dependency_links.txt +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy.egg-info/requires.txt +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/MambuPy.egg-info/top_level.txt +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/README.md +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/classes.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/connector/__init__.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/entities.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/interfaces.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambubranch.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambucentre.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambuclient.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambucustomfield.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambugroup.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambuproduct.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mamburole.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambutask.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambutransaction.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/api/mambuuser.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/mambuconfig.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/mambugeturl.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/mambuutil.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/__init__.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_activities.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_addresses.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_branches.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_centres.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_clients.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_customfields.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_dummies.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_groups.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_loans.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_mambu.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_orm.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_tasks.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/orm/schema_users.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/rest/__init__.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/rest/mambuactivity.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/utils/__init__.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/utils/update_user_roles.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/mambupy/utils/userdeactivate.py +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/pyproject.toml +0 -0
- {mambupy-2.3.3 → mambupy-2.5.0}/setup.cfg +0 -0
|
@@ -138,6 +138,28 @@ class MambuConnectorReader(ABC):
|
|
|
138
138
|
"""
|
|
139
139
|
raise NotImplementedError
|
|
140
140
|
|
|
141
|
+
@abstractmethod
|
|
142
|
+
def mambu_organization_get_holidays(self):
|
|
143
|
+
"""Retrieves the holidays of the organization.
|
|
144
|
+
|
|
145
|
+
Both the general holidays and the non-working days of the week.
|
|
146
|
+
"""
|
|
147
|
+
raise NotImplementedError
|
|
148
|
+
|
|
149
|
+
@abstractmethod
|
|
150
|
+
def mambu_organization_get_non_working_days(self):
|
|
151
|
+
"""Retrieves the non-working days of the week of the organization."""
|
|
152
|
+
raise NotImplementedError
|
|
153
|
+
|
|
154
|
+
@abstractmethod
|
|
155
|
+
def mambu_organization_get_holiday(self, holidayid):
|
|
156
|
+
"""Retrieves a single general holiday of the organization.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
holidayid (str): the id or encoded key of the holiday
|
|
160
|
+
"""
|
|
161
|
+
raise NotImplementedError
|
|
162
|
+
|
|
141
163
|
|
|
142
164
|
class MambuConnectorWriter(ABC):
|
|
143
165
|
"""Interface for Writers.
|
|
@@ -286,6 +308,37 @@ class MambuConnectorWriter(ABC):
|
|
|
286
308
|
"""
|
|
287
309
|
raise NotImplementedError
|
|
288
310
|
|
|
311
|
+
@abstractmethod
|
|
312
|
+
def mambu_loanaccount_updateSchedule(self, loanid, installments):
|
|
313
|
+
"""Updates the installments schedule of a loan account
|
|
314
|
+
|
|
315
|
+
Mambu replaces the whole schedule with the given installments, so the
|
|
316
|
+
complete list must be sent, not just the modified ones.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
loanid (str): the id or encoded key of the loan account
|
|
320
|
+
installments (list of dict): the installments of the schedule,
|
|
321
|
+
complying with Mambu's schema
|
|
322
|
+
"""
|
|
323
|
+
raise NotImplementedError
|
|
324
|
+
|
|
325
|
+
@abstractmethod
|
|
326
|
+
def mambu_loanaccount_changeDueDatesSettings(
|
|
327
|
+
self, loanid, fixedDaysOfMonth, notes=None, valueDate=None
|
|
328
|
+
):
|
|
329
|
+
"""Changes the due dates settings of a loan account
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
loanid (str): the id or encoded key of the loan account
|
|
333
|
+
fixedDaysOfMonth (list of int): the new fixed days of month to be used
|
|
334
|
+
on the loan account
|
|
335
|
+
notes (str): notes to associate to the change due dates settings
|
|
336
|
+
operation in Mambu
|
|
337
|
+
valueDate (str or :py:obj:`datetime`): the date when to change the due
|
|
338
|
+
dates settings
|
|
339
|
+
"""
|
|
340
|
+
raise NotImplementedError
|
|
341
|
+
|
|
289
342
|
@abstractmethod
|
|
290
343
|
def mambu_loantransaction_adjust(self, transactionid, notes):
|
|
291
344
|
"""Adjust a loan transaction
|
|
@@ -295,3 +348,51 @@ class MambuConnectorWriter(ABC):
|
|
|
295
348
|
notes (str): notes to associate to the transaction adjustment in Mambu
|
|
296
349
|
"""
|
|
297
350
|
raise NotImplementedError
|
|
351
|
+
|
|
352
|
+
@abstractmethod
|
|
353
|
+
def mambu_organization_update_holidays(self, holidays):
|
|
354
|
+
"""Updates the holidays of the organization
|
|
355
|
+
|
|
356
|
+
Mambu replaces the whole configuration with the one given, so the
|
|
357
|
+
complete set of holidays and non-working days must be sent, not just
|
|
358
|
+
the modified ones.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
holidays (dict): holidays of the organization, complying with
|
|
362
|
+
Mambu's schema
|
|
363
|
+
"""
|
|
364
|
+
raise NotImplementedError
|
|
365
|
+
|
|
366
|
+
@abstractmethod
|
|
367
|
+
def mambu_organization_update_non_working_days(self, nonWorkingDays):
|
|
368
|
+
"""Updates the non-working days of the week of the organization
|
|
369
|
+
|
|
370
|
+
Mambu replaces the whole set with the days given.
|
|
371
|
+
|
|
372
|
+
Args:
|
|
373
|
+
nonWorkingDays (list of str): days of the week on which the
|
|
374
|
+
organization does not operate
|
|
375
|
+
"""
|
|
376
|
+
raise NotImplementedError
|
|
377
|
+
|
|
378
|
+
@abstractmethod
|
|
379
|
+
def mambu_organization_create_holidays(self, holidays):
|
|
380
|
+
"""Creates general holidays for the organization
|
|
381
|
+
|
|
382
|
+
Mambu adds them to the ones already configured, all in a single
|
|
383
|
+
request.
|
|
384
|
+
|
|
385
|
+
Args:
|
|
386
|
+
holidays (list of dict): the holidays to create, complying with
|
|
387
|
+
Mambu's schema
|
|
388
|
+
"""
|
|
389
|
+
raise NotImplementedError
|
|
390
|
+
|
|
391
|
+
@abstractmethod
|
|
392
|
+
def mambu_organization_delete_holiday(self, holidayid):
|
|
393
|
+
"""Deletes a general holiday of the organization
|
|
394
|
+
|
|
395
|
+
Args:
|
|
396
|
+
holidayid (str): the id of the holiday to be deleted
|
|
397
|
+
"""
|
|
398
|
+
raise NotImplementedError
|
|
@@ -9,22 +9,19 @@ Currently supports REST.
|
|
|
9
9
|
|
|
10
10
|
import base64
|
|
11
11
|
import copy
|
|
12
|
-
import datetime
|
|
13
|
-
import enum
|
|
14
12
|
import json
|
|
15
13
|
import mimetypes
|
|
16
14
|
import orjson
|
|
17
15
|
import os
|
|
18
16
|
import re
|
|
19
17
|
import uuid
|
|
20
|
-
from decimal import Decimal
|
|
21
18
|
|
|
22
19
|
import requests
|
|
23
20
|
from requests_toolbelt.multipart.encoder import MultipartEncoder
|
|
24
|
-
from requests.adapters import HTTPAdapter
|
|
25
|
-
from requests.packages.urllib3.util.retry import Retry
|
|
26
21
|
|
|
27
22
|
from .mambuconnector import MambuConnector, MambuConnectorReader, MambuConnectorWriter
|
|
23
|
+
from .rest_helpers import _MambuJSONEncoder, _configure_retry_strategy
|
|
24
|
+
from .rest_holidays import MambuConnectorRESTHolidays
|
|
28
25
|
from MambuPy.mambuutil import (
|
|
29
26
|
ALLOWED_UPLOAD_MIMETYPES,
|
|
30
27
|
DETAILSLEVEL,
|
|
@@ -47,55 +44,6 @@ from MambuPy.mambuutil import (
|
|
|
47
44
|
logger = setup_logging(__name__)
|
|
48
45
|
|
|
49
46
|
|
|
50
|
-
class _MambuJSONEncoder(json.JSONEncoder):
|
|
51
|
-
"""JSON encoder that handles Python types not natively serializable by json.dumps."""
|
|
52
|
-
|
|
53
|
-
def default(self, obj):
|
|
54
|
-
if isinstance(obj, (datetime.datetime, datetime.date)):
|
|
55
|
-
return obj.isoformat()
|
|
56
|
-
if isinstance(obj, enum.Enum):
|
|
57
|
-
return obj.value
|
|
58
|
-
if isinstance(obj, Decimal):
|
|
59
|
-
return float(obj)
|
|
60
|
-
return super().default(obj)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def _configure_retry_strategy(session, retries=5):
|
|
64
|
-
"""Configure retry strategy for a session.
|
|
65
|
-
|
|
66
|
-
El HTTPAdapter se construye con pool_maxsize=50 para que los flujos
|
|
67
|
-
que despachan multiples requests concurrentes contra Mambu (p.ej.
|
|
68
|
-
fan-out de aprobaciones, cargar_datos paralelo) no queden encolados
|
|
69
|
-
sobre el default de urllib3 de 10 conexiones por host.
|
|
70
|
-
|
|
71
|
-
Args:
|
|
72
|
-
session (requests.Session): The session to configure
|
|
73
|
-
retries (int, optional): Number of retries. Defaults to 5.
|
|
74
|
-
"""
|
|
75
|
-
retry_strategy = Retry(
|
|
76
|
-
total=retries,
|
|
77
|
-
status_forcelist=[429, 500, 502, 503, 504],
|
|
78
|
-
backoff_factor=1,
|
|
79
|
-
allowed_methods=[
|
|
80
|
-
"HEAD",
|
|
81
|
-
"GET",
|
|
82
|
-
"OPTIONS",
|
|
83
|
-
"POST",
|
|
84
|
-
"PUT",
|
|
85
|
-
"DELETE",
|
|
86
|
-
"TRACE",
|
|
87
|
-
"PATCH",
|
|
88
|
-
],
|
|
89
|
-
)
|
|
90
|
-
adapter = HTTPAdapter(
|
|
91
|
-
max_retries=retry_strategy,
|
|
92
|
-
pool_connections=50,
|
|
93
|
-
pool_maxsize=50,
|
|
94
|
-
)
|
|
95
|
-
session.mount("https://", adapter)
|
|
96
|
-
session.mount("http://", adapter)
|
|
97
|
-
|
|
98
|
-
|
|
99
47
|
class SessionSingleton:
|
|
100
48
|
"""Singleton class to manage HTTP sessions for MambuPy.
|
|
101
49
|
|
|
@@ -138,8 +86,17 @@ class SessionSingleton:
|
|
|
138
86
|
return self.__session
|
|
139
87
|
|
|
140
88
|
|
|
141
|
-
class MambuConnectorREST(
|
|
142
|
-
|
|
89
|
+
class MambuConnectorREST(
|
|
90
|
+
MambuConnectorRESTHolidays,
|
|
91
|
+
MambuConnector,
|
|
92
|
+
MambuConnectorReader,
|
|
93
|
+
MambuConnectorWriter,
|
|
94
|
+
):
|
|
95
|
+
"""A connector for Mambu REST API
|
|
96
|
+
|
|
97
|
+
Endpoint mixins come first: their implementations must win over the
|
|
98
|
+
abstract methods the interfaces declare for them.
|
|
99
|
+
"""
|
|
143
100
|
|
|
144
101
|
_RETRIES = 5
|
|
145
102
|
_tenant = ""
|
|
@@ -293,6 +250,14 @@ url %s, params %s, data %s, headers %s",
|
|
|
293
250
|
|
|
294
251
|
return resp.content
|
|
295
252
|
|
|
253
|
+
_request = __request
|
|
254
|
+
"""protected alias of the private request method
|
|
255
|
+
|
|
256
|
+
Name mangling resolves ``__request`` against the class where it is
|
|
257
|
+
written, so it is out of reach for an endpoint mixin living in another
|
|
258
|
+
module. Those mixins call this alias instead.
|
|
259
|
+
"""
|
|
260
|
+
|
|
296
261
|
def __list_request_args(self, params):
|
|
297
262
|
if not params:
|
|
298
263
|
params = {}
|
|
@@ -775,6 +740,50 @@ url %s, params %s, data %s, headers %s",
|
|
|
775
740
|
data = {"notes": notes}
|
|
776
741
|
return self.__request("POST", url, data=data)
|
|
777
742
|
|
|
743
|
+
def mambu_loanaccount_updateSchedule(self, loanid, installments):
|
|
744
|
+
"""Updates the installments schedule of a loan account
|
|
745
|
+
|
|
746
|
+
Mambu replaces the whole schedule with the given installments, so the
|
|
747
|
+
complete list must be sent, not just the modified ones.
|
|
748
|
+
|
|
749
|
+
Args:
|
|
750
|
+
loanid (str): the id or encoded key of the loan account
|
|
751
|
+
installments (list of dict): the installments of the schedule,
|
|
752
|
+
complying with Mambu's schema
|
|
753
|
+
"""
|
|
754
|
+
url = "https://{}/api/{}/{}/schedule".format(self._tenant, "loans", loanid)
|
|
755
|
+
|
|
756
|
+
return self.__request("PUT", url, data=installments)
|
|
757
|
+
|
|
758
|
+
def mambu_loanaccount_changeDueDatesSettings(
|
|
759
|
+
self, loanid, fixedDaysOfMonth, notes=None, valueDate=None
|
|
760
|
+
):
|
|
761
|
+
"""Changes the due dates settings of a loan account
|
|
762
|
+
|
|
763
|
+
Only available for loan accounts whose product uses the
|
|
764
|
+
FIXED_DAYS_OF_MONTH repayment methodology. Mambu rejects the request
|
|
765
|
+
otherwise.
|
|
766
|
+
|
|
767
|
+
Args:
|
|
768
|
+
loanid (str): the id or encoded key of the loan account
|
|
769
|
+
fixedDaysOfMonth (list of int): the new fixed days of month to be used
|
|
770
|
+
on the loan account
|
|
771
|
+
notes (str): notes to associate to the change due dates settings
|
|
772
|
+
operation in Mambu
|
|
773
|
+
valueDate (str or :py:obj:`datetime`): the date when to change the due
|
|
774
|
+
dates settings
|
|
775
|
+
"""
|
|
776
|
+
url = "https://{}/api/{}/{}:changeDueDatesSettings".format(
|
|
777
|
+
self._tenant, "loans", loanid
|
|
778
|
+
)
|
|
779
|
+
data = {"fixedDaysOfMonth": fixedDaysOfMonth}
|
|
780
|
+
if notes is not None:
|
|
781
|
+
data["notes"] = notes
|
|
782
|
+
if valueDate is not None:
|
|
783
|
+
data["valueDate"] = valueDate
|
|
784
|
+
|
|
785
|
+
return self.__request("POST", url, data=data)
|
|
786
|
+
|
|
778
787
|
def mambu_change_state(self, entid, prefix, action, notes):
|
|
779
788
|
"""change state of mambu entity
|
|
780
789
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Helpers for the REST connector.
|
|
2
|
+
|
|
3
|
+
.. autosummary::
|
|
4
|
+
:nosignatures:
|
|
5
|
+
:toctree: _autosummary
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import datetime
|
|
9
|
+
import enum
|
|
10
|
+
import json
|
|
11
|
+
from decimal import Decimal
|
|
12
|
+
|
|
13
|
+
from requests.adapters import HTTPAdapter
|
|
14
|
+
from requests.packages.urllib3.util.retry import Retry
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _MambuJSONEncoder(json.JSONEncoder):
|
|
18
|
+
"""JSON encoder that handles Python types not natively serializable by json.dumps."""
|
|
19
|
+
|
|
20
|
+
def default(self, obj):
|
|
21
|
+
if isinstance(obj, (datetime.datetime, datetime.date)):
|
|
22
|
+
return obj.isoformat()
|
|
23
|
+
if isinstance(obj, enum.Enum):
|
|
24
|
+
return obj.value
|
|
25
|
+
if isinstance(obj, Decimal):
|
|
26
|
+
return float(obj)
|
|
27
|
+
return super().default(obj)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _configure_retry_strategy(session, retries=5):
|
|
31
|
+
"""Configure retry strategy for a session.
|
|
32
|
+
|
|
33
|
+
El HTTPAdapter se construye con pool_maxsize=50 para que los flujos
|
|
34
|
+
que despachan multiples requests concurrentes contra Mambu (p.ej.
|
|
35
|
+
fan-out de aprobaciones, cargar_datos paralelo) no queden encolados
|
|
36
|
+
sobre el default de urllib3 de 10 conexiones por host.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
session (requests.Session): The session to configure
|
|
40
|
+
retries (int, optional): Number of retries. Defaults to 5.
|
|
41
|
+
"""
|
|
42
|
+
retry_strategy = Retry(
|
|
43
|
+
total=retries,
|
|
44
|
+
status_forcelist=[429, 500, 502, 503, 504],
|
|
45
|
+
backoff_factor=1,
|
|
46
|
+
allowed_methods=[
|
|
47
|
+
"HEAD",
|
|
48
|
+
"GET",
|
|
49
|
+
"OPTIONS",
|
|
50
|
+
"POST",
|
|
51
|
+
"PUT",
|
|
52
|
+
"DELETE",
|
|
53
|
+
"TRACE",
|
|
54
|
+
"PATCH",
|
|
55
|
+
],
|
|
56
|
+
)
|
|
57
|
+
adapter = HTTPAdapter(
|
|
58
|
+
max_retries=retry_strategy,
|
|
59
|
+
pool_connections=50,
|
|
60
|
+
pool_maxsize=50,
|
|
61
|
+
)
|
|
62
|
+
session.mount("https://", adapter)
|
|
63
|
+
session.mount("http://", adapter)
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Holidays endpoints for the REST connector.
|
|
2
|
+
|
|
3
|
+
.. autosummary::
|
|
4
|
+
:nosignatures:
|
|
5
|
+
:toctree: _autosummary
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MambuConnectorRESTHolidays:
|
|
10
|
+
"""Holidays endpoints of the organization.
|
|
11
|
+
|
|
12
|
+
A mixin, not a connector of its own: it builds the URLs and leans on the
|
|
13
|
+
request machinery of
|
|
14
|
+
:py:obj:`MambuPy.api.connector.rest.MambuConnectorREST`, the class that
|
|
15
|
+
mixes it in.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def mambu_organization_get_holidays(self):
|
|
19
|
+
"""Retrieves the holidays of the organization.
|
|
20
|
+
|
|
21
|
+
Both the general holidays and the non-working days of the week.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
response content (str json {})
|
|
25
|
+
"""
|
|
26
|
+
url = "https://{}/api/organization/holidays".format(self._tenant)
|
|
27
|
+
|
|
28
|
+
return self._request("GET", url)
|
|
29
|
+
|
|
30
|
+
def mambu_organization_update_holidays(self, holidays):
|
|
31
|
+
"""Updates the holidays of the organization
|
|
32
|
+
|
|
33
|
+
Mambu replaces the whole configuration with the one given, so the
|
|
34
|
+
complete set of holidays and non-working days must be sent, not just
|
|
35
|
+
the modified ones.
|
|
36
|
+
|
|
37
|
+
Mambu processes holidays asynchronously: this fails with errorCode
|
|
38
|
+
3633, ANOTHER_TASK_IN_PROGRESS, while a previous holidays operation
|
|
39
|
+
is still running. The error is transient and is not retried here.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
holidays (dict): holidays of the organization, complying with
|
|
43
|
+
Mambu's schema
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
response content (str json {})
|
|
47
|
+
"""
|
|
48
|
+
url = "https://{}/api/organization/holidays".format(self._tenant)
|
|
49
|
+
|
|
50
|
+
return self._request("PUT", url, data=holidays)
|
|
51
|
+
|
|
52
|
+
def mambu_organization_get_non_working_days(self):
|
|
53
|
+
"""Retrieves the non-working days of the week of the organization.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
response content (str json {})
|
|
57
|
+
"""
|
|
58
|
+
url = "https://{}/api/organization/holidays/nonworkingdays".format(self._tenant)
|
|
59
|
+
|
|
60
|
+
return self._request("GET", url)
|
|
61
|
+
|
|
62
|
+
def mambu_organization_update_non_working_days(self, nonWorkingDays):
|
|
63
|
+
"""Updates the non-working days of the week of the organization
|
|
64
|
+
|
|
65
|
+
Mambu replaces the whole set with the days given.
|
|
66
|
+
|
|
67
|
+
Mambu processes holidays asynchronously: this fails with errorCode
|
|
68
|
+
3633, ANOTHER_TASK_IN_PROGRESS, while a previous holidays operation
|
|
69
|
+
is still running. The error is transient and is not retried here.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
nonWorkingDays (list of str): days of the week on which the
|
|
73
|
+
organization does not operate
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
response content (str json {})
|
|
77
|
+
"""
|
|
78
|
+
url = "https://{}/api/organization/holidays/nonworkingdays".format(self._tenant)
|
|
79
|
+
data = {"nonWorkingDays": nonWorkingDays}
|
|
80
|
+
|
|
81
|
+
return self._request("PUT", url, data=data)
|
|
82
|
+
|
|
83
|
+
def mambu_organization_create_holidays(self, holidays):
|
|
84
|
+
"""Creates general holidays for the organization
|
|
85
|
+
|
|
86
|
+
Mambu adds them to the ones already configured, all in a single
|
|
87
|
+
request.
|
|
88
|
+
|
|
89
|
+
Mambu processes holidays asynchronously: this fails with errorCode
|
|
90
|
+
3633, ANOTHER_TASK_IN_PROGRESS, while a previous holidays operation
|
|
91
|
+
is still running. The error is transient and is not retried here.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
holidays (list of dict): the holidays to create, complying with
|
|
95
|
+
Mambu's schema
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
response content (str json [])
|
|
99
|
+
"""
|
|
100
|
+
url = "https://{}/api/organization/holidays/general".format(self._tenant)
|
|
101
|
+
|
|
102
|
+
return self._request("POST", url, data=holidays)
|
|
103
|
+
|
|
104
|
+
def mambu_organization_get_holiday(self, holidayid):
|
|
105
|
+
"""Retrieves a single general holiday of the organization.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
holidayid (str): the id or encoded key of the holiday
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
response content (str json {})
|
|
112
|
+
"""
|
|
113
|
+
url = "https://{}/api/organization/holidays/general/{}".format(
|
|
114
|
+
self._tenant, holidayid
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return self._request("GET", url)
|
|
118
|
+
|
|
119
|
+
def mambu_organization_delete_holiday(self, holidayid):
|
|
120
|
+
"""Deletes a general holiday of the organization
|
|
121
|
+
|
|
122
|
+
Mambu processes holidays asynchronously: this fails with errorCode
|
|
123
|
+
3633, ANOTHER_TASK_IN_PROGRESS, while a previous holidays operation
|
|
124
|
+
is still running. The error is transient and is not retried here.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
holidayid (str): the id of the holiday to be deleted
|
|
128
|
+
"""
|
|
129
|
+
url = "https://{}/api/organization/holidays/general/{}".format(
|
|
130
|
+
self._tenant, holidayid
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
return self._request("DELETE", url)
|