diff --git a/models/__init__.py b/models/__init__.py index 2eccaa7fa7acd5e667f3863f6a7d77bf575f39ca..ded4999fcde1d6501ab2264910d45f70cd5bb317 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -3,4 +3,6 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import base_search_param +from . import calendar_search_param +from . import calendar_write_param from . import cgscop_mobile_utils diff --git a/models/base_search_param.py b/models/base_search_param.py index 2cbfafbf8bf9b2e72ce548558f25727a57fcf852..23ab6907e8a415e5582c414e990622166aca918c 100644 --- a/models/base_search_param.py +++ b/models/base_search_param.py @@ -14,3 +14,4 @@ class CgScopMobileBaseSearchParam(Datamodel): filter = fields.String(required=False, allow_none=False) offset = fields.Integer(required=False, allow_none=False) limit = fields.Integer(required=False, allow_none=False) + ur_id = fields.Integer(required=False, allow_none=False) diff --git a/models/calendar_search_param.py b/models/calendar_search_param.py new file mode 100644 index 0000000000000000000000000000000000000000..30d707369cafb3b679e24e1aa0e87482f4dd40a9 --- /dev/null +++ b/models/calendar_search_param.py @@ -0,0 +1,16 @@ +# © 2022 Le Filament (<https://www.le-filament.com>) +# © 2022 Confédération Générale des Scop (<https://www.les-scop.coop>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from marshmallow import fields + +from odoo.addons.datamodel.core import Datamodel + + +class CgScopMobileCalendarSearchParam(Datamodel): + _name = "cgscopmobile.calendar.search.param" + + id = fields.Integer(required=False, allow_none=False) + user_id = fields.Integer(required=False, allow_none=False) + minDate = fields.DateTime(required=False, allow_none=False) + maxDate = fields.DateTime(required=False, allow_none=False) diff --git a/models/calendar_write_param.py b/models/calendar_write_param.py new file mode 100644 index 0000000000000000000000000000000000000000..5f67db6e21dda15f2e14f5ebe82ed0f60eeda153 --- /dev/null +++ b/models/calendar_write_param.py @@ -0,0 +1,19 @@ +# © 2022 Le Filament (<https://www.le-filament.com>) +# © 2022 Confédération Générale des Scop (<https://www.les-scop.coop>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from marshmallow import fields + +from odoo.addons.datamodel.core import Datamodel + + +class CgScopMobileCalendarWriteParam(Datamodel): + _name = "cgscopmobile.calendar.write.param" + + id = fields.Integer(required=False, allow_none=False) + name = fields.String(required=True, allow_none=False) + description = fields.String(required=True, allow_none=False) + allday = fields.Boolean(required=True, allow_none=False) + duration = fields.Float(required=True, allow_none=False) + start = fields.DateTime(required=True, allow_none=False) + stop = fields.DateTime(required=False, allow_none=False) diff --git a/services/__init__.py b/services/__init__.py index cfe372e114004a9d3221581981e8d9fd23e86bf9..fa69fa6cc174f92a86459961ca6b2ec8c5b9ede9 100644 --- a/services/__init__.py +++ b/services/__init__.py @@ -3,6 +3,8 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import exception_services +from . import user_services from . import cooperative_services from . import contact_services from . import project_services +from . import calendar_services diff --git a/services/calendar_services.py b/services/calendar_services.py new file mode 100644 index 0000000000000000000000000000000000000000..b029fdbd179bdde9df1c860438ee5be42f63cf0d --- /dev/null +++ b/services/calendar_services.py @@ -0,0 +1,165 @@ +# © 2022 Le Filament (<https://www.le-filament.com>) +# © 2022 Confédération Générale des Scop (<https://www.les-scop.coop>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.addons.cgscop_mobile_api.models.calendar_search_param import ( + CgScopMobileCalendarSearchParam, +) +import odoo.addons.cgscop_mobile_api.models.calendar_write_param + +from odoo.addons.base_rest import restapi +from odoo.addons.base_rest_datamodel.restapi import Datamodel +from odoo.addons.component.core import Component + + +class CgScopMobileCalendarServices(Component): + _inherit = ["base.rest.service", "cgscop_mobile.utils"] + _name = "cgscopmobile.calendar.services" + _usage = "calendrier" + _collection = "cgscopmobile.services.coll" + _description = """ + Calendar Mobile API Services + Services developed with the new api provided by base_rest + """ + + @restapi.method( + [(["/<int:id>/get", "/<int:id>"], "GET")], + auth="user", + ) + def get(self, _id): + """ + Get event's information + """ + my_search_param = CgScopMobileCalendarSearchParam() + my_search_param.id = _id + + return self._search(my_search_param, True) + + @restapi.method( + [(["/", "/search"], "POST")], + input_param=Datamodel("cgscopmobile.calendar.search.param"), + auth="user", + ) + def search(self, my_search_param): + """ + Search for events + :param base_search_param: An instance of partner.search.param + """ + return self._search(my_search_param, False) + + @restapi.method( + [(["/write"], "POST")], + input_param=Datamodel("cgscopmobile.calendar.write.param"), + auth="user", + ) + def write(self, my_write_param): + """ + Create a new event + """ + if my_write_param.id <= 0: + return self._create(my_write_param) + else: + return self._update (my_write_param) + + @restapi.method( + [(["/delete/<int:id>"], "GET")], + auth="user", + ) + def delete(self, _id): + """ + Get event's information + """ + self._delete(_id) + res = {"count": 0, "rows": []} + return res + + + # The following method are 'private' and should be never never NEVER call + # from the controller. + + def _create(self, my_write_param): + event = self.env["calendar.event"].create({ + 'name': my_write_param.name, + 'description': my_write_param.name, + 'allday': my_write_param.allday, + 'duration': my_write_param.duration, + 'start': my_write_param.start, + 'stop': my_write_param.stop + }) + return self._to_json(True, event) + + def _update(self, my_write_param): + event = self.env["calendar.event"].browse(my_write_param.id) + if event: + event.write({ + 'name': my_write_param.name, + 'description': my_write_param.name, + 'allday': my_write_param.allday, + 'duration': my_write_param.duration, + 'start': my_write_param.start, + 'stop': my_write_param.stop + }) + return self._to_json(True, event) + + return {} + + def _delete(self, id): + event = self.env["calendar.event"].browse(id) + if event: + event.unlink() + return + + + + def _search(self, my_search_param, detailed): + """ + Search for events + :param calendar_search_param: An instance of calendar.search.param + :param detailed: specify detailed output + """ + domain = [] + if my_search_param.id: + domain.append(("id", "=", my_search_param.id)) + else: + domain.append(("active", "=", True)) + domain.append(("user_id", "=", my_search_param.user_id)) + domain.append(("start", ">=", my_search_param.minDate)) + domain.append(("start", "<=", my_search_param.maxDate)) + + nbrec = self.env["calendar.event"].search_count(domain) + events = self.env["calendar.event"].search(domain) + + rows = [] + res = {"count": nbrec, "rows": rows} + for event in events: + rows.append(self._to_json(detailed, event)) + return res + + def _to_json(self, detailed, event): + """ + Generate output json + :param event: An instance of calendar.event + :param detailed: specify detailed output + """ + + res = { + "id": self.getinteger(event.id), + "name": self.getstring(event.name), + "description": self.getstring(event.description), + "start": self.getstring(event.start), + "allday": self.getboolean(event.allday), + } + + if detailed: + res.update( + { + "stop": self.getstring(event.stop), + "start_date": self.getstring(event.start_date), + "stop_date": self.getstring(event.stop_date), + "start_datetime": self.getstring(event.start_datetime), + "stop_datetime": self.getstring(event.stop_datetime), + "duration": self.getinteger(event.duration), + } + ) + + return res diff --git a/services/contact_services.py b/services/contact_services.py index 5a91969bf00fcef7127981f309cd91192781c68b..b40b9c9e4a928335bdb2228c7e9d8ffc5ed1f063 100644 --- a/services/contact_services.py +++ b/services/contact_services.py @@ -31,6 +31,7 @@ class CgScopMobileContactServices(Component): """ my_search_param = CgScopMobileBaseSearchParam() my_search_param.id = _id + my_search_param.ur_id = 0; return self._search(my_search_param, True) @@ -71,6 +72,10 @@ class CgScopMobileContactServices(Component): domain.append(("type", "=", "contact")) domain.append(("active", "=", True)) + # On regarde si il faut limiter à l'UR + if my_search_param.ur_id != 0: + domain.append(("ur_id", "=", my_search_param.ur_id)) + offset = 0 if my_search_param.offset: offset = my_search_param.offset @@ -79,10 +84,11 @@ class CgScopMobileContactServices(Component): if my_search_param.limit: limit = my_search_param.limit + nbrec = self.env["res.partner"].search_count(domain) partners = self.env["res.partner"].search(domain, limit=limit, offset=offset) rows = [] - res = {"count": len(partners), "rows": rows} + res = {"count": nbrec, "rows": rows} for partner in partners: rows.append(self._to_json(detailed, partner)) return res @@ -98,6 +104,8 @@ class CgScopMobileContactServices(Component): "id": self.getinteger(partner.id), "name": self.getstring(partner.name), "email": self.getstring(partner.email), + "phone": self.getstring(partner.phone), + "image": partner.image.decode("utf-8") if partner.image else None, } if detailed: @@ -107,7 +115,6 @@ class CgScopMobileContactServices(Component): "lastname": self.getstring(partner.lastname), "firstname": self.getstring(partner.firstname), "mobile": self.getstring(partner.mobile), - "phone": self.getstring(partner.phone), "extranet_access": self.getboolean(partner.extranet_access), "extranet_update_company": self.getboolean( partner.extranet_update_company diff --git a/services/cooperative_services.py b/services/cooperative_services.py index a3aa70dd3936c6ed2ab4cd752088fc14181c52e6..09d1bb736c868f94050967d6b4eb0e29bc0e830c 100644 --- a/services/cooperative_services.py +++ b/services/cooperative_services.py @@ -31,6 +31,7 @@ class CgScopMobileCooperativeServices(Component): """ my_search_param = CgScopMobileBaseSearchParam() my_search_param.id = _id + my_search_param.ur_id = 0; return self._search(my_search_param, True) @@ -73,6 +74,10 @@ class CgScopMobileCooperativeServices(Component): domain.append(("membership_status", "=", "member")) domain.append(("active", "=", True)) + # On regarde si il faut limiter à l'UR + if my_search_param.ur_id != 0: + domain.append(("ur_id", "=", my_search_param.ur_id)) + offset = 0 if my_search_param.offset: offset = my_search_param.offset @@ -81,10 +86,11 @@ class CgScopMobileCooperativeServices(Component): if my_search_param.limit: limit = my_search_param.limit + nbrec = self.env["res.partner"].search_count(domain) partners = self.env["res.partner"].search(domain, limit=limit, offset=offset) rows = [] - res = {"count": len(partners), "rows": rows} + res = {"count": nbrec, "rows": rows} for partner in partners: rows.append(self._to_json(detailed, partner)) return res @@ -101,6 +107,8 @@ class CgScopMobileCooperativeServices(Component): "name": self.getstring(partner.name), "sigle": self.getstring(partner.sigle), "member_number": self.getstring(partner.member_number), + "image": partner.image.decode("utf-8") if partner.image else None, + } if detailed: @@ -108,6 +116,7 @@ class CgScopMobileCooperativeServices(Component): { "street": self.getstring(partner.street), "street2": self.getstring(partner.street2), + "street3": self.getstring(partner.street3), "zip": self.getstring(partner.zip), "city": self.getstring(partner.city), "zip_departement": self.getstring(partner.zip_departement), diff --git a/services/project_services.py b/services/project_services.py index a84f14a490c9f405460122319ec436dc96e7b5cf..5f7f0d728f2eb0b63283ebb4acc98243178b3e02 100644 --- a/services/project_services.py +++ b/services/project_services.py @@ -31,6 +31,7 @@ class CgScopMobileProjectServices(Component): """ my_search_param = CgScopMobileBaseSearchParam() my_search_param.id = _id + my_search_param.ur_id = 0; return self._search(my_search_param, True) @@ -85,6 +86,10 @@ class CgScopMobileProjectServices(Component): ) ) + # On regarde si il faut limiter à l'UR + if my_search_param.ur_id != 0: + domain.append(("ur_id", "=", my_search_param.ur_id)) + offset = 0 if my_search_param.offset: offset = my_search_param.offset @@ -93,10 +98,11 @@ class CgScopMobileProjectServices(Component): if my_search_param.limit: limit = my_search_param.limit + nbrec = self.env["res.partner"].search_count(domain) partners = self.env["res.partner"].search(domain, limit=limit, offset=offset) rows = [] - res = {"count": len(partners), "rows": rows} + res = {"count": nbrec, "rows": rows} for partner in partners: rows.append(self._to_json(detailed, partner)) return res @@ -112,6 +118,9 @@ class CgScopMobileProjectServices(Component): "id": self.getinteger(partner.id), "name": self.getstring(partner.name), "project_status": self.getstring(partner.project_status), + "member_number": self.getstring(partner.member_number), + "image": partner.image.decode("utf-8") if partner.image else None, + } if detailed: @@ -120,6 +129,7 @@ class CgScopMobileProjectServices(Component): "sigle": self.getstring(partner.sigle), "street": self.getstring(partner.street), "street2": self.getstring(partner.street2), + "street3": self.getstring(partner.street2), "zip": self.getstring(partner.zip), "city": self.getstring(partner.city), "zip_departement": self.getstring(partner.zip_departement), diff --git a/services/user_services.py b/services/user_services.py new file mode 100644 index 0000000000000000000000000000000000000000..de2e7889123a091aa60fc5a2ecc1a57cb0703649 --- /dev/null +++ b/services/user_services.py @@ -0,0 +1,85 @@ +# © 2022 Le Filament (<https://www.le-filament.com>) +# © 2022 Confédération Générale des Scop (<https://www.les-scop.coop>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.addons.cgscop_mobile_api.models.base_search_param import ( + CgScopMobileBaseSearchParam, +) + +from odoo.addons.base_rest import restapi +from odoo.addons.base_rest_datamodel.restapi import Datamodel +from odoo.addons.component.core import Component + + +class CgScopMobileUserServices(Component): + _inherit = ["base.rest.service", "cgscop_mobile.utils"] + _name = "cgscopmobile.user.services" + _usage = "user" + _collection = "cgscopmobile.services.coll" + _description = """ + Partner Mobile API Services + Services developed with the new api provided by base_rest + """ + + @restapi.method( + [(["/<int:id>/get", "/<int:id>"], "GET")], + auth="user", + ) + def get(self, _id): + """ + Get user's information + """ + + return self._get(_id) + + + # The following method are 'private' and should be never never NEVER call + # from the controller. + + def _get(self, userId): + """ + Search for user + """ + user = self.env["res.users"].browse(userId) + + rows = [] + if not user: + return {"count": 0, "rows": rows} + else: + rows.append(self._to_json(user)) + return {"count": 1, "rows": rows} + + def _to_json(self, user): + """ + Generate output json + :param partner: An instance of user + """ + + res = { + "id": self.getinteger(user.id), + "login": self.getstring(user.login), + } + + res["ur"] = self.getnested(user.ur_id) + res["partner"] = self.getpartner(user.partner_id) + + return res + + def getpartner(self, partner): + res = {} + if partner: + res.update( + { + "id": self.getinteger(partner.id), + "name": self.getstring(partner.name), + "title": self.getnested(partner.title), + "lastname": self.getstring(partner.lastname), + "firstname": self.getstring(partner.firstname), + "mobile": self.getstring(partner.mobile), + "phone": self.getstring(partner.phone), + "image": partner.image.decode("utf-8") if partner.image else None, + } + ) + else: + res.update({"id": 0, "name": ""}) + return res