From d157227a9c075f689f76af5ad47a9215a68dbdf5 Mon Sep 17 00:00:00 2001 From: EdgarRetes Date: Wed, 6 Nov 2024 11:10:43 -0600 Subject: [PATCH] [ADD] fieldservice_mobile --- fieldservice_mobile/README.rst | 48 ++++++++ fieldservice_mobile/__init__.py | 3 + fieldservice_mobile/__manifest__.py | 38 +++++++ fieldservice_mobile/data/base_automation.xml | 49 ++++++++ fieldservice_mobile/data/feature_line.xml | 107 ++++++++++++++++++ fieldservice_mobile/data/feature_mapping.xml | 28 +++++ fieldservice_mobile/data/server_actions.xml | 103 +++++++++++++++++ fieldservice_mobile/models/__init__.py | 10 ++ .../models/fsm_mobile_feature_line.py | 15 +++ .../models/fsm_mobile_feature_mapping.py | 96 ++++++++++++++++ fieldservice_mobile/models/fsm_order.py | 98 ++++++++++++++++ fieldservice_mobile/models/fsm_stage.py | 12 ++ .../models/fsm_stage_history.py | 16 +++ fieldservice_mobile/models/ir_attachment.py | 80 +++++++++++++ .../models/res_config_settings.py | 18 +++ fieldservice_mobile/models/res_users.py | 27 +++++ fieldservice_mobile/pyproject.toml | 3 + .../security/fieldservice_mobile_security.xml | 7 ++ .../security/ir.model.access.csv | 35 ++++++ fieldservice_mobile/security/ir_rule.xml | 14 +++ .../static/description/icon.png | Bin 0 -> 29789 bytes .../static/description/icon.svg | 1 + fieldservice_mobile/views/fsm_order_view.xml | 35 ++++++ fieldservice_mobile/views/fsm_stage_view.xml | 13 +++ .../views/mobile_feature_line.xml | 17 +++ .../views/mobile_feature_mapping.xml | 80 +++++++++++++ .../views/res_config_settings.xml | 33 ++++++ 27 files changed, 986 insertions(+) create mode 100644 fieldservice_mobile/README.rst create mode 100644 fieldservice_mobile/__init__.py create mode 100644 fieldservice_mobile/__manifest__.py create mode 100644 fieldservice_mobile/data/base_automation.xml create mode 100644 fieldservice_mobile/data/feature_line.xml create mode 100644 fieldservice_mobile/data/feature_mapping.xml create mode 100644 fieldservice_mobile/data/server_actions.xml create mode 100644 fieldservice_mobile/models/__init__.py create mode 100644 fieldservice_mobile/models/fsm_mobile_feature_line.py create mode 100644 fieldservice_mobile/models/fsm_mobile_feature_mapping.py create mode 100644 fieldservice_mobile/models/fsm_order.py create mode 100644 fieldservice_mobile/models/fsm_stage.py create mode 100644 fieldservice_mobile/models/fsm_stage_history.py create mode 100644 fieldservice_mobile/models/ir_attachment.py create mode 100644 fieldservice_mobile/models/res_config_settings.py create mode 100644 fieldservice_mobile/models/res_users.py create mode 100644 fieldservice_mobile/pyproject.toml create mode 100644 fieldservice_mobile/security/fieldservice_mobile_security.xml create mode 100644 fieldservice_mobile/security/ir.model.access.csv create mode 100644 fieldservice_mobile/security/ir_rule.xml create mode 100644 fieldservice_mobile/static/description/icon.png create mode 100644 fieldservice_mobile/static/description/icon.svg create mode 100644 fieldservice_mobile/views/fsm_order_view.xml create mode 100644 fieldservice_mobile/views/fsm_stage_view.xml create mode 100644 fieldservice_mobile/views/mobile_feature_line.xml create mode 100644 fieldservice_mobile/views/mobile_feature_mapping.xml create mode 100644 fieldservice_mobile/views/res_config_settings.xml diff --git a/fieldservice_mobile/README.rst b/fieldservice_mobile/README.rst new file mode 100644 index 0000000000..b7f0c7ad99 --- /dev/null +++ b/fieldservice_mobile/README.rst @@ -0,0 +1,48 @@ +.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 + +==================== +Field Service Mobile +==================== + +This module is manage FSM mobile stages based on configuration. + +Configuration +============= + +To configure this module, you need to: + +* Go to Field Service > Configuration > Stages. +* Check Display in Mobile for display stage in FSM Mobile. +* Check Display in Odoo for display stage in Odoo FSM Order. +* Select a server action based on Stages. + +* Manage domain on Automated Actions based on Stage sequence. + +For Example:- If the Started stage sequence is 6. + +* Go to Settings > Automated Actions > FSM Order Started Stage Update > Apply on > [["stage_id.sequence","=",6]] + +Features on the mobile application will be visible depending on the groups set on this model. + +Usage +============= +1) Navigate to the "Field Service" application +2) Under menu item "Configuration", select "FSM Mobile Features" +3) Select Installed Modules for FSM Mobile Dynamic Menu and it's records +4) Select a feature and add/remove groups + +Credits +======= + +* Open Source Integrators +* Serpent Consulting Services Pvt. Ltd. + +Contributors +~~~~~~~~~~~~ + +* Wolfgang Hall +* Sandip Mangukiya +* Serpent Consulting Services Pvt. Ltd. +* Ammar Officewala diff --git a/fieldservice_mobile/__init__.py b/fieldservice_mobile/__init__.py new file mode 100644 index 0000000000..69f7babdfb --- /dev/null +++ b/fieldservice_mobile/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/fieldservice_mobile/__manifest__.py b/fieldservice_mobile/__manifest__.py new file mode 100644 index 0000000000..f9247483fa --- /dev/null +++ b/fieldservice_mobile/__manifest__.py @@ -0,0 +1,38 @@ +# Copyright (C) 2020 Open Source Integrators +# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Field Service - Mobile", + "summary": "Field Service Mobile Backend Support.", + "license": "AGPL-3", + "version": "18.0.1.0.0", + "category": "Field Service", + "author": "Open Source Integrators, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/field-service", + "depends": [ + "fieldservice_stage_server_action", + "stock", + "analytic", + "maintenance", + "fieldservice_vehicle", + "fieldservice_sale", + "calendar", + ], + "data": [ + "security/ir_rule.xml", + "security/ir.model.access.csv", + "security/fieldservice_mobile_security.xml", + "data/server_actions.xml", + "data/base_automation.xml", + "data/feature_line.xml", + "data/feature_mapping.xml", + "views/res_config_settings.xml", + "views/fsm_stage_view.xml", + "views/fsm_order_view.xml", + "views/mobile_feature_mapping.xml", + "views/mobile_feature_line.xml", + ], + "development_status": "Beta", + "maintainers": ["wolfhall"], +} diff --git a/fieldservice_mobile/data/base_automation.xml b/fieldservice_mobile/data/base_automation.xml new file mode 100644 index 0000000000..fadc60d6c9 --- /dev/null +++ b/fieldservice_mobile/data/base_automation.xml @@ -0,0 +1,49 @@ + + + FSM Order Started Stage Update + + on_write + + [["stage_id.sequence", "=", 6]] + + + + + FSM Order Break Stage Update + + on_write + + [["stage_id.sequence", "=", 7]] + + + + + FSM Order Resume Stage Update + + on_write + + [["stage_id.sequence", "=", 8]] + + + + + FSM Order Completed Stage Update + + on_write + + [["stage_id.sequence", "=", 9]] + + + diff --git a/fieldservice_mobile/data/feature_line.xml b/fieldservice_mobile/data/feature_line.xml new file mode 100644 index 0000000000..68285347b5 --- /dev/null +++ b/fieldservice_mobile/data/feature_line.xml @@ -0,0 +1,107 @@ + + + + Location + LOC + + + + Contact + CON + + + + Notes + NOT + + + + Chatter + CHA + + + + Documents + DOC + + + + Pictures + PIC + + + + Timesheets + TIM + + + + Signature + SIG + + + + Equipment + EQU + + + + Pickup/Delivery + DEL + + + + Sale Order Lines + SOL + + + + Durations + DUR + + + + Stock Requests + STO + + + diff --git a/fieldservice_mobile/data/feature_mapping.xml b/fieldservice_mobile/data/feature_mapping.xml new file mode 100644 index 0000000000..08f5a9fd57 --- /dev/null +++ b/fieldservice_mobile/data/feature_mapping.xml @@ -0,0 +1,28 @@ + + + + Default FSM Mobile Feature Mapping + + + + diff --git a/fieldservice_mobile/data/server_actions.xml b/fieldservice_mobile/data/server_actions.xml new file mode 100644 index 0000000000..196f81caf5 --- /dev/null +++ b/fieldservice_mobile/data/server_actions.xml @@ -0,0 +1,103 @@ + + + FSM Order Started Stage Update Action + + code + + for rec in records: + stage_rec = env['fsm.stage.history'].search([('order_id', '=', rec.id)], order='id desc', limit=1) + call_it = False + if not stage_rec: + call_it = True + if stage_rec.stage_id != rec.stage_id: + call_it = True + if call_it and rec.stage_id.action_id: + rec.write({ + 'date_start': datetime.datetime.now(), + 'fsm_stage_history_ids': [(0, 0, { + 'start_datetime': datetime.datetime.now(), + 'stage_id': rec.stage_id.id, + 'duration': 0.0, + 'total_duration': 0.0, + })] + }) + + + + + FSM Order Break Stage Update Action + + code + + for rec in records: + stage_rec = env['fsm.stage.history'].search([('order_id', '=', rec.id)], order='id desc', limit=1) + call_it = False + if not stage_rec: + call_it = True + if stage_rec.stage_id != rec.stage_id: + call_it = True + if call_it and rec.stage_id.action_id: + delta = datetime.datetime.now() - stage_rec.start_datetime + duration = round((delta.total_seconds() / 3600), 2) + rec.write({ + 'fsm_stage_history_ids': [(0, 0, { + 'start_datetime': datetime.datetime.now(), + 'stage_id': rec.stage_id.id, + 'duration': duration, + 'total_duration': round((duration + stage_rec.total_duration), 2), + })] + }) + + + + + FSM Order Resume Stage Update Action + + code + + for rec in records: + stage_rec = env['fsm.stage.history'].search([('order_id', '=', rec.id)], order='id desc', limit=1) + call_it = False + if not stage_rec: + call_it = True + if stage_rec.stage_id != rec.stage_id: + call_it = True + if call_it and rec.stage_id.action_id: + rec.write({ + 'fsm_stage_history_ids': [(0, 0, { + 'start_datetime': datetime.datetime.now(), + 'stage_id': rec.stage_id.id, + 'duration': 0.0, + 'total_duration': round((rec.duration + stage_rec.total_duration), 2), + })] + }) + + + + + FSM Order Completed Stage Update Action + + code + + for rec in records: + stage_rec = env['fsm.stage.history'].search([('order_id', '=', rec.id)], order='id desc', limit=1) + call_it = False + if not stage_rec: + call_it = True + if stage_rec.stage_id != rec.stage_id: + call_it = True + if call_it and rec.stage_id.action_id: + delta = datetime.datetime.now() - stage_rec.start_datetime + duration = round((delta.total_seconds() / 3600), 2) + rec.write({ + 'date_end': datetime.datetime.now(), + 'fsm_stage_history_ids': [(0, 0, { + 'start_datetime': datetime.datetime.now(), + 'stage_id': rec.stage_id.id, + 'duration': duration, + 'total_duration': round((duration + stage_rec.total_duration), 2), + })] + }) + + + diff --git a/fieldservice_mobile/models/__init__.py b/fieldservice_mobile/models/__init__.py new file mode 100644 index 0000000000..2d76926f19 --- /dev/null +++ b/fieldservice_mobile/models/__init__.py @@ -0,0 +1,10 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import fsm_stage +from . import fsm_order +from . import fsm_stage_history +from . import res_config_settings +from . import res_users +from . import ir_attachment +from . import fsm_mobile_feature_mapping +from . import fsm_mobile_feature_line diff --git a/fieldservice_mobile/models/fsm_mobile_feature_line.py b/fieldservice_mobile/models/fsm_mobile_feature_line.py new file mode 100644 index 0000000000..5a22db062c --- /dev/null +++ b/fieldservice_mobile/models/fsm_mobile_feature_line.py @@ -0,0 +1,15 @@ +# Copyright (C) 2022 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import fields, models + + +class FSMMobileFeatureLine(models.Model): + _name = "fsm.mobile.feature.line" + _description = "FSM Mobile Feature Line" + + feature_id = fields.Many2one("fsm.mobile.feature.mapping", string="Feature Mapping") + name = fields.Char(string="Feature Name") + group_ids = fields.Many2many("res.groups", string="Groups") + code = fields.Char() diff --git a/fieldservice_mobile/models/fsm_mobile_feature_mapping.py b/fieldservice_mobile/models/fsm_mobile_feature_mapping.py new file mode 100644 index 0000000000..2e9742231c --- /dev/null +++ b/fieldservice_mobile/models/fsm_mobile_feature_mapping.py @@ -0,0 +1,96 @@ +# Copyright (C) 2022 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class FSMMobileFeatureMapping(models.Model): + _name = "fsm.mobile.feature.mapping" + _description = "FSM Mobile Feature Mapping" + + name = fields.Char(string="Mapping Name") + installed_module_ids = fields.Many2many( + "ir.module.module", + string="Installed Modules", + domain=[("state", "=", "installed")], + ) + feature_line_ids = fields.One2many( + "fsm.mobile.feature.line", "feature_id", string="Mobile Feature Lines" + ) + company_id = fields.Many2one( + "res.company", + string="Company", + default=lambda self: self.env.user.company_id.id, + ) + state = fields.Selection( + [("draft", "Draft"), ("active", "Active")], + default="draft", + ) + + @api.depends("name") + def _compute_display_name(self): + for record in self: + record.display_name = record.name + + def set_to_draft(self): + """Set to draft state.""" + for rec in self: + rec.state = "draft" + + def set_to_active(self): + """Set to active state.""" + record = self.search([("state", "=", "active")]) + if record: + raise UserError( + _("Active record is already exits in FSM Mobile Feature Mapping!") + ) + for rec in self: + rec.state = "active" + + def unlink(self): + """Override unlink method for can't delete active FSM Mobile Feature Mapping.""" + for rec in self: + if rec.state == "active": + raise UserError( + _( + "You can't delete FSM Mobile Feature Mapping which is in" + " an active state!" + ) + ) + return super().unlink() + + @api.model + def get_fsm_mobile_feature_mapping_values(self, user_id): + fsm_feature_mapping_obj = self.env["fsm.mobile.feature.mapping"] + fsm_feature_mapping_rec = fsm_feature_mapping_obj.search( + [("state", "=", "active")], limit=1 + ) + params_dict = {} + feature_mapping_list = [] + installed_modules_list = [] + for f_line_rec in fsm_feature_mapping_rec.feature_line_ids: + group_ids = f_line_rec.group_ids.sudo().filtered( + lambda line: user_id in line.users.ids + ) + if group_ids: + feature_mapping_list.append( + { + "id": f_line_rec.id, + "name": f_line_rec.name, + "group_ids": group_ids.ids, + "code": f_line_rec.code, + } + ) + for inst_module in fsm_feature_mapping_rec.sudo().installed_module_ids: + installed_modules_list.append( + {"id": inst_module.id, "name": inst_module.name} + ) + if feature_mapping_list and installed_modules_list: + params_dict.update( + { + "feature_mapping": feature_mapping_list, + "installed_modules": installed_modules_list, + } + ) + return params_dict diff --git a/fieldservice_mobile/models/fsm_order.py b/fieldservice_mobile/models/fsm_order.py new file mode 100644 index 0000000000..a7ff81bc39 --- /dev/null +++ b/fieldservice_mobile/models/fsm_order.py @@ -0,0 +1,98 @@ +# Copyright (C) 2020 Open Source Integrators +# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class FSMOrder(models.Model): + _inherit = "fsm.order" + + @api.depends("date_start", "date_end") + def _compute_duration(self): + res = super()._compute_duration() + for rec in self: + if rec.fsm_stage_history_ids and rec.date_end: + stage_rec = self.env["fsm.stage.history"].search( + [("order_id", "=", rec.id)], order="id desc", limit=1 + ) + rec.duration = stage_rec.total_duration + elif not rec.date_end: + rec.duration = 0.0 + return res + + @api.depends("sale_id.transaction_ids.state") + def _compute_payment_state(self): + for rec in self: + payment_state = "not_paid" + paid_payment_check_list = [ + True if paym.state == "done" else False + for paym in rec.sale_id.transaction_ids + ] + if rec.sale_id.transaction_ids: + if all(paid_payment_check_list): + payment_state = "paid" + elif rec.sale_id.transaction_ids.filtered( + lambda r: r.state == "pending" + ): + payment_state = "pending" + rec.payment_state = payment_state + + duration = fields.Float( + string="Actual duration", + compute=_compute_duration, + help="Actual duration in hours", + store=True, + ) + fsm_stage_history_ids = fields.One2many( + "fsm.stage.history", "order_id", string="Stage History" + ) + payment_state = fields.Selection( + [("not_paid", "Not Paid"), ("paid", "Paid"), ("pending", "Pending")], + compute="_compute_payment_state", + store=True, + ) + + @api.model + def create_fsm_attachment(self, name, datas, res_model, res_id): + if res_model == "fsm.order": + attachment = ( + self.env["ir.attachment"] + .sudo() + .create( + { + "name": name, + "datas": datas, + "res_model": res_model, + "res_id": res_id, + } + ) + ) + return attachment.id + + @api.model + def generate_so_payment_link(self, fsm_order_id): + order = self.env["fsm.order"].browse(fsm_order_id) + if not order.sale_id: + return { + "payment_status": False, + "message": "The sale order is not found related to this FSO.", + } + payment_link_id = ( + self.env["payment.link.wizard"] + .with_context( + default_res_model="sale.order", default_res_id=order.sale_id.id + ) + .sudo() + .create( + { + "res_model": "sale.order", + "res_id": order.sale_id.id, + "amount": order.sale_id.amount_total, + "currency_id": order.sale_id.currency_id.id, + "partner_id": order.sale_id.partner_id.id, + "description": order.sale_id.name, + } + ) + ) + return {"payment_status": True, "payment_link": payment_link_id.link} diff --git a/fieldservice_mobile/models/fsm_stage.py b/fieldservice_mobile/models/fsm_stage.py new file mode 100644 index 0000000000..a141796661 --- /dev/null +++ b/fieldservice_mobile/models/fsm_stage.py @@ -0,0 +1,12 @@ +# Copyright (C) 2020 Open Source Integrators +# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class FSMStage(models.Model): + _inherit = "fsm.stage" + + is_display_in_mobile = fields.Boolean("Display in Mobile", default=False) + is_display_in_odoo = fields.Boolean("Display in Odoo", default=True) diff --git a/fieldservice_mobile/models/fsm_stage_history.py b/fieldservice_mobile/models/fsm_stage_history.py new file mode 100644 index 0000000000..0bc8d1e881 --- /dev/null +++ b/fieldservice_mobile/models/fsm_stage_history.py @@ -0,0 +1,16 @@ +# Copyright (C) 2020 Open Source Integrators +# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class FsmStageHistory(models.Model): + _name = "fsm.stage.history" + _description = "FSM Stage History" + + order_id = fields.Many2one("fsm.order", string="FSM Order") + start_datetime = fields.Datetime("Start Date&time") + stage_id = fields.Many2one("fsm.stage") + duration = fields.Float() + total_duration = fields.Float() diff --git a/fieldservice_mobile/models/ir_attachment.py b/fieldservice_mobile/models/ir_attachment.py new file mode 100644 index 0000000000..f5d96f1e6f --- /dev/null +++ b/fieldservice_mobile/models/ir_attachment.py @@ -0,0 +1,80 @@ +# Copyright (C) 2021 Open Source Integrators +# Copyright (C) 2021 Serpent Consulting Services Pvt. Ltd. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from collections import defaultdict + +from odoo import _, api, models +from odoo.exceptions import AccessError + + +class IrAttachment(models.Model): + _inherit = "ir.attachment" + + """Overwrite check method for allow portal user to read attachment""" + + @api.model + def check(self, mode, values=None): + """Restricts the access to an ir.attachment, according to referred mode""" + if self.env.is_superuser(): + return True + # Always require an internal user (aka, employee) to access to a attachment + + # if not (self.env.is_admin() or + # self.env.user.has_group('base.group_user')): + # raise AccessError(_("Sorry, you are not + # allowed to access this document.")) + + # collect the records to check (by model) + model_ids = defaultdict(set) # {model_name: set(ids)} + if self: + # DLE P173: `test_01_portal_attachment` + self.env["ir.attachment"].flush_model( + ["res_model", "res_id", "public", "res_field"] + ) + self._cr.execute( + """SELECT res_model, res_id, create_uid, public, res_field + FROM ir_attachment WHERE id IN %s""", + [tuple(self.ids)], + ) + for ( + res_model, + res_id, + _create_uid, + public, + res_field, + ) in self._cr.fetchall(): + if not self.env.is_system() and res_field: + raise AccessError( + _("Sorry, you are not allowed to access this document.") + ) + if public and mode == "read": + continue + if not (res_model and res_id): + continue + model_ids[res_model].add(res_id) + if values and values.get("res_model") and values.get("res_id"): + model_ids[values["res_model"]].add(values["res_id"]) + + # check access rights on the records + for res_model, res_ids in model_ids.items(): + # ignore attachments that are not attached to a resource anymore + # when checking access rights (resource was deleted but attachment + # was not) + if res_model not in self.env: + continue + if ( + res_model == "res.users" + and len(res_ids) == 1 + and self.env.uid == list(res_ids)[0] + ): + # by default a user cannot write on itself, + # despite the list of writeable fields + # e.g. in the case of a user inserting an image into his image signature + # we need to bypass this check which would needlessly throw us away + continue + records = self.env[res_model].browse(res_ids).exists() + # For related models, check if we can write to the model, as unlinking + # and creating attachments can be seen as an update to the model + access_mode = "write" if mode in ("create", "unlink") else mode + records.check_access_rights(access_mode) + records.check_access_rule(access_mode) diff --git a/fieldservice_mobile/models/res_config_settings.py b/fieldservice_mobile/models/res_config_settings.py new file mode 100644 index 0000000000..6a4ccad3f2 --- /dev/null +++ b/fieldservice_mobile/models/res_config_settings.py @@ -0,0 +1,18 @@ +# Copyright (C) 2020 Open Source Integrators +# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + fsm_allow_portal_view_move_qty = fields.Boolean( + string="Allow portal user to view stock move quantities", + config_parameter="fieldservice_mobile.fsm_allow_portal_view_move_qty", + ) + fsm_allow_portal_update_move_qty = fields.Boolean( + string="Allow portal user update of stock move quantities", + config_parameter="fieldservice_mobile.fsm_allow_portal_update_move_qty", + ) diff --git a/fieldservice_mobile/models/res_users.py b/fieldservice_mobile/models/res_users.py new file mode 100644 index 0000000000..b21eba1285 --- /dev/null +++ b/fieldservice_mobile/models/res_users.py @@ -0,0 +1,27 @@ +# Copyright (C) 2020 Open Source Integrators +# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class Users(models.Model): + _inherit = "res.users" + + @api.model + def get_portal_config_values(self, config_parameters=False): + if not config_parameters: + config_parameters = [] + params_dict = {} + group_params = [ + "fieldservice_mobile.fsm_allow_portal_view_move_qty", + "fieldservice_mobile.fsm_allow_portal_update_move_qty", + "fieldservice_mobile.fsm_allow_portal_validate_move_qty", + "fieldservice_sale_order_line.fsm_allow_portal_view_sol_qty", + "fieldservice_sale_order_line.fsm_allow_portal_update_sol_qty", + ] + for config_param in config_parameters: + if config_param in group_params: + params = self.env["ir.config_parameter"].sudo() + params_dict.update({config_param: bool(params.get_param(config_param))}) + return params_dict diff --git a/fieldservice_mobile/pyproject.toml b/fieldservice_mobile/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/fieldservice_mobile/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/fieldservice_mobile/security/fieldservice_mobile_security.xml b/fieldservice_mobile/security/fieldservice_mobile_security.xml new file mode 100644 index 0000000000..4605c52a30 --- /dev/null +++ b/fieldservice_mobile/security/fieldservice_mobile_security.xml @@ -0,0 +1,7 @@ + + + User can only see own feature mapping + + [('company_id.id','=',user.company_id.id)] + + diff --git a/fieldservice_mobile/security/ir.model.access.csv b/fieldservice_mobile/security/ir.model.access.csv new file mode 100644 index 0000000000..d4838088d5 --- /dev/null +++ b/fieldservice_mobile/security/ir.model.access.csv @@ -0,0 +1,35 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_res_territory_portal,access.res.territory.portal,base_territory.model_res_territory,base.group_portal,1,0,0,0 +access_res_branch_portal,access.res.branch.portal,base_territory.model_res_branch,base.group_portal,1,0,0,0 +access_res_district_portal,access.res.district.portal,base_territory.model_res_district,base.group_portal,1,0,0,0 +access_res_region_portal,access.res.region.portal,base_territory.model_res_region,base.group_portal,1,0,0,0 +access_fsm_stage_portal,access.fsm.stage.portal,fieldservice.model_fsm_stage,base.group_portal,1,0,0,0 +access_fsm_tag_portal,access.fsm.tag.portal,fieldservice.model_fsm_tag,base.group_portal,1,0,0,0 +access_fsm_person_portal,access.fsm.person.portal,fieldservice.model_fsm_person,base.group_portal,1,1,0,0 +access_fsm_location_portal,access.fsm.location.portal,fieldservice.model_fsm_location,base.group_portal,1,0,0,0 +access_fsm_order_portal,access.fsm.order.portal,fieldservice.model_fsm_order,base.group_portal,1,1,0,0 +access_fsm_equipment_portal,access.fsm.equipment.portal,fieldservice.model_fsm_equipment,base.group_portal,1,0,0,0 +access_fsm_category_portal,access.fsm.category.portal,fieldservice.model_fsm_category,base.group_portal,1,0,0,0 +access_fsm_template_portal,access.fsm.template.portal,fieldservice.model_fsm_template,base.group_portal,1,0,0,0 +access_fsm_team_portal,access.fsm.team.portal,fieldservice.model_fsm_team,base.group_portal,1,0,0,0 +access_fsm_location_person_portal,access.fsm.location.person.portal,fieldservice.model_fsm_location_person,base.group_portal,1,0,0,0 +access_fsm_order_type_portal,access.fsm.order.type.portal,fieldservice.model_fsm_order_type,base.group_portal,1,0,0,0 +access_fsm_stage_history_fsm_user,fsm.stage.history.user,model_fsm_stage_history,fieldservice.group_fsm_user,1,1,1,0 +access_fsm_stage_history_fsm_manager,fsm.stage.history.manager,model_fsm_stage_history,fieldservice.group_fsm_manager,1,1,1,1 +access_fsm_stage_history_portal,fsm.stage.history.portal,model_fsm_stage_history,base.group_portal,1,1,1,0 +stock.access_stock_move_line_portal,stock.move.line portal,stock.model_stock_move_line,base.group_portal,1,0,0,0 +access_stock_location_portal,access.stock.location.portal,stock.model_stock_location,base.group_portal,1,0,0,0 +access_stock_warehouse_portal,access.stock.warehouse.portal,stock.model_stock_warehouse,base.group_portal,1,0,0,0 +access_account_analytic_line_portal,access.account.analytic.line.portal,analytic.model_account_analytic_line,base.group_portal,1,0,0,0 +access_stock_picking_type_portal,access.stock.picking.type.portal,stock.model_stock_picking_type,base.group_portal,1,0,0,0 +access_fsm_vehicle_portal,access.fsm.vehicle.portal,fieldservice_vehicle.model_fsm_vehicle,base.group_portal,1,0,0,0 +access_maintenance_equipment_portal,access.maintenance.equipment.portal,maintenance.model_maintenance_equipment,base.group_portal,1,0,0,0 +access_ir_attachment_portal,access.ir.attachment.portal,base.model_ir_attachment,base.group_portal,1,0,0,0 +access_mobile_feature_mapping_user,mobile.feature.user,fieldservice_mobile.model_fsm_mobile_feature_mapping,base.group_user,1,0,0,0 +access_mobile_feature_mapping_manager,mobile.feature.manager,fieldservice_mobile.model_fsm_mobile_feature_mapping,fieldservice.group_fsm_manager,1,1,1,1 +access_mobile_feature_line_user,mobile.feature.line.user,fieldservice_mobile.model_fsm_mobile_feature_line,base.group_user,1,0,0,0 +access_mobile_feature_line_manager,mobile.feature.line.manager,fieldservice_mobile.model_fsm_mobile_feature_line,fieldservice.group_fsm_manager,1,1,1,1 +access_mobile_feature_line_portal,mobile.feature.line.portal,fieldservice_mobile.model_fsm_mobile_feature_line,base.group_portal,1,0,0,0 +access_mobile_feature_mapping_user_portal,mobile.feature.user.portal,fieldservice_mobile.model_fsm_mobile_feature_mapping,base.group_portal,1,0,0,0 +access_mobile_feature_mapping_manager_portal,mobile.feature.manager.portal,fieldservice_mobile.model_fsm_mobile_feature_mapping,base.group_portal,1,0,0,0 +access_calendar_recurrence_portal,access_calendar_recurrence_portal,calendar.model_calendar_recurrence,base.group_portal,1,0,0,0 diff --git a/fieldservice_mobile/security/ir_rule.xml b/fieldservice_mobile/security/ir_rule.xml new file mode 100644 index 0000000000..5c21251633 --- /dev/null +++ b/fieldservice_mobile/security/ir_rule.xml @@ -0,0 +1,14 @@ + + + Portal Partner multi-company + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + + + + diff --git a/fieldservice_mobile/static/description/icon.png b/fieldservice_mobile/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e3757caa15401e8ed72d8f824c645151bdf8536a GIT binary patch literal 29789 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 literal 0 HcmV?d00001 diff --git a/fieldservice_mobile/static/description/icon.svg b/fieldservice_mobile/static/description/icon.svg new file mode 100644 index 0000000000..c27c090fda --- /dev/null +++ b/fieldservice_mobile/static/description/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/fieldservice_mobile/views/fsm_order_view.xml b/fieldservice_mobile/views/fsm_order_view.xml new file mode 100644 index 0000000000..92354188dc --- /dev/null +++ b/fieldservice_mobile/views/fsm_order_view.xml @@ -0,0 +1,35 @@ + + + view.fsm.order.inherit.mobile + fsm.order + + + + [('stage_type', '=', 'order'), + ('team_ids', 'in', (team_id, False)), + ('is_display_in_odoo', '=', True)] + + + float_time + + + + + + + + + + + + + + + + + + + diff --git a/fieldservice_mobile/views/fsm_stage_view.xml b/fieldservice_mobile/views/fsm_stage_view.xml new file mode 100644 index 0000000000..6c750aaf28 --- /dev/null +++ b/fieldservice_mobile/views/fsm_stage_view.xml @@ -0,0 +1,13 @@ + + + fsm.stage.form.inherit.mobile + fsm.stage + + + + + + + + + diff --git a/fieldservice_mobile/views/mobile_feature_line.xml b/fieldservice_mobile/views/mobile_feature_line.xml new file mode 100644 index 0000000000..b1584ce956 --- /dev/null +++ b/fieldservice_mobile/views/mobile_feature_line.xml @@ -0,0 +1,17 @@ + + + + fsm.mobile.feature.line.view + fsm.mobile.feature.line + +
+ + +
+
+
+
diff --git a/fieldservice_mobile/views/mobile_feature_mapping.xml b/fieldservice_mobile/views/mobile_feature_mapping.xml new file mode 100644 index 0000000000..3b0a258b38 --- /dev/null +++ b/fieldservice_mobile/views/mobile_feature_mapping.xml @@ -0,0 +1,80 @@ + + + + fsm.mobile.feature.mapping.list.view + fsm.mobile.feature.mapping + + + + + + + + + + fsm.mobile.feature.mapping.view + fsm.mobile.feature.mapping + +
+
+
+ + + + + + + + + + + + + + + + + + +
+
+
+ + + + Field Service Mobile Feature Mapping + fsm.mobile.feature.mapping + + list,form + + + + +
diff --git a/fieldservice_mobile/views/res_config_settings.xml b/fieldservice_mobile/views/res_config_settings.xml new file mode 100644 index 0000000000..8706908819 --- /dev/null +++ b/fieldservice_mobile/views/res_config_settings.xml @@ -0,0 +1,33 @@ + + + res.config.settings.view.form.fsm.mobile + res.config.settings + + + + + + + + + + + + + + +