# coding: utf-8
"""Mambu Groups objects.
.. autosummary::
:nosignatures:
:toctree: _autosummary
MambuGroup holds a group.
MambuGroups holds a list of groups.
Uses mambugeturl.getgroupurl as default urlfunc
"""
from ..mambugeturl import getgroupcustominformationurl, getgroupurl
from .mambustruct import MambuStruct
from .mamburestutils import MambuStructIterator
# Other options include getgrouploansurl and getgroupcustominformationurl
mod_urlfunc = getgroupurl
[docs]class MambuGroup(MambuStruct):
"""A Group from Mambu.
With the default urlfunc, entid argument must be the ID of the
group you wish to retrieve.
"""
[docs] def __init__(self, urlfunc=mod_urlfunc, entid="", *args, **kwargs):
"""Tasks done here:
Just initializes the MambuStruct.
"""
MambuStruct.__init__(
self, urlfunc, entid, custom_field_name="customInformation", *args, **kwargs
)
[docs] def preprocess(self):
"""Preprocessing.
Flattens the object. Important data comes on the 'theGroup'
dictionary inside of the response. Instead, every element of the
'theGroup' dictionary is taken out to the main attrs dictionary.
Notes on the group get some html tags removed.
.. todo:: use mambuutil.strip_tags() method
A 'name' field is added, equivalent to the 'groupName' field.
This is useful on loan accounts. They get a 'holder' field added
somewhere, which may be an individual client, or a group. So to
get the holder name, you just access the 'holder'['name']. No
matter if you have a client loan or a group loan, you get the
name of the holder.
"""
super(MambuGroup, self).preprocess()
try:
for k, v in self["theGroup"].items():
self[k] = v
del self.attrs["theGroup"]
except Exception:
pass
try:
self["notes"] = self["notes"].replace("<div>", "").replace("</div>", "")
except Exception:
self["notes"] = ""
try:
self["name"] = self["groupName"]
except KeyError:
pass
self["address"] = {}
try:
for name, item in self["addresses"][0].items():
try:
self["addresses"][0][name] = item.strip()
self["address"][name] = item.strip()
except AttributeError:
pass
except (KeyError, IndexError):
pass
[docs] def setClients(self, *args, **kwargs):
"""Adds the clients for this group to a 'clients' field.
The 'groupMembers' field of the group holds the encodedKeys of
the member clients of the group. Since Mambu REST API accepts
both ids or encodedKeys to retrieve entities, we use that here.
You may wish to get the full details of each client by passing a
fullDetails=True argument here.
Returns the number of requests done to Mambu.
"""
requests = 0
if "fullDetails" in kwargs:
fullDetails = kwargs["fullDetails"]
kwargs.pop("fullDetails")
else:
fullDetails = True
clients = []
for m in self["groupMembers"]:
try:
self.mambuclientclass = kwargs.pop("mambuclientclass")
except KeyError:
try:
self.mambuclientclass
except AttributeError:
from .mambuclient import MambuClient
self.mambuclientclass = MambuClient
client = self.mambuclientclass(
entid=m["clientKey"], fullDetails=fullDetails, *args, **kwargs
)
requests += 1
clients.append(client)
self["clients"] = clients
return requests
[docs] def setBranch(self, *args, **kwargs):
"""Adds the branch to which this groups belongs"""
try:
self.mambubranchclass
except AttributeError:
from .mambubranch import MambuBranch
self.mambubranchclass = MambuBranch
branch = self.mambubranchclass(entid=self["assignedBranchKey"], *args, **kwargs)
self["branch"] = branch
return 1
[docs] def setCentre(self, *args, **kwargs):
"""Adds the centre to which this groups belongs"""
try:
self.mambucentreclass
except AttributeError:
from .mambucentre import MambuCentre
self.mambucentreclass = MambuCentre
centre = self.mambucentreclass(entid=self["assignedCentreKey"], *args, **kwargs)
self["centre"] = centre
return 1
[docs] def setActivities(self, *args, **kwargs):
"""Adds the activities for this group to a 'activities' field.
Activities are MambuActivity objects.
Activities get sorted by activity timestamp.
Returns the number of requests done to Mambu.
"""
def activity_date(activity):
"""Util function used for sorting activities according to timestamp"""
try:
return activity["activity"]["timestamp"]
except KeyError:
return None
try:
self.mambuactivitiesclass
except AttributeError:
from .mambuactivity import MambuActivities
self.mambuactivitiesclass = MambuActivities
activities = self.mambuactivitiesclass(
groupId=self["encodedKey"], *args, **kwargs
)
activities.attrs = sorted(activities.attrs, key=activity_date)
self["activities"] = activities
return 1
[docs] def create(self, data, *args, **kwargs):
"""Creates a group in Mambu
Parameters
-data dictionary with data to send
"""
super(MambuGroup, self).create(data)
if self.get("customInformation"):
self["group"][self.custom_field_name] = self["customInformation"]
if self.get("addresses"):
self["group"]["addresses"] = self["addresses"]
if self.get("groupMembers"):
self["group"]["groupMembers"] = self["groupMembers"]
self.init(attrs=self["group"])
return 1
[docs] def update(self, data, *args, **kwargs):
"""Updates a group in Mambu
Uses PATCH and POST methods, for update "groupMembers", "groupRoles"
and "group fields" PATCH method is used, for "customInformation" also
Patch is used but url needs to be changed, in order to update
"addresses" POST method is needed.
https://support.mambu.com/docs/groups-api#post-group
https://support.mambu.com/docs/groups-api#patch-group-information
https://support.mambu.com/docs/groups-api#patch-group-custom-field-values
Parameters
-data dictionary with data to update
"""
cont_requests = 0
data2update = {}
# SET groupMembers
if data.get("groupMembers"):
data2update["groupMembers"] = data.get("groupMembers")
# SET groupRoles
if data.get("groupRoles"):
data2update["groupRoles"] = data.get("groupRoles")
# if there is data to update or data group to update, updates
if data2update or data.get("group"):
# SET group fields
data2update["group"] = data.get("group", {})
# UPDATE group fields
cont_requests += self.update_patch(data2update, *args, **kwargs)
# UPDATE customFields
if data.get("customInformation"):
data2update = {"group": {}}
data2update["customInformation"] = data.get("customInformation")
self._MambuStruct__urlfunc = getgroupcustominformationurl
cont_requests += self.update_patch(data2update, *args, **kwargs)
self._MambuStruct__urlfunc = getgroupurl
# UPDATE addresses
if data.get("addresses"):
data2update = self._notUpdateData()
data2update["addresses"] = data.get("addresses")
cont_requests += self.update_post(data2update, *args, **kwargs)
cont_requests += super(MambuGroup, self).update(data, *args, **kwargs)
return cont_requests
[docs] def update_patch(self, data, *args, **kwargs):
"""Updates a group Mambu using method PATCH
Args:
data (dictionary): dictionary with data to update
https://support.mambu.com/docs/groups-api#patch-group-information
"""
return super(MambuGroup, self).update_patch(data, *args, **kwargs)
[docs] def update_post(self, data, *args, **kwargs):
"""Updates a group in Mambu using method POST
Args:
data (dictionary): dictionary with data to update
https://support.mambu.com/docs/groups-api#post-group
"""
return super(MambuGroup, self).update_post(data, *args, **kwargs)
[docs] def _notUpdateData(self):
"""Data that would not be updated/overwritten in case of POST
Dictionary with group data copied
"""
notUpdateFields = [
"id",
"groupName",
"mobilePhone1",
"homePhone",
"emailAddress",
"preferredLanguage",
"notes",
"assignedUserKey",
"assignedCentreKey",
"assignedBranchKey",
]
data = {"group": {}}
data["group"] = {f: self.get(f) for f in notUpdateFields if self.get(f)}
return data
[docs] def addMembers(self, newMembers=[], *args, **kwargs):
"""Adds a list of members to the group
Args:
newMembers (list): list with encoded keys of the members to add to group
"""
data2update = {}
data2update["group"] = {}
# get actual members
groupMembers = [
{"clientKey": i["clientKey"]} for i in self.get("groupMembers", [])
]
data2update["groupMembers"] = groupMembers
# add new members if not already exists in group
newMembers = [
{"clientKey": i}
for i in newMembers
if i not in [c["clientKey"] for c in groupMembers]
]
data2update["groupMembers"].extend(newMembers)
cont_requests = super(MambuGroup, self).update_patch(data2update)
self.connect()
cont_requests += 1
return cont_requests
[docs]class MambuGroups(MambuStruct):
"""A list of Groups from Mambu.
With the default urlfunc, entid argument must be empty at
instantiation time to retrieve all the groups according to any
other filter you send to the urlfunc.
"""
[docs] def __init__(self, urlfunc=mod_urlfunc, entid="", *args, **kwargs):
"""By default, entid argument is empty. That makes perfect
sense: you want several groups, not just one
"""
MambuStruct.__init__(self, urlfunc, entid, *args, **kwargs)
[docs] def __iter__(self):
return MambuStructIterator(self.attrs)
[docs] def convert_dict_to_attrs(self, *args, **kwargs):
"""The trick for iterable Mambu Objects comes here:
You iterate over each element of the responded List from Mambu,
and create a Mambu Group object for each one, initializing them
one at a time, and changing the attrs attribute (which just
holds a list of plain dictionaries) with a MambuGroup just
created.
.. todo:: pass a valid (perhaps default) urlfunc, and its
corresponding id to entid to each MambuGroup, telling
MambuStruct not to connect() by default. It's desirable to
connect at any other further moment to refresh some element in
the list.
"""
for n, c in enumerate(self.attrs):
# ok ok, I'm modifying elements of a list while iterating it. BAD PRACTICE!
try:
params = self.params
except AttributeError:
params = {}
kwargs.update(params)
try:
self.mambugroupclass
except AttributeError:
self.mambugroupclass = MambuGroup
group = self.mambugroupclass(urlfunc=None, entid=None, *args, **kwargs)
group.init(c, *args, **kwargs)
group._MambuStruct__urlfunc = getgroupurl
self.attrs[n] = group