From b3f5a1aed078ac4b63ca6ccd9f8f99f7dcefa8ec 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 | 36 ++++++ fieldservice_mobile/data/base_automation.xml | 87 ++++++++++++++ fieldservice_mobile/data/feature_line.xml | 107 ++++++++++++++++++ fieldservice_mobile/data/feature_mapping.xml | 28 +++++ 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 -> 17808 bytes 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 ++++++ 25 files changed, 918 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/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/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..7eb9ad8e86 --- /dev/null +++ b/fieldservice_mobile/__manifest__.py @@ -0,0 +1,36 @@ +# 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", + ], + "data": [ + "security/ir_rule.xml", + "security/ir.model.access.csv", + "security/fieldservice_mobile_security.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..067b1f426e --- /dev/null +++ b/fieldservice_mobile/data/base_automation.xml @@ -0,0 +1,87 @@ + + + FSM Order Started Stage Update + + on_write + + [["stage_id.sequence","=",6]] + 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 + + on_write + + [["stage_id.sequence","=",7]] + 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 + + on_write + + [["stage_id.sequence","=", 8]] + 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 + + on_write + + [["stage_id.sequence","=",9]] + 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/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/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..192bd2742a --- /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,1,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..955674d8f0b8c47de3ffa9db25cb109fbe4a1091 GIT binary patch literal 17808 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 literal 0 HcmV?d00001 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..07f738453c --- /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..75b26ca676 --- /dev/null +++ b/fieldservice_mobile/views/res_config_settings.xml @@ -0,0 +1,33 @@ + + + res.config.settings.view.form.fsm.mobile + res.config.settings + + + +
+ + + + + + + +
+
+
+