From 0d5935a1e4bd4a0524fb4b26a9a2081f82de2244 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 4 Dec 2023 13:58:58 -0500 Subject: [PATCH 01/96] new module to open full form view from a dialog. --- bemade_full_formview_from_modal/__init__.py | 0 .../__manifest__.py | 37 ++++++++++++++++ .../static/src/js/form_view_dialog.js | 43 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 bemade_full_formview_from_modal/__init__.py create mode 100644 bemade_full_formview_from_modal/__manifest__.py create mode 100644 bemade_full_formview_from_modal/static/src/js/form_view_dialog.js diff --git a/bemade_full_formview_from_modal/__init__.py b/bemade_full_formview_from_modal/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bemade_full_formview_from_modal/__manifest__.py b/bemade_full_formview_from_modal/__manifest__.py new file mode 100644 index 0000000..66d3327 --- /dev/null +++ b/bemade_full_formview_from_modal/__manifest__.py @@ -0,0 +1,37 @@ +# +# Bemade Inc. +# +# Copyright (C) 2023-June Bemade Inc. (). +# Author: Marc Durepos (Contact : mdurepos@durpro.com) +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +{ + 'name': 'Full Form from Dialog', + 'version': '15.0.1.0.0', + 'summary': 'Allows opening the full form view from the dialog (modal) view.', + 'description': 'Adds a button to open the full form view when viewing the form view for a record in a dialog.', + 'category': 'Technical', + 'author': 'Bemade Inc.', + 'website': 'http://www.bemade.org', + 'license': 'OPL-1', + 'depends': [], + 'data': [], + 'assets': { + 'web.assets_backend': [ + 'bemade_full_formview_from_modal/static/src/js/form_view_dialog.js', + ], + }, + 'installable': True, + 'auto_install': False +} diff --git a/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js b/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js new file mode 100644 index 0000000..e94ad00 --- /dev/null +++ b/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js @@ -0,0 +1,43 @@ +/** @odoo-module **/ + +import FormViewDialog from 'web.FormView'; +import Dialog from 'web.Dialog'; +import {patch} from '@web/core/utils/patch'; +import {_t} from 'web.core'; + +const dom = require('web.dom') + +patch(Dialog.prototype, "bemade_full_formview_from_modal.Dialog", { + init: function (parent, options) { + this._super(...arguments); + }, + custom_events: _.extend({}, Dialog.prototype.custom_events, { + open_full_form_view: '_onOpen', + }), + willStart: function () { + const self = this; + return this._super(...arguments).then(function () { + if (self.$footer) { + const $button = dom.renderButton({ + attrs: { + class: 'btn btn-secondary o_form_button_open', + }, + text: _t('Open'), + }); + $button.on('click', function() {self._onOpen.call(self)}); + self.$footer.append($button); + } + } + ); + }, + _onOpen: function () { + this.do_action({ + type: 'ir.actions.act_window', + res_model: this.options.res_model, + res_id: this.options.res_id, + views: [[false, 'form']], + target: 'current', + context: this.context, + }) + } +}); From 8af9704b67ade939dcdd1cd955ca0a2e1f7bb987 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 06:59:51 -0500 Subject: [PATCH 02/96] bemade_fsm: work for creating tasks directly from templates. --- bemade_fsm/models/task_template.py | 35 ++++++++++++++++ bemade_fsm/tests/test_task_template.py | 14 +++++++ bemade_fsm/wizard/__init__.py | 1 + bemade_fsm/wizard/new_task_from_template.py | 44 ++++++++++++++++++++ bemade_fsm/wizard/new_task_from_template.xml | 22 ++++++++++ 5 files changed, 116 insertions(+) create mode 100644 bemade_fsm/wizard/__init__.py create mode 100644 bemade_fsm/wizard/new_task_from_template.py create mode 100644 bemade_fsm/wizard/new_task_from_template.xml diff --git a/bemade_fsm/models/task_template.py b/bemade_fsm/models/task_template.py index 7253fbf..fdc1a46 100644 --- a/bemade_fsm/models/task_template.py +++ b/bemade_fsm/models/task_template.py @@ -81,3 +81,38 @@ class TaskTemplate(models.Model): for rec in self: new_equipment_ids = [eq.id for eq in rec.equipment_ids if eq.partner_location_id == rec.customer] rec.write({'equipment_ids': [Command.set(new_equipment_ids)]}) + + def _prepare_new_task_values_from_self(self, project, name=False, parent_id=False): + vals = { + 'project_id': project.id, + 'name': name or self.name, + 'description': self.description, + 'parent_id': parent_id, + 'user_ids': self.assignees.ids, + 'tag_ids': self.tags.ids, + 'planned_hours': self.planned_hours, + 'sequence': self.sequence, + 'equipment_ids': [Command.set(self.equipment_ids.ids)] if self.equipment_ids else False, + 'partner_id': project.partner_id and project.partner_id.id, + 'company_id': self.company_id.id, + } + return vals + + def create_task_from_self(self, project, name=False, parent_id=False): + """ Create a project.task from this template and return it. Can be called on a RecordSet of multiple templates. + + :param project: project.project record the task should be added to + :param name: name for the new task (defaults to template name) + :param parent_id: parent task for the new task (none by default) + :return: project.task record created from this template + """ + tasks = self.env['project.task'] + for rec in self: + vals = rec._prepare_new_task_values_from_self(project, name, parent_id) + task = rec.env['project.task'].create(vals) + rec.subtasks.create_task_from_self(project, name=False, parent_id=task.id) + tasks |= task + return tasks + + + diff --git a/bemade_fsm/tests/test_task_template.py b/bemade_fsm/tests/test_task_template.py index d0cf173..178911a 100644 --- a/bemade_fsm/tests/test_task_template.py +++ b/bemade_fsm/tests/test_task_template.py @@ -78,3 +78,17 @@ class TestTaskTemplate(BemadeFSMBaseTest): self.assertEqual(sol1.task_id.name, "Short Name 1") self.assertEqual(sol2.task_id.name, "Short Name 2") self.assertEqual(sol3.task_id.name, "Task") + + def test_task_creation_directly_from_template(self): + project = self.env.ref("industry_fsm.fsm_project") + template = self._generate_task_template(names=['Task', 'Child', 'Grandchild'], structure=[2, 1]) + + task = template.create_task_from_self(project, "My new task") + + self.assertEqual(len(task.child_ids), len(template.subtasks)) + self.assertEqual(len(task.child_ids[0].child_ids), len(template.subtasks[0].subtasks)) + self.assertEqual(len(task.child_ids[1].child_ids), len(template.subtasks[1].subtasks)) + self.assertEqual(task.name, "My new task") + self.assertEqual(task.child_ids[0].name, template.subtasks[0].name) + self.assertTrue(all([t.project_id == project for t in task | task._get_all_subtasks()])) + diff --git a/bemade_fsm/wizard/__init__.py b/bemade_fsm/wizard/__init__.py new file mode 100644 index 0000000..5cc0245 --- /dev/null +++ b/bemade_fsm/wizard/__init__.py @@ -0,0 +1 @@ +from . import new_task_from_template diff --git a/bemade_fsm/wizard/new_task_from_template.py b/bemade_fsm/wizard/new_task_from_template.py new file mode 100644 index 0000000..575629c --- /dev/null +++ b/bemade_fsm/wizard/new_task_from_template.py @@ -0,0 +1,44 @@ +from odoo import models, fields, api, _ +from odoo.exceptions import UserError + + +class NewTaskFromTemplateWizard(models.TransientModel): + _name = "project.task.from.template.wizard" + + project_id = fields.Many2one( + comodel_name='project.project', + string='Project', + help='The project the new task should be created in.', + required=True, + ) + + task_template_id = fields.Many2one( + comodel_name='project.task.template', + string='Task Template', + help='The template to use when creating the new task.', + required=True, + ) + + new_task_title = fields.Char( + help='The title (name) for the newly created task. If left blank, the name of the template will be used.', + ) + + def default_get(self, fields_list): + res = super().default_get(fields_list) + if 'project_id' in fields_list: + active_id = self.env.context.get('active_id', False) + res.update({'project_id': active_id}) + return res + + def action_create_task_from_template(self): + self.ensure_one() + task = self.task_template_id.create_task_from_self(self.project_id, self.new_task_title) + return { + 'type': 'ir.actions.act_window', + 'res_model': 'project.task', + 'res_id': task.id, + 'view_mode': 'form', + 'target': 'current', + } + + diff --git a/bemade_fsm/wizard/new_task_from_template.xml b/bemade_fsm/wizard/new_task_from_template.xml new file mode 100644 index 0000000..49a22ce --- /dev/null +++ b/bemade_fsm/wizard/new_task_from_template.xml @@ -0,0 +1,22 @@ + + + + project.task.from.template.wizard.view.form + project.task.from.template.wizard + +
+
+
+ + + + + + + +
+
+
+
\ No newline at end of file From 22936eee1c0fb7b403ca91611ad94f7d2d258ae8 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 09:58:39 -0500 Subject: [PATCH 03/96] bemade_fsm: Create task from template (from FSM views) Adds a button to create a task from a task template to the list view and kanban view for the project.task when viewed from the FSM application. --- bemade_fsm/__init__.py | 1 + bemade_fsm/__manifest__.py | 8 ++++ bemade_fsm/security/ir.model.access.csv | 1 + bemade_fsm/static/src/js/kanban_view.js | 37 +++++++++++++++++++ bemade_fsm/static/src/js/list_view.js | 36 ++++++++++++++++++ .../static/src/xml/project_view_buttons.xml | 21 +++++++++++ bemade_fsm/views/task_views.xml | 13 +++++++ bemade_fsm/wizard/new_task_from_template.py | 14 +++++-- bemade_fsm/wizard/new_task_from_template.xml | 15 ++++++-- 9 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 bemade_fsm/static/src/js/kanban_view.js create mode 100644 bemade_fsm/static/src/js/list_view.js create mode 100644 bemade_fsm/static/src/xml/project_view_buttons.xml diff --git a/bemade_fsm/__init__.py b/bemade_fsm/__init__.py index 0650744..9b42961 100644 --- a/bemade_fsm/__init__.py +++ b/bemade_fsm/__init__.py @@ -1 +1,2 @@ from . import models +from . import wizard diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index c71d220..c378151 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -53,6 +53,7 @@ 'views/sale_order_views.xml', 'reports/worksheet_custom_report_templates.xml', 'reports/worksheet_custom_reports.xml', + 'wizard/new_task_from_template.xml', ], 'assets': { 'web.assets_tests': [ @@ -62,6 +63,13 @@ ], 'web.report_assets_common': [ 'bemade_fsm/static/src/scss/bemade_fsm.scss' + ], + 'web.assets_backend': [ + 'bemade_fsm/static/src/js/kanban_view.js', + 'bemade_fsm/static/src/js/list_view.js', + ], + 'web.assets_qweb': [ + 'bemade_fsm/static/src/xml/project_view_buttons.xml', ] }, 'installable': True, diff --git a/bemade_fsm/security/ir.model.access.csv b/bemade_fsm/security/ir.model.access.csv index df83ebc..2c30345 100644 --- a/bemade_fsm/security/ir.model.access.csv +++ b/bemade_fsm/security/ir.model.access.csv @@ -5,3 +5,4 @@ access_bemade_fsm_equipment,bemade_fsm_equipment,model_bemade_fsm_equipment,base access_bemade_fsm_equipment_tag,bemade_fsm_equipment_tag,model_bemade_fsm_equipment_tag,base.group_user,1,1,1,1 access_bemade_fsm_equipment_type,access_bemade_fsm_equipment_type,model_bemade_fsm_equipment_type,base.group_user,1,0,0,0 access_bemade_fsm_visit,access_bemade_fsm_visit,model_bemade_fsm_visit,base.group_user,1,1,1,1 +access_bemade_fsm_task_wizard,access_bemade_fsm_task_wizard,model_project_task_from_template_wizard,project.group_project_user,1,1,1,1 diff --git a/bemade_fsm/static/src/js/kanban_view.js b/bemade_fsm/static/src/js/kanban_view.js new file mode 100644 index 0000000..2185d01 --- /dev/null +++ b/bemade_fsm/static/src/js/kanban_view.js @@ -0,0 +1,37 @@ +/** @odoo-module **/ + +import KanbanController from 'web.KanbanController'; +import KanbanView from 'web.KanbanView'; +const viewRegistry = require('web.view_registry') + +const ProjectKanbanController = KanbanController.extend({ + buttons_template: 'project.KanbanView.buttons', + custom_events: _.extend({}, KanbanController.prototype.custom_events, { + create_from_template: '_onCreateFromTemplate', + }), + _onCreateFromTemplate(ev) { + ev.stopPropagation(); + const record = this.model.get(this.handle, {raw: true}); + let context = record.context; + context.active_id = record.project_id; + this.do_action({ + type: 'ir.actions.act_window', + res_model: 'project.task.from.template.wizard', + views: [[false, 'form']], + target: 'new', + context: {...record.context, active_id: record.project_id}, + }); + }, + renderButtons ($node) { + this._super.apply(this, arguments); + this.$buttons.on('click', 'button.o-kanban-button-new-from-template', this._onCreateFromTemplate.bind(this)) + }, +}) + +const ProjectKanbanView = KanbanView.extend({ + config: _.extend({}, KanbanView.prototype.config, { + Controller: ProjectKanbanController, + }) +}); + +viewRegistry.add('project_kanban', ProjectKanbanView) \ No newline at end of file diff --git a/bemade_fsm/static/src/js/list_view.js b/bemade_fsm/static/src/js/list_view.js new file mode 100644 index 0000000..3486965 --- /dev/null +++ b/bemade_fsm/static/src/js/list_view.js @@ -0,0 +1,36 @@ +/** @odoo-module **/ + +import ListController from 'web.ListController'; +import ListView from 'web.ListView'; +const viewRegistry = require('web.view_registry') + +const ProjectListController = ListController.extend({ + buttons_template: 'project.ListView.buttons', + custom_events: _.extend({}, ListController.prototype.custom_events, { + create_from_template: '_onCreateFromTemplate', + }), + _onCreateFromTemplate(ev) { + ev.stopPropagation(); + const record = this.model.get(this.handle, {raw: true}); + this.do_action({ + type: 'ir.actions.act_window', + res_model: 'project.task.from.template.wizard', + views: [[false, 'form']], + target: 'new', + context: {...record.context, active_id: record.project_id}, + }); + }, + renderButtons ($node) { + self = this; + this._super.apply(this, arguments); + this.$buttons.on('click', 'button.o_list_button_add_from_template', this._onCreateFromTemplate.bind(this)) + }, +}) + +const ProjectListView = ListView.extend({ + config: _.extend({}, ListView.prototype.config, { + Controller: ProjectListController, + }) +}); + +viewRegistry.add('project_list', ProjectListView) \ No newline at end of file diff --git a/bemade_fsm/static/src/xml/project_view_buttons.xml b/bemade_fsm/static/src/xml/project_view_buttons.xml new file mode 100644 index 0000000..df3484a --- /dev/null +++ b/bemade_fsm/static/src/xml/project_view_buttons.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bemade_fsm/views/task_views.xml b/bemade_fsm/views/task_views.xml index 1fbfecf..25f71be 100644 --- a/bemade_fsm/views/task_views.xml +++ b/bemade_fsm/views/task_views.xml @@ -98,6 +98,9 @@ project.task + + project_list + @@ -112,6 +115,16 @@ + + project.task.view.kanban.fsm.inherit + project.task + + + + project_kanban + + + project.task.view.search.fsm.inherit project.task diff --git a/bemade_fsm/wizard/new_task_from_template.py b/bemade_fsm/wizard/new_task_from_template.py index 575629c..26d67ba 100644 --- a/bemade_fsm/wizard/new_task_from_template.py +++ b/bemade_fsm/wizard/new_task_from_template.py @@ -4,6 +4,7 @@ from odoo.exceptions import UserError class NewTaskFromTemplateWizard(models.TransientModel): _name = "project.task.from.template.wizard" + _description = "Create Task from Template Wizard" project_id = fields.Many2one( comodel_name='project.project', @@ -25,9 +26,16 @@ class NewTaskFromTemplateWizard(models.TransientModel): def default_get(self, fields_list): res = super().default_get(fields_list) - if 'project_id' in fields_list: - active_id = self.env.context.get('active_id', False) - res.update({'project_id': active_id}) + active_id = self.env.context.get('active_id', False) + active_model = self.env.context.get('active_model', False) + if not active_model: + params = self.env.context.get('params', False) + active_model = params.get('model', False) + + if active_model == 'project.task.template' and active_id and 'task_template_id' in fields_list: + res.update({'task_template_id': active_id}) + if active_model == 'project.task' and 'project_id' in fields_list: + res.update({'project_id': self.env.ref('industry_fsm.fsm_project').id}) return res def action_create_task_from_template(self): diff --git a/bemade_fsm/wizard/new_task_from_template.xml b/bemade_fsm/wizard/new_task_from_template.xml index 49a22ce..1290b8f 100644 --- a/bemade_fsm/wizard/new_task_from_template.xml +++ b/bemade_fsm/wizard/new_task_from_template.xml @@ -5,10 +5,6 @@ project.task.from.template.wizard
-
-
@@ -16,7 +12,18 @@ +
+
+ + New Task from Template + project.task.from.template.wizard + + form + new + \ No newline at end of file From 79d1cbe330870b6f7b30023bdfbfbad8062b0f80 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 11:16:10 -0500 Subject: [PATCH 04/96] bemade_full_formview_from_modal: remove useless lines of JS. --- .../static/src/js/form_view_dialog.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js b/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js index e94ad00..fbb2b83 100644 --- a/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js +++ b/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js @@ -11,9 +11,6 @@ patch(Dialog.prototype, "bemade_full_formview_from_modal.Dialog", { init: function (parent, options) { this._super(...arguments); }, - custom_events: _.extend({}, Dialog.prototype.custom_events, { - open_full_form_view: '_onOpen', - }), willStart: function () { const self = this; return this._super(...arguments).then(function () { From 0806bc96f0292e54349cf9a1010b8da3e69549b8 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 11:19:16 -0500 Subject: [PATCH 05/96] version bump for bemade_fsm --- bemade_fsm/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index c378151..ecc58bc 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.3', + 'version': '15.0.1.0.4', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', From 6ab1bda2b7bb0a3fd277bad84b9c9f50a03953a7 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 11:43:24 -0500 Subject: [PATCH 06/96] bemade_fsm: bug fix in new_task_from_template.py default_get --- bemade_fsm/wizard/new_task_from_template.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bemade_fsm/wizard/new_task_from_template.py b/bemade_fsm/wizard/new_task_from_template.py index 26d67ba..6c8c5e1 100644 --- a/bemade_fsm/wizard/new_task_from_template.py +++ b/bemade_fsm/wizard/new_task_from_template.py @@ -30,8 +30,7 @@ class NewTaskFromTemplateWizard(models.TransientModel): active_model = self.env.context.get('active_model', False) if not active_model: params = self.env.context.get('params', False) - active_model = params.get('model', False) - + active_model = params and params.get('model', False) if active_model == 'project.task.template' and active_id and 'task_template_id' in fields_list: res.update({'task_template_id': active_id}) if active_model == 'project.task' and 'project_id' in fields_list: From 9ff8934556c0a9a0c9004ec0bc4a6b70aca17604 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 12:11:48 -0500 Subject: [PATCH 07/96] Fixed new task from template wizard to show right default project. --- bemade_fsm/static/src/js/kanban_view.js | 2 +- bemade_fsm/static/src/js/list_view.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bemade_fsm/static/src/js/kanban_view.js b/bemade_fsm/static/src/js/kanban_view.js index 2185d01..7f99dcc 100644 --- a/bemade_fsm/static/src/js/kanban_view.js +++ b/bemade_fsm/static/src/js/kanban_view.js @@ -19,7 +19,7 @@ const ProjectKanbanController = KanbanController.extend({ res_model: 'project.task.from.template.wizard', views: [[false, 'form']], target: 'new', - context: {...record.context, active_id: record.project_id}, + context: {...record.context, res_model: 'project.task'}, }); }, renderButtons ($node) { diff --git a/bemade_fsm/static/src/js/list_view.js b/bemade_fsm/static/src/js/list_view.js index 3486965..dc60c3a 100644 --- a/bemade_fsm/static/src/js/list_view.js +++ b/bemade_fsm/static/src/js/list_view.js @@ -17,7 +17,7 @@ const ProjectListController = ListController.extend({ res_model: 'project.task.from.template.wizard', views: [[false, 'form']], target: 'new', - context: {...record.context, active_id: record.project_id}, + context: {...record.context, res_model: 'project.task'}, }); }, renderButtons ($node) { From 41ef2c1484e28f1b72b62b5f9dfe26b8b5341a4d Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 12:23:38 -0500 Subject: [PATCH 08/96] bemade_fsm: spacing for task from template button, delete js tests. --- .../static/src/xml/project_view_buttons.xml | 2 +- .../static/tests/tours/equipment_tour.js | 104 ------------------ .../static/tests/tours/sale_order_tour.js | 40 ------- .../static/tests/tours/task_equipment_tour.js | 75 ------------- .../static/tests/tours/task_template_tour.js | 47 -------- 5 files changed, 1 insertion(+), 267 deletions(-) delete mode 100644 bemade_fsm/static/tests/tours/equipment_tour.js delete mode 100644 bemade_fsm/static/tests/tours/sale_order_tour.js delete mode 100644 bemade_fsm/static/tests/tours/task_equipment_tour.js delete mode 100644 bemade_fsm/static/tests/tours/task_template_tour.js diff --git a/bemade_fsm/static/src/xml/project_view_buttons.xml b/bemade_fsm/static/src/xml/project_view_buttons.xml index df3484a..e2c48c6 100644 --- a/bemade_fsm/static/src/xml/project_view_buttons.xml +++ b/bemade_fsm/static/src/xml/project_view_buttons.xml @@ -12,7 +12,7 @@ - diff --git a/bemade_fsm/static/tests/tours/equipment_tour.js b/bemade_fsm/static/tests/tours/equipment_tour.js deleted file mode 100644 index ec69e1e..0000000 --- a/bemade_fsm/static/tests/tours/equipment_tour.js +++ /dev/null @@ -1,104 +0,0 @@ -/** @odoo-module **/ - -import tour from 'web_tour.tour'; - -const TEST_COMPANY = "Test Partner"; -const TEST_EQPT1 = "Test Equipment 1"; -const TEST_EQPT2 = "Test Equipment 2"; -tour.register('equipment_base_tour', { - test: true, - url: '/web', - }, /* Create a new "Test Equipment" and link it to "Test Partner Company" */ - [tour.stepUtils.showAppsMenuItem(), { - content: 'Navigate to the Service menu', - trigger: '.o_app[data-menu-xmlid="industry_fsm.fsm_menu_root"]', - }, { - content: 'Navigate to the Clients submenu', - trigger: 'button.dropdown-toggle[data-menu-xmlid="bemade_fsm.menu_service_client"]', - }, { - content: 'Navigate to the Equipment menu', - trigger: '.dropdown-item[data-menu-xmlid="bemade_fsm.menu_service_client_equipment"]', - }, { - content: 'Click the create button', - trigger: '.o_list_button_add', - }, { - content: 'Add a tag', - trigger: 'input[name="pid_tag"]', - run: 'text TestPIDTag', - }, { - content: 'Set the name', - trigger: 'input[name="name"]', - run: `text ${TEST_EQPT2}`, - }, { - content: 'Set the partner', - trigger: 'div[name="partner_location_id"] div div input', - run: `text ${TEST_COMPANY}`, - }, { - content: 'Click the partner in the dropdown', - trigger: `li a.dropdown-item:contains(${TEST_COMPANY})`, - }, { - content: 'Save equipment', - trigger: 'button.o_list_button_save', - }, { - /* Navigate to the client and make sure that there are two equipments saved (one from the Python test case) */ - content: 'Navigate to the Clients submenu', - trigger: 'button.dropdown-toggle[data-menu-xmlid="bemade_fsm.menu_service_client"]', - }, { - content: 'Click on the clients submenu', - trigger: '.dropdown-item[data-menu-xmlid="bemade_fsm.menu_service_client_clients"]', - }, { - content: 'Search for the Test Partner Company', - trigger: 'input.o_searchview_input', - extra_trigger: 'li.breadcrumb-item.active:has(span:contains(Customers))', - run: `text ${TEST_COMPANY}` - }, { - content: 'Validate Search', - trigger: '.o_menu_item.o_selection_focus', - run: 'click', - }, { - content: 'Open the test client.', - trigger: `div.o_kanban_record:has(span:contains(${TEST_COMPANY}))`, - }, { - content: 'Click the Field Service tab.', - trigger: 'a.nav-link:contains(Field Service)', - extra_trigger: `h1 span.o_field_partner_autocomplete[name="name"]:contains(${TEST_COMPANY})`, - }, { - content: 'Make sure we have a first test equipment', - trigger: `td:contains(${TEST_EQPT1})`, - run: function () { - }, - }, { - content: 'Make sure we have a second test equipment', - trigger: `div[name="equipment_ids"]:has(td:contains(${TEST_EQPT2}))`, - run: function () { - }, - } - ]); - -tour.register('equipment_sale_order_tour', { - test: true, - url: '/web', -}, [tour.stepUtils.showAppsMenuItem(), { - content: 'Navigate to the Sales menu', - trigger: '.o_app[data-menu-xmlid="sale.sale_menu_root"]', -}, { - content: 'Create an order', - trigger: 'button.o_list_button_add', -}, { - content: 'Select the test partner', - trigger: 'div[name="partner_id"] input', - run: `text ${TEST_COMPANY}`, -}, { - content: 'Click the partner in the dropdown', - trigger: `li a.dropdown-item:contains(${TEST_COMPANY})`, -}, { - content: 'Save', - trigger: 'button.o_form_button_save', -}, { - content: 'Navigate to the Field Service tab.', - trigger: 'a.nav-link[role="tab"]:contains(Field Service)' -}, { - content: 'Check that the equipment is listed in the tab.', - trigger: `li.ui-menu-item > a:contains(${TEST_EQPT1})`, -} -]); \ No newline at end of file diff --git a/bemade_fsm/static/tests/tours/sale_order_tour.js b/bemade_fsm/static/tests/tours/sale_order_tour.js deleted file mode 100644 index 6ea8eee..0000000 --- a/bemade_fsm/static/tests/tours/sale_order_tour.js +++ /dev/null @@ -1,40 +0,0 @@ -/** @odoo-module **/ - -import tour from 'web_tour.tour'; - -const SO_NAME = "TEST ORDER 2" -const PRODUCT_NAME = "Test Product 3" -tour.register('sale_order_tour', { - test: true, - url: '/web', - }, - [tour.stepUtils.showAppsMenuItem(), { - content: 'Navigate to the Service menu', - trigger: '.o_app[data-menu-xmlid="sale.sale_menu_root"]', - }, { - content: 'Search for the sales order', - trigger: 'input.o_searchview_input', - run: `text ${SO_NAME}`, - }, { - content: 'Validate Search', - trigger: '.o_menu_item.o_selection_focus', - run: 'click', - }, { - content: 'Open the test order', - trigger: `.o_data_cell[name="client_order_ref"]:contains(${SO_NAME})`, - }, { - content: 'Click the view tasks button', - trigger: 'button[name="action_view_task"]', - }, /*{ - content: 'Click the first task', - trigger: `div.o_kanban_record:has(span:contains(${PRODUCT_NAME}))`, - },*/ { - content: 'Click on the ready to invoice button', - trigger: 'button[name="action_fsm_validate"]', - extra_trigger: `li.breadcrumb-item.active:has(span:contains(${PRODUCT_NAME}))` - }, { - content: 'View the SO', - trigger: 'button[name="action_view_so"]', - // extra_trigger: 'button[title="Current state"]:contains(Done)', - } - ]); diff --git a/bemade_fsm/static/tests/tours/task_equipment_tour.js b/bemade_fsm/static/tests/tours/task_equipment_tour.js deleted file mode 100644 index f8a244d..0000000 --- a/bemade_fsm/static/tests/tours/task_equipment_tour.js +++ /dev/null @@ -1,75 +0,0 @@ -/** @odoo-module **/ - -import tour from 'web_tour.tour'; -const TEST_COMPANY = "Test Partner Company"; -const TEST_EQPT1 = "Test Equipment 1"; -const TEST_EQPT2 = "Test Equipment 2"; -tour.register('task_equipment_tour', { - test: true, - url: '/web', - }, /* Create a new "Test Equipment" and link it to "Test Partner Company" */ - [tour.stepUtils.showAppsMenuItem(), { - content: 'Navigate to the Service menu', - trigger: '.o_app[data-menu-xmlid="industry_fsm.fsm_menu_root"]', - }, { - content: 'Navigate to the Clients submenu', - trigger: 'button.dropdown-toggle[data-menu-xmlid="bemade_fsm.menu_service_client"]', - }, { - content: 'Navigate to the Equipment menu', - trigger: '.dropdown-item[data-menu-xmlid="bemade_fsm.menu_service_client_equipment"]', - }, { - content: 'Click the create button', - trigger: '.o_list_button_add', - extra_trigger: 'li.breadcrumb-item.active:has(span:contains(Equipment))', - }, { - content: 'Add a tag', - trigger: 'input[name="pid_tag"]', - run: 'text TestPIDTag', - }, { - content: 'Set the name', - trigger: 'input[name="name"]', - run: `text ${TEST_EQPT2}`, - }, { - content: 'Set the partner', - trigger: 'div[name="partner_location_id"] div div input', - run: 'text Test Partner Company', - }, { - content: 'Click the partner in the dropdown', - trigger: `li a.dropdown-item:contains(${TEST_COMPANY})`, - }, { - content: 'Save equipment', - trigger: 'button.o_list_button_save', - }, { - /* Navigate to the client and make sure that there are two equipments saved (one from the Python test case) */ - content: 'Navigate to the Clients submenu', - trigger: 'button.dropdown-toggle[data-menu-xmlid="bemade_fsm.menu_service_client"]', - }, { - content: 'Click on the clients submenu', - trigger: '.dropdown-item[data-menu-xmlid="bemade_fsm.menu_service_client_clients"]', - }, { - content: 'Search for the Test Partner Company', - trigger: 'input.o_searchview_input', - extra_trigger: 'li.breadcrumb-item.active:has(span:contains(Customers))', - run: `text ${TEST_COMPANY}` - }, { - content: 'Validate Search', - trigger: '.o_menu_item.o_selection_focus', - run: 'click', - }, { - content: 'Open the test client.', - trigger: `div.o_kanban_record:has(span:contains(${TEST_COMPANY}))`, - }, { - content: 'Click the Field Service tab.', - trigger: 'a.nav-link:contains(Field Service)', - extra_trigger: `h1 span.o_field_partner_autocomplete[name="name"]:contains(${TEST_COMPANY})`, - }, { - content: 'Make sure we have a first test equipment', - /*trigger: `div[name="equipment_ids"]:has(td:contains(${TEST_EQPT1}))`,*/ - trigger: `td:contains(${TEST_EQPT1})`, - run: function() {}, - }, { - content: 'Make sure we have a second test equipment', - trigger: `div[name="equipment_ids"]:has(td:contains(${TEST_EQPT2}))`, - run: function() {}, - } - ]) \ No newline at end of file diff --git a/bemade_fsm/static/tests/tours/task_template_tour.js b/bemade_fsm/static/tests/tours/task_template_tour.js deleted file mode 100644 index 3573a45..0000000 --- a/bemade_fsm/static/tests/tours/task_template_tour.js +++ /dev/null @@ -1,47 +0,0 @@ -/** @odoo-module */ - -import tour from 'web_tour.tour'; - -tour.register('task_template_tour', { - test: true, - url: '/web', - }, /* Make sure the test task is visible via the Project > Task Templates path */ - [tour.stepUtils.showAppsMenuItem(), { - trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]', - }, { - content: 'Open the task templates list view.', - trigger: '.o_nav_entry[data-menu-xmlid="bemade_fsm.project_task_template_menu"]', - }, { - content: 'Open the existing task template.', - trigger: '.o_data_cell:contains("Template 1"):parent()', - }, { - content: 'Confirm that the header contains the task title.', - trigger: 'span[name="name"]:contains("Template 1")', - }, /* Make sure we can see the task template from the product */ - tour.stepUtils.toggleHomeMenu(), - { - content: 'Open the sales menu.', - trigger: '.o_app[data-menu-xmlid="sale.sale_menu_root"]', - }, { - content: 'Open the product dropdown menu.', - trigger: 'button[data-menu-xmlid="sale.product_menu_catalog"]', - }, { - content: 'Click the products menu item.', - trigger: 'a.dropdown-item[data-menu-xmlid="sale.menu_product_template_action"]', - }, { - content: 'Search for the test product.', - trigger: 'input.o_searchview_input', - extra_trigger: 'li.breadcrumb-item.active:has(span:contains(Products))', - run: 'text Test Product 1', - }, { - trigger: '.o_menu_item.o_selection_focus', - content: 'Validate search', - run: 'click', - }, { - content: 'Open the test product.', - trigger: 'div.o_kanban_record:has(span:contains(Test Product 1))', - }, { - content: 'Ensure the product_template_id field is displayed with the "Template 1" mention.', - trigger: 'a.o_quick_editable[name="task_template_id"]:first-child:contains("Template 1")', - }, - ]) \ No newline at end of file From 74ec46382a2f435263f2d1caf5496e679b3ea451 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 14:56:06 -0500 Subject: [PATCH 09/96] bemade_fsm: Propagation of task assignee to subtasks (optional). --- bemade_fsm/__manifest__.py | 2 +- bemade_fsm/models/task.py | 17 ++++++++++++ bemade_fsm/tests/__init__.py | 1 + bemade_fsm/tests/test_sale_order.py | 2 +- bemade_fsm/tests/test_task.py | 40 +++++++++++++++++++++++++++++ bemade_fsm/views/task_views.xml | 3 +++ 6 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 bemade_fsm/tests/test_task.py diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index ecc58bc..9b7669d 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.4', + 'version': '15.0.1.0.5', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', diff --git a/bemade_fsm/models/task.py b/bemade_fsm/models/task.py index 296a7c6..c0b20e0 100644 --- a/bemade_fsm/models/task.py +++ b/bemade_fsm/models/task.py @@ -76,6 +76,12 @@ class Task(models.Model): work_order_number = fields.Char(readonly=True) + propagate_assignment = fields.Boolean( + string='Propagate Assignment', + help='Propagate assignment of this task to all subtasks.', + default=True, + ) + @api.model_create_multi def create(self, vals): res = super().create(vals) @@ -92,6 +98,16 @@ class Task(models.Model): + f"-{seq}" return res + def write(self, vals): + super().write(vals) + if not self: # End recursion on empty RecordSet + return + if 'user_ids' in vals: + to_propagate = self.filtered(lambda task: task.propagate_assignment) + # Here we use child_ids instead of _get_all_subtasks() so as to allow for setting propagate_assignment + # to false on a child task. + to_propagate.child_ids.write({'user_ids': vals['user_ids']}) + @api.depends('sale_order_id') def _compute_relevant_order_lines(self): for rec in self: @@ -199,6 +215,7 @@ class Task(models.Model): if self.child_ids: return self | self.child_ids._get_full_hierarchy() return self + def synchronize_name_fsm(self): """ Applies naming to the entire task tree for tasks that are part of this recordset. Root tasks are named: diff --git a/bemade_fsm/tests/__init__.py b/bemade_fsm/tests/__init__.py index 381536f..4b317ee 100644 --- a/bemade_fsm/tests/__init__.py +++ b/bemade_fsm/tests/__init__.py @@ -4,3 +4,4 @@ from . import test_sale_order from . import test_equipment from . import test_fsm_contact_setting from . import test_fsm_visit +from . import test_task diff --git a/bemade_fsm/tests/test_sale_order.py b/bemade_fsm/tests/test_sale_order.py index c51246c..484392e 100644 --- a/bemade_fsm/tests/test_sale_order.py +++ b/bemade_fsm/tests/test_sale_order.py @@ -251,7 +251,7 @@ class TestSalesOrder(BemadeFSMBaseTest): self.assertFalse(visit_task.user_ids) self.assertFalse(subtask1.user_ids) self.assertFalse(subtask2.user_ids) - + def test_long_line_name_overflows_to_task_description(self): so = self._generate_sale_order() product = self._generate_product() diff --git a/bemade_fsm/tests/test_task.py b/bemade_fsm/tests/test_task.py new file mode 100644 index 0000000..63185de --- /dev/null +++ b/bemade_fsm/tests/test_task.py @@ -0,0 +1,40 @@ +from .test_bemade_fsm_common import BemadeFSMBaseTest +from odoo.tests.common import tagged +from odoo import Command + + +@tagged('post_install', '-at_install') +class TaskTest(BemadeFSMBaseTest): + + def test_reassigning_assignment_propagating_task_changes_subtasks(self): + # This creation step is a bit lazy - we use defaults to make tasks with a hierachy and settings we want + so = self._generate_sale_order() + template = self._generate_task_template(names=['Parent', 'Child'], structure=[2]) + product = self._generate_product(task_template=template) + sol = self._generate_sale_order_line(sale_order=so, product=product) + user = self._generate_project_manager_user('Bob', 'Bob') + so.action_confirm() + task = sol.task_id + + task.write({ + 'user_ids': [Command.set([user.id])] + }) + + self.assertTrue(all([t.user_ids == user for t in task | task._get_all_subtasks()])) + + def test_reassigning_assignment_non_propagating_task_doesnt_change_subtasks(self): + so = self._generate_sale_order() + template = self._generate_task_template(names=['Parent', 'Child', 'Grandchild'], structure=[2, 1]) + product = self._generate_product(task_template=template) + sol = self._generate_sale_order_line(sale_order=so, product=product) + user = self._generate_project_manager_user('Bob', 'Bob') + so.action_confirm() + task = sol.task_id + task.child_ids.write({'propagate_assignment': False}) # Stop propagation after the first level + + task.write({ + 'user_ids': [Command.set([user.id])] + }) + + self.assertTrue(all([t.user_ids == user for t in task | task.child_ids])) + self.assertFalse(any([t.user_ids for t in task.child_ids.child_ids])) diff --git a/bemade_fsm/views/task_views.xml b/bemade_fsm/views/task_views.xml index 25f71be..8db34b3 100644 --- a/bemade_fsm/views/task_views.xml +++ b/bemade_fsm/views/task_views.xml @@ -46,6 +46,9 @@ + + + From 165ad8a226c55bf433105b9cc045f47791322bad Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Fri, 8 Dec 2023 14:01:41 -0500 Subject: [PATCH 10/96] bemade_fsm: propagate assignees to false by default. --- bemade_fsm/__manifest__.py | 2 +- bemade_fsm/models/task.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index 9b7669d..fa6c83b 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.5', + 'version': '15.0.1.0.6', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', diff --git a/bemade_fsm/models/task.py b/bemade_fsm/models/task.py index c0b20e0..43a147d 100644 --- a/bemade_fsm/models/task.py +++ b/bemade_fsm/models/task.py @@ -79,7 +79,7 @@ class Task(models.Model): propagate_assignment = fields.Boolean( string='Propagate Assignment', help='Propagate assignment of this task to all subtasks.', - default=True, + default=False, ) @api.model_create_multi From c950fe3e93ca51f397ba5ab57f7f36f354ae16e4 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 11 Dec 2023 18:23:31 -0500 Subject: [PATCH 11/96] [ENH] bemade_sports_clinic: wrap text on the portal and show HTML. Allows portal users to see the full diagnosis and notes. Previously, diagnosis was truncated if it went beyond the bounds of the column. Also, notes are now shown in HTML instead of HTML escaped to text. --- bemade_sports_clinic/__manifest__.py | 2 +- bemade_sports_clinic/views/sports_clinic_portal_views.xml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bemade_sports_clinic/__manifest__.py b/bemade_sports_clinic/__manifest__.py index 8b604e0..f1689fd 100644 --- a/bemade_sports_clinic/__manifest__.py +++ b/bemade_sports_clinic/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Sports Clinic Management', - 'version': '16.0.1.5.0', + 'version': '16.0.1.5.1', 'summary': 'Manage the patients of a sports medicine clinic.', 'description': """ Adds the notion of sports teams, players (patients), coaches and treatment diff --git a/bemade_sports_clinic/views/sports_clinic_portal_views.xml b/bemade_sports_clinic/views/sports_clinic_portal_views.xml index a91b59e..63d0cb7 100644 --- a/bemade_sports_clinic/views/sports_clinic_portal_views.xml +++ b/bemade_sports_clinic/views/sports_clinic_portal_views.xml @@ -165,18 +165,18 @@ - Active Injury - Notes + Active Injury + Notes - + - + From 6ff1bf5706880dc2cb319dedd39d9e1eb3596fcb Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 11 Dec 2023 21:30:08 -0500 Subject: [PATCH 12/96] [ENH] bemade_sports_clinic: Kanban view created to enhance mobile. Kanban view added for players to improve the experience when browsing on mobile. Card text color synchronized with what the user expects from the list view. --- bemade_sports_clinic/__manifest__.py | 2 +- bemade_sports_clinic/models/patient.py | 2 +- .../views/sports_patient_views.xml | 43 +++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/bemade_sports_clinic/__manifest__.py b/bemade_sports_clinic/__manifest__.py index f1689fd..81b355f 100644 --- a/bemade_sports_clinic/__manifest__.py +++ b/bemade_sports_clinic/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Sports Clinic Management', - 'version': '16.0.1.5.1', + 'version': '16.0.1.5.2', 'summary': 'Manage the patients of a sports medicine clinic.', 'description': """ Adds the notion of sports teams, players (patients), coaches and treatment diff --git a/bemade_sports_clinic/models/patient.py b/bemade_sports_clinic/models/patient.py index a15db38..201bea2 100644 --- a/bemade_sports_clinic/models/patient.py +++ b/bemade_sports_clinic/models/patient.py @@ -61,7 +61,7 @@ class Patient(models.Model): "return to match play.") is_injured = fields.Boolean(compute="_compute_is_injured") stage = fields.Selection( - selection=[('no_play', 'Injured'), ('practice_ok', 'Cleared for Practice'), ('healthy', 'Cleared to Play')], + selection=[('no_play', 'Injured'), ('practice_ok', 'Practice OK'), ('healthy', 'Play OK')], compute='_compute_stage') last_consultation_date = fields.Date() active_injury_count = fields.Integer(compute='_compute_active_injury_count') diff --git a/bemade_sports_clinic/views/sports_patient_views.xml b/bemade_sports_clinic/views/sports_patient_views.xml index 6157357..3b1fccf 100644 --- a/bemade_sports_clinic/views/sports_patient_views.xml +++ b/bemade_sports_clinic/views/sports_patient_views.xml @@ -62,6 +62,49 @@
+ + sports.patient.view.kanban + sports.patient + + + + + + + + + + + + + + + + +
+ +
+
+
+ +
+
+ Status: +
+
+
+ DOB: + +
+
+
+
+
+
+
+
+ sports.patient.view.form sports.patient From 148fc500ed915eb91324e0dee97f28a6fd775830 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 18 Dec 2023 15:20:33 -0500 Subject: [PATCH 13/96] move account_credit_hold into bemade-addons --- account_credit_hold/__init__.py | 1 + account_credit_hold/__manifest__.py | 30 ++++++++++ account_credit_hold/models/__init__.py | 5 ++ .../models/account_followup.py | 8 +++ .../models/account_followup_report.py | 14 +++++ account_credit_hold/models/res_partner.py | 59 +++++++++++++++++++ account_credit_hold/models/sale_order.py | 17 ++++++ account_credit_hold/models/stock_picking.py | 9 +++ account_credit_hold/readme.md | 35 +++++++++++ .../static/src/js/followup_form_controller.js | 48 +++++++++++++++ .../static/src/js/followup_form_model.js | 14 +++++ .../src/xml/account_followup_template.xml | 10 ++++ .../views/account_followup_views.xml | 16 +++++ .../views/res_partner_views.xml | 33 +++++++++++ .../views/sale_order_views.xml | 18 ++++++ .../views/stock_picking_views.xml | 20 +++++++ 16 files changed, 337 insertions(+) create mode 100644 account_credit_hold/__init__.py create mode 100644 account_credit_hold/__manifest__.py create mode 100644 account_credit_hold/models/__init__.py create mode 100644 account_credit_hold/models/account_followup.py create mode 100644 account_credit_hold/models/account_followup_report.py create mode 100644 account_credit_hold/models/res_partner.py create mode 100644 account_credit_hold/models/sale_order.py create mode 100644 account_credit_hold/models/stock_picking.py create mode 100644 account_credit_hold/readme.md create mode 100644 account_credit_hold/static/src/js/followup_form_controller.js create mode 100644 account_credit_hold/static/src/js/followup_form_model.js create mode 100644 account_credit_hold/static/src/xml/account_followup_template.xml create mode 100644 account_credit_hold/views/account_followup_views.xml create mode 100644 account_credit_hold/views/res_partner_views.xml create mode 100644 account_credit_hold/views/sale_order_views.xml create mode 100644 account_credit_hold/views/stock_picking_views.xml diff --git a/account_credit_hold/__init__.py b/account_credit_hold/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/account_credit_hold/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_credit_hold/__manifest__.py b/account_credit_hold/__manifest__.py new file mode 100644 index 0000000..564b9bd --- /dev/null +++ b/account_credit_hold/__manifest__.py @@ -0,0 +1,30 @@ +{ + 'name': 'Account Credit Hold', + 'version': '15.0.2.0.0.1', + 'summary': 'Allows setting clients on credit hold, blocking the ability confirm a new sales order.', + 'description': 'Allows setting clients on hold, blocking the ability confirm a new sales order.', + 'category': 'Accounting/Accounting', + 'author': 'Bemade Inc.', + 'maintainer': 'Marc Durepos ', + 'website': 'http://www.bemade.org', + 'license': 'LGPL-3', + 'depends': ['sale', 'account_followup', 'stock'], + 'data': [ + 'views/account_followup_views.xml', + 'views/sale_order_views.xml', + 'views/res_partner_views.xml', + 'views/stock_picking_views.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'account_credit_hold/static/src/js/followup_form_model.js', + 'account_credit_hold/static/src/js/followup_form_controller.js', + ], + 'web.assets_qweb': [ + 'account_credit_hold/static/src/xml/account_followup_template.xml', + ], + }, + 'demo': [], + 'installable': True, + 'auto_install': False +} diff --git a/account_credit_hold/models/__init__.py b/account_credit_hold/models/__init__.py new file mode 100644 index 0000000..0c2c11c --- /dev/null +++ b/account_credit_hold/models/__init__.py @@ -0,0 +1,5 @@ +from . import account_followup +from . import res_partner +from . import sale_order +from . import stock_picking +from . import account_followup_report diff --git a/account_credit_hold/models/account_followup.py b/account_credit_hold/models/account_followup.py new file mode 100644 index 0000000..5af3363 --- /dev/null +++ b/account_credit_hold/models/account_followup.py @@ -0,0 +1,8 @@ +from odoo import fields, models, api + + +class FollowupLine(models.Model): + _inherit = 'account_followup.followup.line' + + account_hold = fields.Boolean(string="Place on Credit Hold", + help="Place clients on account hold, restricting confirmation of new orders.") diff --git a/account_credit_hold/models/account_followup_report.py b/account_credit_hold/models/account_followup_report.py new file mode 100644 index 0000000..9c9b852 --- /dev/null +++ b/account_credit_hold/models/account_followup_report.py @@ -0,0 +1,14 @@ +from odoo import models, fields, api, _ + +class FollowUpReport(models.AbstractModel): + _inherit = 'account.followup.report' + + def _get_line_info(self, followup_line): + res = super()._get_line_info(followup_line) + res.update({'credit_hold': followup_line.account_hold}) + return res + @api.model + def credit_hold(self, options): + partner_id = options['partner_id'] + partner = self.env['res.partner'].browse(partner_id) + partner.action_credit_hold() diff --git a/account_credit_hold/models/res_partner.py b/account_credit_hold/models/res_partner.py new file mode 100644 index 0000000..f7fbded --- /dev/null +++ b/account_credit_hold/models/res_partner.py @@ -0,0 +1,59 @@ +from odoo import fields, models, api, _ +from datetime import date + + +class Partner(models.Model): + _inherit = 'res.partner' + + postpone_hold_until = fields.Date(string="Postpone Hold", + help="Grace period specific to this partner despite unpaid invoices.", ) + + hold_bg = fields.Boolean(string="Hold (technical)", + compute="_compute_hold_bg", + store=True, + default=False) + on_hold = fields.Boolean(string="Account on Hold", + help="Client account is on hold for unpaid overdue invoices.", + compute="_compute_on_hold") + + @api.depends('postpone_hold_until', 'hold_bg') + def _compute_on_hold(self): + # manually re-compute hold_bg since followup_status doesn't get updated in Python but gets recalculated + # by an SQL query every time + self._compute_hold_bg() + for rec in self: + if rec.hold_bg and not (rec.postpone_hold_until and rec.postpone_hold_until > date.today()): + rec.on_hold = True + else: + rec.on_hold = False + + @api.autovacuum + def _cleanup_expired_hold_postponements(self): + expired_holds = self.search([('postpone_hold_until', '<=', date.today())]) + expired_holds.write({'postpone_hold_until': False}) + + def action_credit_hold(self): + message = _('Placed on credit hold') + for rec in self: + rec.hold_bg = True + rec.message_post() + + def _execute_followup_partner(self): + res = super()._execute_followup_partner() + if self.followup_status == 'in_need_of_action': + if self.followup_line_id.account_hold: + self.action_credit_hold() + return res + + # BV: FOR MIGRATION + #@api.depends('followup_status', 'followup_level') + def _compute_hold_bg(self): + first_followup_level = self.env['account_followup.followup.line'].search( + [('company_id', '=', self.env.company.id)], order="delay asc", limit=1) + for rec in self: + prev_hold_bg = rec.hold_bg + level = rec.followup_line_id + if rec.followup_status == 'no_action_needed' and level == first_followup_level: + rec.hold_bg = False + else: + rec.hold_bg = prev_hold_bg diff --git a/account_credit_hold/models/sale_order.py b/account_credit_hold/models/sale_order.py new file mode 100644 index 0000000..390e97e --- /dev/null +++ b/account_credit_hold/models/sale_order.py @@ -0,0 +1,17 @@ +from odoo import fields, models, api, _ +from odoo.exceptions import UserError + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + client_on_hold = fields.Boolean(string='Client on Hold', + help="Whether or not a client has been put on hold due to unpaid invoices.", + related="partner_id.on_hold") + + @api.depends('client_on_hold') + def action_confirm(self): + if any(self.mapped('client_on_hold')): + raise UserError(_("This client is on credit hold. No new orders can be confirmed until past-due invoices " + "are paid or the accounting team postpones the hold.")) + super().action_confirm() diff --git a/account_credit_hold/models/stock_picking.py b/account_credit_hold/models/stock_picking.py new file mode 100644 index 0000000..0d46e32 --- /dev/null +++ b/account_credit_hold/models/stock_picking.py @@ -0,0 +1,9 @@ +from odoo import fields, models, api + + +class ModelName(models.Model): + _inherit = "stock.picking" + + client_on_hold = fields.Boolean(string='Client on Hold', + help="Whether or not a client has been put on hold due to unpaid invoices.", + related="partner_id.on_hold") diff --git a/account_credit_hold/readme.md b/account_credit_hold/readme.md new file mode 100644 index 0000000..b11668c --- /dev/null +++ b/account_credit_hold/readme.md @@ -0,0 +1,35 @@ +# Overview + +This module adds the notion of placing clients on credit hold to the followup levels from the Odoo Enterprise +account_followup module. It adds an option to followup levels to mark clients matching the followup criteria as on +credit hold. This hold restricts the confirmation of new sales orders for these clients. + +Accountant and admin users can set a date until which the account hold will be +postponed on a specific partner's form view. This effectively gives clients an extra +grace period, allowing orders to be confirmed until the period ends. + +# Change Log +## 15.0.2.0.0 (2023-05-04) + +Complete remake of the module, making the "Credit Hold" an action that is either manually or +automatically triggered from the Accounting > Followup Reports section or by setting the automatic application field +on followup levels. + +## 15.0.1.1.0 (2023-05-03) + +Adds a ribbon to stock pickings for clients on hold, and therefore a dependency on stock. + +## 15.0.1.0.2 (2023-05-03) + +Fix to sale order view and sale order confirmation for clients not on hold. + +## 15.0.1.0.1 (2023-05-03) + +Fix clients on hold when status is "outstanding_invoices". + +## 15.0.1.0.0 (2023-05-02) Initial Release + +Initial release of the module, including a setting on follow-up levels to toggle placing on credit hold. Blocks +the confirmation of sales orders for clients on credit hold. Red "Credit Hold" banner appears on sales orders and +partner form view when a client is on credit hold. Credit hold can be postponed by setting the "Postpone Hold" field +on the partner form view. \ No newline at end of file diff --git a/account_credit_hold/static/src/js/followup_form_controller.js b/account_credit_hold/static/src/js/followup_form_controller.js new file mode 100644 index 0000000..39b26d0 --- /dev/null +++ b/account_credit_hold/static/src/js/followup_form_controller.js @@ -0,0 +1,48 @@ +/** @odoo-module **/ + +var FollowupFormController = require('account_followup.FollowupFormController'); +import { patch } from '@web/core/utils/patch'; + +var PatchedController = patch(FollowupFormController.prototype, "followup_form_controller", { + events: _.extend({}, FollowupFormController.prototype.events, { + 'click .o_account_followup_credit_hold_button': '_onCreditHold', + }), + updateButtons() { + this._super(...arguments); + let setButtonClass = (button, primary) => { + /* Set class 'btn-primary' if parameter `primary` is true + * 'btn-secondary' otherwise + */ + let addedClass = primary ? 'btn-primary' : 'btn-secondary' + let removedClass = !primary ? 'btn-secondary' : 'btn-primary' + this.$buttons.find(`button.${button}`) + .removeClass(removedClass).addClass(addedClass); + } + if (!this.$buttons) { + return; + } + let followupLevel = this.model.localData[this.handle].data.followup_level; + setButtonClass('o_account_followup_credit_hold_button', followupLevel.credit_hold); + }, + _onCreditHold: function() { + var self = this; + this.model.doCreditHold(this.handle); + this.options = { + partner_id: this._getPartner() + }; + this._rpc({ + model: 'account.followup.report', + method: 'credit_hold', + args: [this.options], + }).then(function (result) { + self._removeHighlightCreditHold(); + self._displayDone(); + }); + }, + _removeHighlightCreditHold: function() { + this.$buttons.find('button.o_account_followup_credit_hold_button') + .removeClass('btn-primary').addClass('btn-secondary'); + }, +}); + +export { PatchedController }; \ No newline at end of file diff --git a/account_credit_hold/static/src/js/followup_form_model.js b/account_credit_hold/static/src/js/followup_form_model.js new file mode 100644 index 0000000..bd84e76 --- /dev/null +++ b/account_credit_hold/static/src/js/followup_form_model.js @@ -0,0 +1,14 @@ +/** @odoo-module **/ + +var FollowupFormModel = require('account_followup.FollowupFormModel'); +import { patch } from '@web/core/utils/patch'; + +var PatchedModel = patch(FollowupFormModel.prototype, 'followup_form_model', { + doCreditHold: function(handle) { + var level = this.localData[handle].data.followup_level; + if(level && level.credit_hold) { + level.credit_hold = false; + } + }, +}); +export { PatchedModel }; \ No newline at end of file diff --git a/account_credit_hold/static/src/xml/account_followup_template.xml b/account_credit_hold/static/src/xml/account_followup_template.xml new file mode 100644 index 0000000..50f74ee --- /dev/null +++ b/account_credit_hold/static/src/xml/account_followup_template.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/account_credit_hold/views/account_followup_views.xml b/account_credit_hold/views/account_followup_views.xml new file mode 100644 index 0000000..61caad9 --- /dev/null +++ b/account_credit_hold/views/account_followup_views.xml @@ -0,0 +1,16 @@ + + + + + + account_credit_hold.account_followup_line.form + account_followup.followup.line + + + + + + + + + \ No newline at end of file diff --git a/account_credit_hold/views/res_partner_views.xml b/account_credit_hold/views/res_partner_views.xml new file mode 100644 index 0000000..4e86f5e --- /dev/null +++ b/account_credit_hold/views/res_partner_views.xml @@ -0,0 +1,33 @@ + + + + + + account_credit_hold.res_partner.form + res.partner + + + + + + + + + + + account_credit_hold.view_partner_property_form + res.partner + + + + + + + + + + + \ No newline at end of file diff --git a/account_credit_hold/views/sale_order_views.xml b/account_credit_hold/views/sale_order_views.xml new file mode 100644 index 0000000..bf8af69 --- /dev/null +++ b/account_credit_hold/views/sale_order_views.xml @@ -0,0 +1,18 @@ + + + + + + account_credit_hold.sale_order.form + sale.order + + + + + + + + + + \ No newline at end of file diff --git a/account_credit_hold/views/stock_picking_views.xml b/account_credit_hold/views/stock_picking_views.xml new file mode 100644 index 0000000..2b96e89 --- /dev/null +++ b/account_credit_hold/views/stock_picking_views.xml @@ -0,0 +1,20 @@ + + + + + + account_credit_hold.stock_picking.form + stock.picking + + + + + + + + + + + + \ No newline at end of file From 1583e4c324e3320cbfdd4c7a1e0268d163d4d752 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 18 Dec 2023 16:00:49 -0500 Subject: [PATCH 14/96] account_credit_hold migrated to 16.0 --- account_credit_hold/__manifest__.py | 11 +---- .../models/account_followup_report.py | 10 ++-- account_credit_hold/models/res_partner.py | 16 ++++--- .../static/src/js/followup_form_controller.js | 48 ------------------- .../static/src/js/followup_form_model.js | 14 ------ .../src/xml/account_followup_template.xml | 10 ---- .../views/account_followup_views.xml | 38 ++++++++++++++- 7 files changed, 52 insertions(+), 95 deletions(-) delete mode 100644 account_credit_hold/static/src/js/followup_form_controller.js delete mode 100644 account_credit_hold/static/src/js/followup_form_model.js delete mode 100644 account_credit_hold/static/src/xml/account_followup_template.xml diff --git a/account_credit_hold/__manifest__.py b/account_credit_hold/__manifest__.py index 564b9bd..0212a4d 100644 --- a/account_credit_hold/__manifest__.py +++ b/account_credit_hold/__manifest__.py @@ -1,6 +1,6 @@ { 'name': 'Account Credit Hold', - 'version': '15.0.2.0.0.1', + 'version': '16.0.1.0.0', 'summary': 'Allows setting clients on credit hold, blocking the ability confirm a new sales order.', 'description': 'Allows setting clients on hold, blocking the ability confirm a new sales order.', 'category': 'Accounting/Accounting', @@ -15,15 +15,6 @@ 'views/res_partner_views.xml', 'views/stock_picking_views.xml', ], - 'assets': { - 'web.assets_backend': [ - 'account_credit_hold/static/src/js/followup_form_model.js', - 'account_credit_hold/static/src/js/followup_form_controller.js', - ], - 'web.assets_qweb': [ - 'account_credit_hold/static/src/xml/account_followup_template.xml', - ], - }, 'demo': [], 'installable': True, 'auto_install': False diff --git a/account_credit_hold/models/account_followup_report.py b/account_credit_hold/models/account_followup_report.py index 9c9b852..a28efdc 100644 --- a/account_credit_hold/models/account_followup_report.py +++ b/account_credit_hold/models/account_followup_report.py @@ -1,14 +1,12 @@ from odoo import models, fields, api, _ + class FollowUpReport(models.AbstractModel): _inherit = 'account.followup.report' def _get_line_info(self, followup_line): res = super()._get_line_info(followup_line) - res.update({'credit_hold': followup_line.account_hold}) + res.update({ + 'credit_hold': followup_line.account_hold + }) return res - @api.model - def credit_hold(self, options): - partner_id = options['partner_id'] - partner = self.env['res.partner'].browse(partner_id) - partner.action_credit_hold() diff --git a/account_credit_hold/models/res_partner.py b/account_credit_hold/models/res_partner.py index f7fbded..3cc765d 100644 --- a/account_credit_hold/models/res_partner.py +++ b/account_credit_hold/models/res_partner.py @@ -25,6 +25,8 @@ class Partner(models.Model): if rec.hold_bg and not (rec.postpone_hold_until and rec.postpone_hold_until > date.today()): rec.on_hold = True else: + if rec.on_hold: + rec.message_post(_("Credit hold lifted.")) rec.on_hold = False @api.autovacuum @@ -33,10 +35,14 @@ class Partner(models.Model): expired_holds.write({'postpone_hold_until': False}) def action_credit_hold(self): - message = _('Placed on credit hold') for rec in self: rec.hold_bg = True - rec.message_post() + rec.message_post(body=_('Placed on credit hold.')) + + def action_lift_credit_hold(self): + for rec in self: + rec.hold_bg = False + rec.message_post(body=_('Credit hold lifted.')) def _execute_followup_partner(self): res = super()._execute_followup_partner() @@ -45,11 +51,9 @@ class Partner(models.Model): self.action_credit_hold() return res - # BV: FOR MIGRATION - #@api.depends('followup_status', 'followup_level') + @api.depends('followup_status', 'followup_line_id') def _compute_hold_bg(self): - first_followup_level = self.env['account_followup.followup.line'].search( - [('company_id', '=', self.env.company.id)], order="delay asc", limit=1) + first_followup_level = self._get_first_followup_level() for rec in self: prev_hold_bg = rec.hold_bg level = rec.followup_line_id diff --git a/account_credit_hold/static/src/js/followup_form_controller.js b/account_credit_hold/static/src/js/followup_form_controller.js deleted file mode 100644 index 39b26d0..0000000 --- a/account_credit_hold/static/src/js/followup_form_controller.js +++ /dev/null @@ -1,48 +0,0 @@ -/** @odoo-module **/ - -var FollowupFormController = require('account_followup.FollowupFormController'); -import { patch } from '@web/core/utils/patch'; - -var PatchedController = patch(FollowupFormController.prototype, "followup_form_controller", { - events: _.extend({}, FollowupFormController.prototype.events, { - 'click .o_account_followup_credit_hold_button': '_onCreditHold', - }), - updateButtons() { - this._super(...arguments); - let setButtonClass = (button, primary) => { - /* Set class 'btn-primary' if parameter `primary` is true - * 'btn-secondary' otherwise - */ - let addedClass = primary ? 'btn-primary' : 'btn-secondary' - let removedClass = !primary ? 'btn-secondary' : 'btn-primary' - this.$buttons.find(`button.${button}`) - .removeClass(removedClass).addClass(addedClass); - } - if (!this.$buttons) { - return; - } - let followupLevel = this.model.localData[this.handle].data.followup_level; - setButtonClass('o_account_followup_credit_hold_button', followupLevel.credit_hold); - }, - _onCreditHold: function() { - var self = this; - this.model.doCreditHold(this.handle); - this.options = { - partner_id: this._getPartner() - }; - this._rpc({ - model: 'account.followup.report', - method: 'credit_hold', - args: [this.options], - }).then(function (result) { - self._removeHighlightCreditHold(); - self._displayDone(); - }); - }, - _removeHighlightCreditHold: function() { - this.$buttons.find('button.o_account_followup_credit_hold_button') - .removeClass('btn-primary').addClass('btn-secondary'); - }, -}); - -export { PatchedController }; \ No newline at end of file diff --git a/account_credit_hold/static/src/js/followup_form_model.js b/account_credit_hold/static/src/js/followup_form_model.js deleted file mode 100644 index bd84e76..0000000 --- a/account_credit_hold/static/src/js/followup_form_model.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @odoo-module **/ - -var FollowupFormModel = require('account_followup.FollowupFormModel'); -import { patch } from '@web/core/utils/patch'; - -var PatchedModel = patch(FollowupFormModel.prototype, 'followup_form_model', { - doCreditHold: function(handle) { - var level = this.localData[handle].data.followup_level; - if(level && level.credit_hold) { - level.credit_hold = false; - } - }, -}); -export { PatchedModel }; \ No newline at end of file diff --git a/account_credit_hold/static/src/xml/account_followup_template.xml b/account_credit_hold/static/src/xml/account_followup_template.xml deleted file mode 100644 index 50f74ee..0000000 --- a/account_credit_hold/static/src/xml/account_followup_template.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/account_credit_hold/views/account_followup_views.xml b/account_credit_hold/views/account_followup_views.xml index 61caad9..10a7165 100644 --- a/account_credit_hold/views/account_followup_views.xml +++ b/account_credit_hold/views/account_followup_views.xml @@ -8,9 +8,45 @@ - + + + + customer.statements.form.view.inherit + res.partner + + + + + + + + + + + + + \ No newline at end of file diff --git a/bemade_packing_wizard/__manifest__.py b/bemade_packing_wizard/__manifest__.py index 41b136d..124c309 100644 --- a/bemade_packing_wizard/__manifest__.py +++ b/bemade_packing_wizard/__manifest__.py @@ -1,12 +1,12 @@ { 'name': 'Packing wizard', - 'version': '15.0.1.0.0', + 'version': '16.0.1.0.0', 'category': 'Extra Tools', 'summary': 'Allow automated packing type creation', 'description': """ This module allows users simply enter all the package dimensions on every packing and it will create the packing type automatically if it not exists, use it the create the package with the weight and related package type. - + You need to activate the auto create package feature on the delivery carrier to use this feature. """, 'depends': [ From e0bde4dcbc49eac8372088e4ba8321db8a673fc5 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Wed, 3 Jan 2024 17:41:51 -0500 Subject: [PATCH 18/96] bemade_stock_quant_valuation to 16.0 --- bemade_stock_quant_valuation/__manifest__.py | 2 +- temporary_change_image_size/__manifest__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bemade_stock_quant_valuation/__manifest__.py b/bemade_stock_quant_valuation/__manifest__.py index 19ffd69..05a8fca 100644 --- a/bemade_stock_quant_valuation/__manifest__.py +++ b/bemade_stock_quant_valuation/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Stock Quant Valuation', - 'version': '15.0.1.0.0', + 'version': '16.0.1.0.0', 'summary': 'Adds valuation to stock quant for better inventory adjustment management', 'description': '', 'category': 'Inventory', diff --git a/temporary_change_image_size/__manifest__.py b/temporary_change_image_size/__manifest__.py index 54a9ac5..611f8cf 100644 --- a/temporary_change_image_size/__manifest__.py +++ b/temporary_change_image_size/__manifest__.py @@ -1,6 +1,6 @@ { 'name': 'Temporary Change for Image Full Size', - 'version': '15.0.0.0.0', + 'version': '16.0.0.0.0', 'category': 'Extra Tools', 'summary': 'Temporary Change for Image Full Size', 'description': """ From 7f775779e3635406646732a522278fe61be5f2b0 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Wed, 3 Jan 2024 17:46:07 -0500 Subject: [PATCH 19/96] [MIG] bemade_partner_email_domain to 16.0 --- bemade_partner_email_domain/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bemade_partner_email_domain/__manifest__.py b/bemade_partner_email_domain/__manifest__.py index 5047c18..9f8fbe9 100644 --- a/bemade_partner_email_domain/__manifest__.py +++ b/bemade_partner_email_domain/__manifest__.py @@ -1,6 +1,6 @@ { 'name': 'Automated Partner Association by Email Domain', - 'version': '15.0.0.0.0', + 'version': '16.0.0.0.0', 'category': 'Extra Tools', 'summary': 'Automatically associates partners with companies using matching email domains', 'description': """ From e96bcadaed383da6eb34f4e75902adced1e7558a Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 11 Dec 2023 18:23:31 -0500 Subject: [PATCH 20/96] [ENH] bemade_sports_clinic: wrap text on the portal and show HTML. Allows portal users to see the full diagnosis and notes. Previously, diagnosis was truncated if it went beyond the bounds of the column. Also, notes are now shown in HTML instead of HTML escaped to text. --- bemade_sports_clinic/__manifest__.py | 2 +- bemade_sports_clinic/views/sports_clinic_portal_views.xml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bemade_sports_clinic/__manifest__.py b/bemade_sports_clinic/__manifest__.py index 8b604e0..f1689fd 100644 --- a/bemade_sports_clinic/__manifest__.py +++ b/bemade_sports_clinic/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Sports Clinic Management', - 'version': '16.0.1.5.0', + 'version': '16.0.1.5.1', 'summary': 'Manage the patients of a sports medicine clinic.', 'description': """ Adds the notion of sports teams, players (patients), coaches and treatment diff --git a/bemade_sports_clinic/views/sports_clinic_portal_views.xml b/bemade_sports_clinic/views/sports_clinic_portal_views.xml index a91b59e..63d0cb7 100644 --- a/bemade_sports_clinic/views/sports_clinic_portal_views.xml +++ b/bemade_sports_clinic/views/sports_clinic_portal_views.xml @@ -165,18 +165,18 @@ - Active Injury - Notes + Active Injury + Notes - + - + From 1ca241fafb93588ae5dc93281e8f18acc3a6793b Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 11 Dec 2023 21:30:08 -0500 Subject: [PATCH 21/96] [ENH] bemade_sports_clinic: Kanban view created to enhance mobile. Kanban view added for players to improve the experience when browsing on mobile. Card text color synchronized with what the user expects from the list view. --- bemade_sports_clinic/__manifest__.py | 2 +- bemade_sports_clinic/models/patient.py | 2 +- .../views/sports_patient_views.xml | 43 +++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/bemade_sports_clinic/__manifest__.py b/bemade_sports_clinic/__manifest__.py index f1689fd..81b355f 100644 --- a/bemade_sports_clinic/__manifest__.py +++ b/bemade_sports_clinic/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Sports Clinic Management', - 'version': '16.0.1.5.1', + 'version': '16.0.1.5.2', 'summary': 'Manage the patients of a sports medicine clinic.', 'description': """ Adds the notion of sports teams, players (patients), coaches and treatment diff --git a/bemade_sports_clinic/models/patient.py b/bemade_sports_clinic/models/patient.py index a15db38..201bea2 100644 --- a/bemade_sports_clinic/models/patient.py +++ b/bemade_sports_clinic/models/patient.py @@ -61,7 +61,7 @@ class Patient(models.Model): "return to match play.") is_injured = fields.Boolean(compute="_compute_is_injured") stage = fields.Selection( - selection=[('no_play', 'Injured'), ('practice_ok', 'Cleared for Practice'), ('healthy', 'Cleared to Play')], + selection=[('no_play', 'Injured'), ('practice_ok', 'Practice OK'), ('healthy', 'Play OK')], compute='_compute_stage') last_consultation_date = fields.Date() active_injury_count = fields.Integer(compute='_compute_active_injury_count') diff --git a/bemade_sports_clinic/views/sports_patient_views.xml b/bemade_sports_clinic/views/sports_patient_views.xml index 6157357..3b1fccf 100644 --- a/bemade_sports_clinic/views/sports_patient_views.xml +++ b/bemade_sports_clinic/views/sports_patient_views.xml @@ -62,6 +62,49 @@ + + sports.patient.view.kanban + sports.patient + + + + + + + + + + + + + + + + +
+ +
+
+
+ +
+
+ Status: +
+
+
+ DOB: + +
+
+
+
+
+
+
+
+ sports.patient.view.form sports.patient From 90989e366904390530d3e081813fdd196fd7dc62 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Fri, 22 Dec 2023 09:53:47 -0500 Subject: [PATCH 22/96] add module for payslip showing up as to pay when 'done' --- bemade_payslip_done_as_not_paid/__init__.py | 0 .../__manifest__.py | 31 +++++++++++++++++++ .../views/hr_payslip_views.xml | 6 ++++ 3 files changed, 37 insertions(+) create mode 100644 bemade_payslip_done_as_not_paid/__init__.py create mode 100644 bemade_payslip_done_as_not_paid/__manifest__.py create mode 100644 bemade_payslip_done_as_not_paid/views/hr_payslip_views.xml diff --git a/bemade_payslip_done_as_not_paid/__init__.py b/bemade_payslip_done_as_not_paid/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bemade_payslip_done_as_not_paid/__manifest__.py b/bemade_payslip_done_as_not_paid/__manifest__.py new file mode 100644 index 0000000..e5e382b --- /dev/null +++ b/bemade_payslip_done_as_not_paid/__manifest__.py @@ -0,0 +1,31 @@ +# +# Bemade Inc. +# +# Copyright (C) 2023-June Bemade Inc. (). +# Author: Marc Durepos (Contact : marc@bemade.org) +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +{ + 'name': 'Payslip Done as To Pay', + 'version': '16.0.1.0.0', + 'summary': 'Payslips in "Done" state appear as "To Pay"', + 'category': 'Human Resources/Payroll', + 'author': 'Bemade Inc.', + 'website': 'http://www.bemade.org', + 'license': 'OPL-1', + 'depends': ['hr_payroll'], + 'data': ['views/hr_payslip_views.xml'], + 'installable': True, + 'auto_install': True, +} diff --git a/bemade_payslip_done_as_not_paid/views/hr_payslip_views.xml b/bemade_payslip_done_as_not_paid/views/hr_payslip_views.xml new file mode 100644 index 0000000..14fda51 --- /dev/null +++ b/bemade_payslip_done_as_not_paid/views/hr_payslip_views.xml @@ -0,0 +1,6 @@ + + + + [('state', 'in', ['draft', 'verify', 'done'])] + + \ No newline at end of file From 6ec7dfefa97a3c21d9eb065a3c7f5a6f21b73697 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 18 Dec 2023 15:20:33 -0500 Subject: [PATCH 23/96] move account_credit_hold into bemade-addons --- account_credit_hold/__init__.py | 1 + account_credit_hold/__manifest__.py | 30 ++++++++++ account_credit_hold/models/__init__.py | 5 ++ .../models/account_followup.py | 8 +++ .../models/account_followup_report.py | 14 +++++ account_credit_hold/models/res_partner.py | 59 +++++++++++++++++++ account_credit_hold/models/sale_order.py | 17 ++++++ account_credit_hold/models/stock_picking.py | 9 +++ account_credit_hold/readme.md | 35 +++++++++++ .../static/src/js/followup_form_controller.js | 48 +++++++++++++++ .../static/src/js/followup_form_model.js | 14 +++++ .../src/xml/account_followup_template.xml | 10 ++++ .../views/account_followup_views.xml | 16 +++++ .../views/res_partner_views.xml | 33 +++++++++++ .../views/sale_order_views.xml | 18 ++++++ .../views/stock_picking_views.xml | 20 +++++++ 16 files changed, 337 insertions(+) create mode 100644 account_credit_hold/__init__.py create mode 100644 account_credit_hold/__manifest__.py create mode 100644 account_credit_hold/models/__init__.py create mode 100644 account_credit_hold/models/account_followup.py create mode 100644 account_credit_hold/models/account_followup_report.py create mode 100644 account_credit_hold/models/res_partner.py create mode 100644 account_credit_hold/models/sale_order.py create mode 100644 account_credit_hold/models/stock_picking.py create mode 100644 account_credit_hold/readme.md create mode 100644 account_credit_hold/static/src/js/followup_form_controller.js create mode 100644 account_credit_hold/static/src/js/followup_form_model.js create mode 100644 account_credit_hold/static/src/xml/account_followup_template.xml create mode 100644 account_credit_hold/views/account_followup_views.xml create mode 100644 account_credit_hold/views/res_partner_views.xml create mode 100644 account_credit_hold/views/sale_order_views.xml create mode 100644 account_credit_hold/views/stock_picking_views.xml diff --git a/account_credit_hold/__init__.py b/account_credit_hold/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/account_credit_hold/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_credit_hold/__manifest__.py b/account_credit_hold/__manifest__.py new file mode 100644 index 0000000..564b9bd --- /dev/null +++ b/account_credit_hold/__manifest__.py @@ -0,0 +1,30 @@ +{ + 'name': 'Account Credit Hold', + 'version': '15.0.2.0.0.1', + 'summary': 'Allows setting clients on credit hold, blocking the ability confirm a new sales order.', + 'description': 'Allows setting clients on hold, blocking the ability confirm a new sales order.', + 'category': 'Accounting/Accounting', + 'author': 'Bemade Inc.', + 'maintainer': 'Marc Durepos ', + 'website': 'http://www.bemade.org', + 'license': 'LGPL-3', + 'depends': ['sale', 'account_followup', 'stock'], + 'data': [ + 'views/account_followup_views.xml', + 'views/sale_order_views.xml', + 'views/res_partner_views.xml', + 'views/stock_picking_views.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'account_credit_hold/static/src/js/followup_form_model.js', + 'account_credit_hold/static/src/js/followup_form_controller.js', + ], + 'web.assets_qweb': [ + 'account_credit_hold/static/src/xml/account_followup_template.xml', + ], + }, + 'demo': [], + 'installable': True, + 'auto_install': False +} diff --git a/account_credit_hold/models/__init__.py b/account_credit_hold/models/__init__.py new file mode 100644 index 0000000..0c2c11c --- /dev/null +++ b/account_credit_hold/models/__init__.py @@ -0,0 +1,5 @@ +from . import account_followup +from . import res_partner +from . import sale_order +from . import stock_picking +from . import account_followup_report diff --git a/account_credit_hold/models/account_followup.py b/account_credit_hold/models/account_followup.py new file mode 100644 index 0000000..5af3363 --- /dev/null +++ b/account_credit_hold/models/account_followup.py @@ -0,0 +1,8 @@ +from odoo import fields, models, api + + +class FollowupLine(models.Model): + _inherit = 'account_followup.followup.line' + + account_hold = fields.Boolean(string="Place on Credit Hold", + help="Place clients on account hold, restricting confirmation of new orders.") diff --git a/account_credit_hold/models/account_followup_report.py b/account_credit_hold/models/account_followup_report.py new file mode 100644 index 0000000..9c9b852 --- /dev/null +++ b/account_credit_hold/models/account_followup_report.py @@ -0,0 +1,14 @@ +from odoo import models, fields, api, _ + +class FollowUpReport(models.AbstractModel): + _inherit = 'account.followup.report' + + def _get_line_info(self, followup_line): + res = super()._get_line_info(followup_line) + res.update({'credit_hold': followup_line.account_hold}) + return res + @api.model + def credit_hold(self, options): + partner_id = options['partner_id'] + partner = self.env['res.partner'].browse(partner_id) + partner.action_credit_hold() diff --git a/account_credit_hold/models/res_partner.py b/account_credit_hold/models/res_partner.py new file mode 100644 index 0000000..f7fbded --- /dev/null +++ b/account_credit_hold/models/res_partner.py @@ -0,0 +1,59 @@ +from odoo import fields, models, api, _ +from datetime import date + + +class Partner(models.Model): + _inherit = 'res.partner' + + postpone_hold_until = fields.Date(string="Postpone Hold", + help="Grace period specific to this partner despite unpaid invoices.", ) + + hold_bg = fields.Boolean(string="Hold (technical)", + compute="_compute_hold_bg", + store=True, + default=False) + on_hold = fields.Boolean(string="Account on Hold", + help="Client account is on hold for unpaid overdue invoices.", + compute="_compute_on_hold") + + @api.depends('postpone_hold_until', 'hold_bg') + def _compute_on_hold(self): + # manually re-compute hold_bg since followup_status doesn't get updated in Python but gets recalculated + # by an SQL query every time + self._compute_hold_bg() + for rec in self: + if rec.hold_bg and not (rec.postpone_hold_until and rec.postpone_hold_until > date.today()): + rec.on_hold = True + else: + rec.on_hold = False + + @api.autovacuum + def _cleanup_expired_hold_postponements(self): + expired_holds = self.search([('postpone_hold_until', '<=', date.today())]) + expired_holds.write({'postpone_hold_until': False}) + + def action_credit_hold(self): + message = _('Placed on credit hold') + for rec in self: + rec.hold_bg = True + rec.message_post() + + def _execute_followup_partner(self): + res = super()._execute_followup_partner() + if self.followup_status == 'in_need_of_action': + if self.followup_line_id.account_hold: + self.action_credit_hold() + return res + + # BV: FOR MIGRATION + #@api.depends('followup_status', 'followup_level') + def _compute_hold_bg(self): + first_followup_level = self.env['account_followup.followup.line'].search( + [('company_id', '=', self.env.company.id)], order="delay asc", limit=1) + for rec in self: + prev_hold_bg = rec.hold_bg + level = rec.followup_line_id + if rec.followup_status == 'no_action_needed' and level == first_followup_level: + rec.hold_bg = False + else: + rec.hold_bg = prev_hold_bg diff --git a/account_credit_hold/models/sale_order.py b/account_credit_hold/models/sale_order.py new file mode 100644 index 0000000..390e97e --- /dev/null +++ b/account_credit_hold/models/sale_order.py @@ -0,0 +1,17 @@ +from odoo import fields, models, api, _ +from odoo.exceptions import UserError + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + client_on_hold = fields.Boolean(string='Client on Hold', + help="Whether or not a client has been put on hold due to unpaid invoices.", + related="partner_id.on_hold") + + @api.depends('client_on_hold') + def action_confirm(self): + if any(self.mapped('client_on_hold')): + raise UserError(_("This client is on credit hold. No new orders can be confirmed until past-due invoices " + "are paid or the accounting team postpones the hold.")) + super().action_confirm() diff --git a/account_credit_hold/models/stock_picking.py b/account_credit_hold/models/stock_picking.py new file mode 100644 index 0000000..0d46e32 --- /dev/null +++ b/account_credit_hold/models/stock_picking.py @@ -0,0 +1,9 @@ +from odoo import fields, models, api + + +class ModelName(models.Model): + _inherit = "stock.picking" + + client_on_hold = fields.Boolean(string='Client on Hold', + help="Whether or not a client has been put on hold due to unpaid invoices.", + related="partner_id.on_hold") diff --git a/account_credit_hold/readme.md b/account_credit_hold/readme.md new file mode 100644 index 0000000..b11668c --- /dev/null +++ b/account_credit_hold/readme.md @@ -0,0 +1,35 @@ +# Overview + +This module adds the notion of placing clients on credit hold to the followup levels from the Odoo Enterprise +account_followup module. It adds an option to followup levels to mark clients matching the followup criteria as on +credit hold. This hold restricts the confirmation of new sales orders for these clients. + +Accountant and admin users can set a date until which the account hold will be +postponed on a specific partner's form view. This effectively gives clients an extra +grace period, allowing orders to be confirmed until the period ends. + +# Change Log +## 15.0.2.0.0 (2023-05-04) + +Complete remake of the module, making the "Credit Hold" an action that is either manually or +automatically triggered from the Accounting > Followup Reports section or by setting the automatic application field +on followup levels. + +## 15.0.1.1.0 (2023-05-03) + +Adds a ribbon to stock pickings for clients on hold, and therefore a dependency on stock. + +## 15.0.1.0.2 (2023-05-03) + +Fix to sale order view and sale order confirmation for clients not on hold. + +## 15.0.1.0.1 (2023-05-03) + +Fix clients on hold when status is "outstanding_invoices". + +## 15.0.1.0.0 (2023-05-02) Initial Release + +Initial release of the module, including a setting on follow-up levels to toggle placing on credit hold. Blocks +the confirmation of sales orders for clients on credit hold. Red "Credit Hold" banner appears on sales orders and +partner form view when a client is on credit hold. Credit hold can be postponed by setting the "Postpone Hold" field +on the partner form view. \ No newline at end of file diff --git a/account_credit_hold/static/src/js/followup_form_controller.js b/account_credit_hold/static/src/js/followup_form_controller.js new file mode 100644 index 0000000..39b26d0 --- /dev/null +++ b/account_credit_hold/static/src/js/followup_form_controller.js @@ -0,0 +1,48 @@ +/** @odoo-module **/ + +var FollowupFormController = require('account_followup.FollowupFormController'); +import { patch } from '@web/core/utils/patch'; + +var PatchedController = patch(FollowupFormController.prototype, "followup_form_controller", { + events: _.extend({}, FollowupFormController.prototype.events, { + 'click .o_account_followup_credit_hold_button': '_onCreditHold', + }), + updateButtons() { + this._super(...arguments); + let setButtonClass = (button, primary) => { + /* Set class 'btn-primary' if parameter `primary` is true + * 'btn-secondary' otherwise + */ + let addedClass = primary ? 'btn-primary' : 'btn-secondary' + let removedClass = !primary ? 'btn-secondary' : 'btn-primary' + this.$buttons.find(`button.${button}`) + .removeClass(removedClass).addClass(addedClass); + } + if (!this.$buttons) { + return; + } + let followupLevel = this.model.localData[this.handle].data.followup_level; + setButtonClass('o_account_followup_credit_hold_button', followupLevel.credit_hold); + }, + _onCreditHold: function() { + var self = this; + this.model.doCreditHold(this.handle); + this.options = { + partner_id: this._getPartner() + }; + this._rpc({ + model: 'account.followup.report', + method: 'credit_hold', + args: [this.options], + }).then(function (result) { + self._removeHighlightCreditHold(); + self._displayDone(); + }); + }, + _removeHighlightCreditHold: function() { + this.$buttons.find('button.o_account_followup_credit_hold_button') + .removeClass('btn-primary').addClass('btn-secondary'); + }, +}); + +export { PatchedController }; \ No newline at end of file diff --git a/account_credit_hold/static/src/js/followup_form_model.js b/account_credit_hold/static/src/js/followup_form_model.js new file mode 100644 index 0000000..bd84e76 --- /dev/null +++ b/account_credit_hold/static/src/js/followup_form_model.js @@ -0,0 +1,14 @@ +/** @odoo-module **/ + +var FollowupFormModel = require('account_followup.FollowupFormModel'); +import { patch } from '@web/core/utils/patch'; + +var PatchedModel = patch(FollowupFormModel.prototype, 'followup_form_model', { + doCreditHold: function(handle) { + var level = this.localData[handle].data.followup_level; + if(level && level.credit_hold) { + level.credit_hold = false; + } + }, +}); +export { PatchedModel }; \ No newline at end of file diff --git a/account_credit_hold/static/src/xml/account_followup_template.xml b/account_credit_hold/static/src/xml/account_followup_template.xml new file mode 100644 index 0000000..50f74ee --- /dev/null +++ b/account_credit_hold/static/src/xml/account_followup_template.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/account_credit_hold/views/account_followup_views.xml b/account_credit_hold/views/account_followup_views.xml new file mode 100644 index 0000000..61caad9 --- /dev/null +++ b/account_credit_hold/views/account_followup_views.xml @@ -0,0 +1,16 @@ + + + + + + account_credit_hold.account_followup_line.form + account_followup.followup.line + + + + + + + + + \ No newline at end of file diff --git a/account_credit_hold/views/res_partner_views.xml b/account_credit_hold/views/res_partner_views.xml new file mode 100644 index 0000000..4e86f5e --- /dev/null +++ b/account_credit_hold/views/res_partner_views.xml @@ -0,0 +1,33 @@ + + + + + + account_credit_hold.res_partner.form + res.partner + + + + + + + + + + + account_credit_hold.view_partner_property_form + res.partner + + + + + + + + + + + \ No newline at end of file diff --git a/account_credit_hold/views/sale_order_views.xml b/account_credit_hold/views/sale_order_views.xml new file mode 100644 index 0000000..bf8af69 --- /dev/null +++ b/account_credit_hold/views/sale_order_views.xml @@ -0,0 +1,18 @@ + + + + + + account_credit_hold.sale_order.form + sale.order + + + + + + + + + + \ No newline at end of file diff --git a/account_credit_hold/views/stock_picking_views.xml b/account_credit_hold/views/stock_picking_views.xml new file mode 100644 index 0000000..2b96e89 --- /dev/null +++ b/account_credit_hold/views/stock_picking_views.xml @@ -0,0 +1,20 @@ + + + + + + account_credit_hold.stock_picking.form + stock.picking + + + + + + + + + + + + \ No newline at end of file From be0af4dc176b6eae3b9b0f479043b0cea2dd0b03 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 18 Dec 2023 16:00:49 -0500 Subject: [PATCH 24/96] account_credit_hold migrated to 16.0 --- account_credit_hold/__manifest__.py | 11 +---- .../models/account_followup_report.py | 10 ++-- account_credit_hold/models/res_partner.py | 16 ++++--- .../static/src/js/followup_form_controller.js | 48 ------------------- .../static/src/js/followup_form_model.js | 14 ------ .../src/xml/account_followup_template.xml | 10 ---- .../views/account_followup_views.xml | 38 ++++++++++++++- 7 files changed, 52 insertions(+), 95 deletions(-) delete mode 100644 account_credit_hold/static/src/js/followup_form_controller.js delete mode 100644 account_credit_hold/static/src/js/followup_form_model.js delete mode 100644 account_credit_hold/static/src/xml/account_followup_template.xml diff --git a/account_credit_hold/__manifest__.py b/account_credit_hold/__manifest__.py index 564b9bd..0212a4d 100644 --- a/account_credit_hold/__manifest__.py +++ b/account_credit_hold/__manifest__.py @@ -1,6 +1,6 @@ { 'name': 'Account Credit Hold', - 'version': '15.0.2.0.0.1', + 'version': '16.0.1.0.0', 'summary': 'Allows setting clients on credit hold, blocking the ability confirm a new sales order.', 'description': 'Allows setting clients on hold, blocking the ability confirm a new sales order.', 'category': 'Accounting/Accounting', @@ -15,15 +15,6 @@ 'views/res_partner_views.xml', 'views/stock_picking_views.xml', ], - 'assets': { - 'web.assets_backend': [ - 'account_credit_hold/static/src/js/followup_form_model.js', - 'account_credit_hold/static/src/js/followup_form_controller.js', - ], - 'web.assets_qweb': [ - 'account_credit_hold/static/src/xml/account_followup_template.xml', - ], - }, 'demo': [], 'installable': True, 'auto_install': False diff --git a/account_credit_hold/models/account_followup_report.py b/account_credit_hold/models/account_followup_report.py index 9c9b852..a28efdc 100644 --- a/account_credit_hold/models/account_followup_report.py +++ b/account_credit_hold/models/account_followup_report.py @@ -1,14 +1,12 @@ from odoo import models, fields, api, _ + class FollowUpReport(models.AbstractModel): _inherit = 'account.followup.report' def _get_line_info(self, followup_line): res = super()._get_line_info(followup_line) - res.update({'credit_hold': followup_line.account_hold}) + res.update({ + 'credit_hold': followup_line.account_hold + }) return res - @api.model - def credit_hold(self, options): - partner_id = options['partner_id'] - partner = self.env['res.partner'].browse(partner_id) - partner.action_credit_hold() diff --git a/account_credit_hold/models/res_partner.py b/account_credit_hold/models/res_partner.py index f7fbded..3cc765d 100644 --- a/account_credit_hold/models/res_partner.py +++ b/account_credit_hold/models/res_partner.py @@ -25,6 +25,8 @@ class Partner(models.Model): if rec.hold_bg and not (rec.postpone_hold_until and rec.postpone_hold_until > date.today()): rec.on_hold = True else: + if rec.on_hold: + rec.message_post(_("Credit hold lifted.")) rec.on_hold = False @api.autovacuum @@ -33,10 +35,14 @@ class Partner(models.Model): expired_holds.write({'postpone_hold_until': False}) def action_credit_hold(self): - message = _('Placed on credit hold') for rec in self: rec.hold_bg = True - rec.message_post() + rec.message_post(body=_('Placed on credit hold.')) + + def action_lift_credit_hold(self): + for rec in self: + rec.hold_bg = False + rec.message_post(body=_('Credit hold lifted.')) def _execute_followup_partner(self): res = super()._execute_followup_partner() @@ -45,11 +51,9 @@ class Partner(models.Model): self.action_credit_hold() return res - # BV: FOR MIGRATION - #@api.depends('followup_status', 'followup_level') + @api.depends('followup_status', 'followup_line_id') def _compute_hold_bg(self): - first_followup_level = self.env['account_followup.followup.line'].search( - [('company_id', '=', self.env.company.id)], order="delay asc", limit=1) + first_followup_level = self._get_first_followup_level() for rec in self: prev_hold_bg = rec.hold_bg level = rec.followup_line_id diff --git a/account_credit_hold/static/src/js/followup_form_controller.js b/account_credit_hold/static/src/js/followup_form_controller.js deleted file mode 100644 index 39b26d0..0000000 --- a/account_credit_hold/static/src/js/followup_form_controller.js +++ /dev/null @@ -1,48 +0,0 @@ -/** @odoo-module **/ - -var FollowupFormController = require('account_followup.FollowupFormController'); -import { patch } from '@web/core/utils/patch'; - -var PatchedController = patch(FollowupFormController.prototype, "followup_form_controller", { - events: _.extend({}, FollowupFormController.prototype.events, { - 'click .o_account_followup_credit_hold_button': '_onCreditHold', - }), - updateButtons() { - this._super(...arguments); - let setButtonClass = (button, primary) => { - /* Set class 'btn-primary' if parameter `primary` is true - * 'btn-secondary' otherwise - */ - let addedClass = primary ? 'btn-primary' : 'btn-secondary' - let removedClass = !primary ? 'btn-secondary' : 'btn-primary' - this.$buttons.find(`button.${button}`) - .removeClass(removedClass).addClass(addedClass); - } - if (!this.$buttons) { - return; - } - let followupLevel = this.model.localData[this.handle].data.followup_level; - setButtonClass('o_account_followup_credit_hold_button', followupLevel.credit_hold); - }, - _onCreditHold: function() { - var self = this; - this.model.doCreditHold(this.handle); - this.options = { - partner_id: this._getPartner() - }; - this._rpc({ - model: 'account.followup.report', - method: 'credit_hold', - args: [this.options], - }).then(function (result) { - self._removeHighlightCreditHold(); - self._displayDone(); - }); - }, - _removeHighlightCreditHold: function() { - this.$buttons.find('button.o_account_followup_credit_hold_button') - .removeClass('btn-primary').addClass('btn-secondary'); - }, -}); - -export { PatchedController }; \ No newline at end of file diff --git a/account_credit_hold/static/src/js/followup_form_model.js b/account_credit_hold/static/src/js/followup_form_model.js deleted file mode 100644 index bd84e76..0000000 --- a/account_credit_hold/static/src/js/followup_form_model.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @odoo-module **/ - -var FollowupFormModel = require('account_followup.FollowupFormModel'); -import { patch } from '@web/core/utils/patch'; - -var PatchedModel = patch(FollowupFormModel.prototype, 'followup_form_model', { - doCreditHold: function(handle) { - var level = this.localData[handle].data.followup_level; - if(level && level.credit_hold) { - level.credit_hold = false; - } - }, -}); -export { PatchedModel }; \ No newline at end of file diff --git a/account_credit_hold/static/src/xml/account_followup_template.xml b/account_credit_hold/static/src/xml/account_followup_template.xml deleted file mode 100644 index 50f74ee..0000000 --- a/account_credit_hold/static/src/xml/account_followup_template.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/account_credit_hold/views/account_followup_views.xml b/account_credit_hold/views/account_followup_views.xml index 61caad9..10a7165 100644 --- a/account_credit_hold/views/account_followup_views.xml +++ b/account_credit_hold/views/account_followup_views.xml @@ -8,9 +8,45 @@ - + + + + customer.statements.form.view.inherit + res.partner + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bemade_fsm/views/task_views.xml b/bemade_fsm/views/task_views.xml index ddc48b8..c1d9a1b 100644 --- a/bemade_fsm/views/task_views.xml +++ b/bemade_fsm/views/task_views.xml @@ -168,4 +168,4 @@ - \ No newline at end of file + diff --git a/bemade_fsm/wizard/new_task_from_template.py b/bemade_fsm/wizard/new_task_from_template.py index 575629c..26d67ba 100644 --- a/bemade_fsm/wizard/new_task_from_template.py +++ b/bemade_fsm/wizard/new_task_from_template.py @@ -4,6 +4,7 @@ from odoo.exceptions import UserError class NewTaskFromTemplateWizard(models.TransientModel): _name = "project.task.from.template.wizard" + _description = "Create Task from Template Wizard" project_id = fields.Many2one( comodel_name='project.project', @@ -25,9 +26,16 @@ class NewTaskFromTemplateWizard(models.TransientModel): def default_get(self, fields_list): res = super().default_get(fields_list) - if 'project_id' in fields_list: - active_id = self.env.context.get('active_id', False) - res.update({'project_id': active_id}) + active_id = self.env.context.get('active_id', False) + active_model = self.env.context.get('active_model', False) + if not active_model: + params = self.env.context.get('params', False) + active_model = params.get('model', False) + + if active_model == 'project.task.template' and active_id and 'task_template_id' in fields_list: + res.update({'task_template_id': active_id}) + if active_model == 'project.task' and 'project_id' in fields_list: + res.update({'project_id': self.env.ref('industry_fsm.fsm_project').id}) return res def action_create_task_from_template(self): diff --git a/bemade_fsm/wizard/new_task_from_template.xml b/bemade_fsm/wizard/new_task_from_template.xml index 49a22ce..1290b8f 100644 --- a/bemade_fsm/wizard/new_task_from_template.xml +++ b/bemade_fsm/wizard/new_task_from_template.xml @@ -5,10 +5,6 @@ project.task.from.template.wizard
-
-
@@ -16,7 +12,18 @@ +
+
+ + New Task from Template + project.task.from.template.wizard + + form + new + \ No newline at end of file From 87b4f21d20fa6535550499725c364eb70cc14bf2 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 11:16:10 -0500 Subject: [PATCH 28/96] bemade_full_formview_from_modal: remove useless lines of JS. --- .../static/src/js/form_view_dialog.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js b/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js index e94ad00..fbb2b83 100644 --- a/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js +++ b/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js @@ -11,9 +11,6 @@ patch(Dialog.prototype, "bemade_full_formview_from_modal.Dialog", { init: function (parent, options) { this._super(...arguments); }, - custom_events: _.extend({}, Dialog.prototype.custom_events, { - open_full_form_view: '_onOpen', - }), willStart: function () { const self = this; return this._super(...arguments).then(function () { From a7965008cccba5ea67d4e0a0dfa4ba31423c2639 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 11:19:16 -0500 Subject: [PATCH 29/96] version bump for bemade_fsm --- bemade_fsm/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index b45d3c4..8df780e 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.0', + 'version': '15.0.1.0.4', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', From ddf0ad80adc77431fb50f089ce6e26649f062816 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 11:43:24 -0500 Subject: [PATCH 30/96] bemade_fsm: bug fix in new_task_from_template.py default_get --- bemade_fsm/wizard/new_task_from_template.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bemade_fsm/wizard/new_task_from_template.py b/bemade_fsm/wizard/new_task_from_template.py index 26d67ba..6c8c5e1 100644 --- a/bemade_fsm/wizard/new_task_from_template.py +++ b/bemade_fsm/wizard/new_task_from_template.py @@ -30,8 +30,7 @@ class NewTaskFromTemplateWizard(models.TransientModel): active_model = self.env.context.get('active_model', False) if not active_model: params = self.env.context.get('params', False) - active_model = params.get('model', False) - + active_model = params and params.get('model', False) if active_model == 'project.task.template' and active_id and 'task_template_id' in fields_list: res.update({'task_template_id': active_id}) if active_model == 'project.task' and 'project_id' in fields_list: From 16a45118ea6261d33343ecdc77be7b20f9a07ce9 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 12:11:48 -0500 Subject: [PATCH 31/96] Fixed new task from template wizard to show right default project. --- bemade_fsm/static/src/js/kanban_view.js | 2 +- bemade_fsm/static/src/js/list_view.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bemade_fsm/static/src/js/kanban_view.js b/bemade_fsm/static/src/js/kanban_view.js index 2185d01..7f99dcc 100644 --- a/bemade_fsm/static/src/js/kanban_view.js +++ b/bemade_fsm/static/src/js/kanban_view.js @@ -19,7 +19,7 @@ const ProjectKanbanController = KanbanController.extend({ res_model: 'project.task.from.template.wizard', views: [[false, 'form']], target: 'new', - context: {...record.context, active_id: record.project_id}, + context: {...record.context, res_model: 'project.task'}, }); }, renderButtons ($node) { diff --git a/bemade_fsm/static/src/js/list_view.js b/bemade_fsm/static/src/js/list_view.js index 3486965..dc60c3a 100644 --- a/bemade_fsm/static/src/js/list_view.js +++ b/bemade_fsm/static/src/js/list_view.js @@ -17,7 +17,7 @@ const ProjectListController = ListController.extend({ res_model: 'project.task.from.template.wizard', views: [[false, 'form']], target: 'new', - context: {...record.context, active_id: record.project_id}, + context: {...record.context, res_model: 'project.task'}, }); }, renderButtons ($node) { From 2643f5007fad5146f269d95b7d6cc74bc47f44f2 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 12:23:38 -0500 Subject: [PATCH 32/96] bemade_fsm: spacing for task from template button, delete js tests. --- .../static/src/xml/project_view_buttons.xml | 2 +- .../static/tests/tours/equipment_tour.js | 104 ------------------ .../static/tests/tours/sale_order_tour.js | 40 ------- .../static/tests/tours/task_equipment_tour.js | 75 ------------- .../static/tests/tours/task_template_tour.js | 47 -------- 5 files changed, 1 insertion(+), 267 deletions(-) delete mode 100644 bemade_fsm/static/tests/tours/equipment_tour.js delete mode 100644 bemade_fsm/static/tests/tours/sale_order_tour.js delete mode 100644 bemade_fsm/static/tests/tours/task_equipment_tour.js delete mode 100644 bemade_fsm/static/tests/tours/task_template_tour.js diff --git a/bemade_fsm/static/src/xml/project_view_buttons.xml b/bemade_fsm/static/src/xml/project_view_buttons.xml index df3484a..e2c48c6 100644 --- a/bemade_fsm/static/src/xml/project_view_buttons.xml +++ b/bemade_fsm/static/src/xml/project_view_buttons.xml @@ -12,7 +12,7 @@ - diff --git a/bemade_fsm/static/tests/tours/equipment_tour.js b/bemade_fsm/static/tests/tours/equipment_tour.js deleted file mode 100644 index ec69e1e..0000000 --- a/bemade_fsm/static/tests/tours/equipment_tour.js +++ /dev/null @@ -1,104 +0,0 @@ -/** @odoo-module **/ - -import tour from 'web_tour.tour'; - -const TEST_COMPANY = "Test Partner"; -const TEST_EQPT1 = "Test Equipment 1"; -const TEST_EQPT2 = "Test Equipment 2"; -tour.register('equipment_base_tour', { - test: true, - url: '/web', - }, /* Create a new "Test Equipment" and link it to "Test Partner Company" */ - [tour.stepUtils.showAppsMenuItem(), { - content: 'Navigate to the Service menu', - trigger: '.o_app[data-menu-xmlid="industry_fsm.fsm_menu_root"]', - }, { - content: 'Navigate to the Clients submenu', - trigger: 'button.dropdown-toggle[data-menu-xmlid="bemade_fsm.menu_service_client"]', - }, { - content: 'Navigate to the Equipment menu', - trigger: '.dropdown-item[data-menu-xmlid="bemade_fsm.menu_service_client_equipment"]', - }, { - content: 'Click the create button', - trigger: '.o_list_button_add', - }, { - content: 'Add a tag', - trigger: 'input[name="pid_tag"]', - run: 'text TestPIDTag', - }, { - content: 'Set the name', - trigger: 'input[name="name"]', - run: `text ${TEST_EQPT2}`, - }, { - content: 'Set the partner', - trigger: 'div[name="partner_location_id"] div div input', - run: `text ${TEST_COMPANY}`, - }, { - content: 'Click the partner in the dropdown', - trigger: `li a.dropdown-item:contains(${TEST_COMPANY})`, - }, { - content: 'Save equipment', - trigger: 'button.o_list_button_save', - }, { - /* Navigate to the client and make sure that there are two equipments saved (one from the Python test case) */ - content: 'Navigate to the Clients submenu', - trigger: 'button.dropdown-toggle[data-menu-xmlid="bemade_fsm.menu_service_client"]', - }, { - content: 'Click on the clients submenu', - trigger: '.dropdown-item[data-menu-xmlid="bemade_fsm.menu_service_client_clients"]', - }, { - content: 'Search for the Test Partner Company', - trigger: 'input.o_searchview_input', - extra_trigger: 'li.breadcrumb-item.active:has(span:contains(Customers))', - run: `text ${TEST_COMPANY}` - }, { - content: 'Validate Search', - trigger: '.o_menu_item.o_selection_focus', - run: 'click', - }, { - content: 'Open the test client.', - trigger: `div.o_kanban_record:has(span:contains(${TEST_COMPANY}))`, - }, { - content: 'Click the Field Service tab.', - trigger: 'a.nav-link:contains(Field Service)', - extra_trigger: `h1 span.o_field_partner_autocomplete[name="name"]:contains(${TEST_COMPANY})`, - }, { - content: 'Make sure we have a first test equipment', - trigger: `td:contains(${TEST_EQPT1})`, - run: function () { - }, - }, { - content: 'Make sure we have a second test equipment', - trigger: `div[name="equipment_ids"]:has(td:contains(${TEST_EQPT2}))`, - run: function () { - }, - } - ]); - -tour.register('equipment_sale_order_tour', { - test: true, - url: '/web', -}, [tour.stepUtils.showAppsMenuItem(), { - content: 'Navigate to the Sales menu', - trigger: '.o_app[data-menu-xmlid="sale.sale_menu_root"]', -}, { - content: 'Create an order', - trigger: 'button.o_list_button_add', -}, { - content: 'Select the test partner', - trigger: 'div[name="partner_id"] input', - run: `text ${TEST_COMPANY}`, -}, { - content: 'Click the partner in the dropdown', - trigger: `li a.dropdown-item:contains(${TEST_COMPANY})`, -}, { - content: 'Save', - trigger: 'button.o_form_button_save', -}, { - content: 'Navigate to the Field Service tab.', - trigger: 'a.nav-link[role="tab"]:contains(Field Service)' -}, { - content: 'Check that the equipment is listed in the tab.', - trigger: `li.ui-menu-item > a:contains(${TEST_EQPT1})`, -} -]); \ No newline at end of file diff --git a/bemade_fsm/static/tests/tours/sale_order_tour.js b/bemade_fsm/static/tests/tours/sale_order_tour.js deleted file mode 100644 index 6ea8eee..0000000 --- a/bemade_fsm/static/tests/tours/sale_order_tour.js +++ /dev/null @@ -1,40 +0,0 @@ -/** @odoo-module **/ - -import tour from 'web_tour.tour'; - -const SO_NAME = "TEST ORDER 2" -const PRODUCT_NAME = "Test Product 3" -tour.register('sale_order_tour', { - test: true, - url: '/web', - }, - [tour.stepUtils.showAppsMenuItem(), { - content: 'Navigate to the Service menu', - trigger: '.o_app[data-menu-xmlid="sale.sale_menu_root"]', - }, { - content: 'Search for the sales order', - trigger: 'input.o_searchview_input', - run: `text ${SO_NAME}`, - }, { - content: 'Validate Search', - trigger: '.o_menu_item.o_selection_focus', - run: 'click', - }, { - content: 'Open the test order', - trigger: `.o_data_cell[name="client_order_ref"]:contains(${SO_NAME})`, - }, { - content: 'Click the view tasks button', - trigger: 'button[name="action_view_task"]', - }, /*{ - content: 'Click the first task', - trigger: `div.o_kanban_record:has(span:contains(${PRODUCT_NAME}))`, - },*/ { - content: 'Click on the ready to invoice button', - trigger: 'button[name="action_fsm_validate"]', - extra_trigger: `li.breadcrumb-item.active:has(span:contains(${PRODUCT_NAME}))` - }, { - content: 'View the SO', - trigger: 'button[name="action_view_so"]', - // extra_trigger: 'button[title="Current state"]:contains(Done)', - } - ]); diff --git a/bemade_fsm/static/tests/tours/task_equipment_tour.js b/bemade_fsm/static/tests/tours/task_equipment_tour.js deleted file mode 100644 index f8a244d..0000000 --- a/bemade_fsm/static/tests/tours/task_equipment_tour.js +++ /dev/null @@ -1,75 +0,0 @@ -/** @odoo-module **/ - -import tour from 'web_tour.tour'; -const TEST_COMPANY = "Test Partner Company"; -const TEST_EQPT1 = "Test Equipment 1"; -const TEST_EQPT2 = "Test Equipment 2"; -tour.register('task_equipment_tour', { - test: true, - url: '/web', - }, /* Create a new "Test Equipment" and link it to "Test Partner Company" */ - [tour.stepUtils.showAppsMenuItem(), { - content: 'Navigate to the Service menu', - trigger: '.o_app[data-menu-xmlid="industry_fsm.fsm_menu_root"]', - }, { - content: 'Navigate to the Clients submenu', - trigger: 'button.dropdown-toggle[data-menu-xmlid="bemade_fsm.menu_service_client"]', - }, { - content: 'Navigate to the Equipment menu', - trigger: '.dropdown-item[data-menu-xmlid="bemade_fsm.menu_service_client_equipment"]', - }, { - content: 'Click the create button', - trigger: '.o_list_button_add', - extra_trigger: 'li.breadcrumb-item.active:has(span:contains(Equipment))', - }, { - content: 'Add a tag', - trigger: 'input[name="pid_tag"]', - run: 'text TestPIDTag', - }, { - content: 'Set the name', - trigger: 'input[name="name"]', - run: `text ${TEST_EQPT2}`, - }, { - content: 'Set the partner', - trigger: 'div[name="partner_location_id"] div div input', - run: 'text Test Partner Company', - }, { - content: 'Click the partner in the dropdown', - trigger: `li a.dropdown-item:contains(${TEST_COMPANY})`, - }, { - content: 'Save equipment', - trigger: 'button.o_list_button_save', - }, { - /* Navigate to the client and make sure that there are two equipments saved (one from the Python test case) */ - content: 'Navigate to the Clients submenu', - trigger: 'button.dropdown-toggle[data-menu-xmlid="bemade_fsm.menu_service_client"]', - }, { - content: 'Click on the clients submenu', - trigger: '.dropdown-item[data-menu-xmlid="bemade_fsm.menu_service_client_clients"]', - }, { - content: 'Search for the Test Partner Company', - trigger: 'input.o_searchview_input', - extra_trigger: 'li.breadcrumb-item.active:has(span:contains(Customers))', - run: `text ${TEST_COMPANY}` - }, { - content: 'Validate Search', - trigger: '.o_menu_item.o_selection_focus', - run: 'click', - }, { - content: 'Open the test client.', - trigger: `div.o_kanban_record:has(span:contains(${TEST_COMPANY}))`, - }, { - content: 'Click the Field Service tab.', - trigger: 'a.nav-link:contains(Field Service)', - extra_trigger: `h1 span.o_field_partner_autocomplete[name="name"]:contains(${TEST_COMPANY})`, - }, { - content: 'Make sure we have a first test equipment', - /*trigger: `div[name="equipment_ids"]:has(td:contains(${TEST_EQPT1}))`,*/ - trigger: `td:contains(${TEST_EQPT1})`, - run: function() {}, - }, { - content: 'Make sure we have a second test equipment', - trigger: `div[name="equipment_ids"]:has(td:contains(${TEST_EQPT2}))`, - run: function() {}, - } - ]) \ No newline at end of file diff --git a/bemade_fsm/static/tests/tours/task_template_tour.js b/bemade_fsm/static/tests/tours/task_template_tour.js deleted file mode 100644 index 3573a45..0000000 --- a/bemade_fsm/static/tests/tours/task_template_tour.js +++ /dev/null @@ -1,47 +0,0 @@ -/** @odoo-module */ - -import tour from 'web_tour.tour'; - -tour.register('task_template_tour', { - test: true, - url: '/web', - }, /* Make sure the test task is visible via the Project > Task Templates path */ - [tour.stepUtils.showAppsMenuItem(), { - trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]', - }, { - content: 'Open the task templates list view.', - trigger: '.o_nav_entry[data-menu-xmlid="bemade_fsm.project_task_template_menu"]', - }, { - content: 'Open the existing task template.', - trigger: '.o_data_cell:contains("Template 1"):parent()', - }, { - content: 'Confirm that the header contains the task title.', - trigger: 'span[name="name"]:contains("Template 1")', - }, /* Make sure we can see the task template from the product */ - tour.stepUtils.toggleHomeMenu(), - { - content: 'Open the sales menu.', - trigger: '.o_app[data-menu-xmlid="sale.sale_menu_root"]', - }, { - content: 'Open the product dropdown menu.', - trigger: 'button[data-menu-xmlid="sale.product_menu_catalog"]', - }, { - content: 'Click the products menu item.', - trigger: 'a.dropdown-item[data-menu-xmlid="sale.menu_product_template_action"]', - }, { - content: 'Search for the test product.', - trigger: 'input.o_searchview_input', - extra_trigger: 'li.breadcrumb-item.active:has(span:contains(Products))', - run: 'text Test Product 1', - }, { - trigger: '.o_menu_item.o_selection_focus', - content: 'Validate search', - run: 'click', - }, { - content: 'Open the test product.', - trigger: 'div.o_kanban_record:has(span:contains(Test Product 1))', - }, { - content: 'Ensure the product_template_id field is displayed with the "Template 1" mention.', - trigger: 'a.o_quick_editable[name="task_template_id"]:first-child:contains("Template 1")', - }, - ]) \ No newline at end of file From 95d2ce5274011796a98703bc6e7c4c18bd866de1 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 5 Dec 2023 14:56:06 -0500 Subject: [PATCH 33/96] bemade_fsm: Propagation of task assignee to subtasks (optional). --- bemade_fsm/__manifest__.py | 2 +- bemade_fsm/models/task.py | 16 ++++++++++++ bemade_fsm/tests/__init__.py | 1 + bemade_fsm/tests/test_sale_order.py | 2 +- bemade_fsm/tests/test_task.py | 40 +++++++++++++++++++++++++++++ bemade_fsm/views/task_views.xml | 3 +++ 6 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 bemade_fsm/tests/test_task.py diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index 8df780e..0175510 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.4', + 'version': '15.0.1.0.5', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', diff --git a/bemade_fsm/models/task.py b/bemade_fsm/models/task.py index b9b5a92..5fd4468 100644 --- a/bemade_fsm/models/task.py +++ b/bemade_fsm/models/task.py @@ -76,6 +76,12 @@ class Task(models.Model): work_order_number = fields.Char(readonly=True) + propagate_assignment = fields.Boolean( + string='Propagate Assignment', + help='Propagate assignment of this task to all subtasks.', + default=True, + ) + @api.model_create_multi def create(self, vals): res = super().create(vals) @@ -92,6 +98,16 @@ class Task(models.Model): + f"-{seq}" return res + def write(self, vals): + super().write(vals) + if not self: # End recursion on empty RecordSet + return + if 'user_ids' in vals: + to_propagate = self.filtered(lambda task: task.propagate_assignment) + # Here we use child_ids instead of _get_all_subtasks() so as to allow for setting propagate_assignment + # to false on a child task. + to_propagate.child_ids.write({'user_ids': vals['user_ids']}) + @api.depends('sale_order_id') def _compute_relevant_order_lines(self): for rec in self: diff --git a/bemade_fsm/tests/__init__.py b/bemade_fsm/tests/__init__.py index 381536f..4b317ee 100644 --- a/bemade_fsm/tests/__init__.py +++ b/bemade_fsm/tests/__init__.py @@ -4,3 +4,4 @@ from . import test_sale_order from . import test_equipment from . import test_fsm_contact_setting from . import test_fsm_visit +from . import test_task diff --git a/bemade_fsm/tests/test_sale_order.py b/bemade_fsm/tests/test_sale_order.py index 2801ff3..1e39371 100644 --- a/bemade_fsm/tests/test_sale_order.py +++ b/bemade_fsm/tests/test_sale_order.py @@ -251,7 +251,7 @@ class TestSalesOrder(BemadeFSMBaseTest): self.assertFalse(visit_task.user_ids) self.assertFalse(subtask1.user_ids) self.assertFalse(subtask2.user_ids) - + def test_long_line_name_overflows_to_task_description(self): so = self._generate_sale_order() product = self._generate_product() diff --git a/bemade_fsm/tests/test_task.py b/bemade_fsm/tests/test_task.py new file mode 100644 index 0000000..63185de --- /dev/null +++ b/bemade_fsm/tests/test_task.py @@ -0,0 +1,40 @@ +from .test_bemade_fsm_common import BemadeFSMBaseTest +from odoo.tests.common import tagged +from odoo import Command + + +@tagged('post_install', '-at_install') +class TaskTest(BemadeFSMBaseTest): + + def test_reassigning_assignment_propagating_task_changes_subtasks(self): + # This creation step is a bit lazy - we use defaults to make tasks with a hierachy and settings we want + so = self._generate_sale_order() + template = self._generate_task_template(names=['Parent', 'Child'], structure=[2]) + product = self._generate_product(task_template=template) + sol = self._generate_sale_order_line(sale_order=so, product=product) + user = self._generate_project_manager_user('Bob', 'Bob') + so.action_confirm() + task = sol.task_id + + task.write({ + 'user_ids': [Command.set([user.id])] + }) + + self.assertTrue(all([t.user_ids == user for t in task | task._get_all_subtasks()])) + + def test_reassigning_assignment_non_propagating_task_doesnt_change_subtasks(self): + so = self._generate_sale_order() + template = self._generate_task_template(names=['Parent', 'Child', 'Grandchild'], structure=[2, 1]) + product = self._generate_product(task_template=template) + sol = self._generate_sale_order_line(sale_order=so, product=product) + user = self._generate_project_manager_user('Bob', 'Bob') + so.action_confirm() + task = sol.task_id + task.child_ids.write({'propagate_assignment': False}) # Stop propagation after the first level + + task.write({ + 'user_ids': [Command.set([user.id])] + }) + + self.assertTrue(all([t.user_ids == user for t in task | task.child_ids])) + self.assertFalse(any([t.user_ids for t in task.child_ids.child_ids])) diff --git a/bemade_fsm/views/task_views.xml b/bemade_fsm/views/task_views.xml index c1d9a1b..9d8d201 100644 --- a/bemade_fsm/views/task_views.xml +++ b/bemade_fsm/views/task_views.xml @@ -46,6 +46,9 @@ + + + From 81cfdfa39d88072ddc007162ad960bd52ab409f3 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Fri, 8 Dec 2023 14:01:41 -0500 Subject: [PATCH 34/96] bemade_fsm: propagate assignees to false by default. --- bemade_fsm/__manifest__.py | 2 +- bemade_fsm/models/task.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index 0175510..d912bdb 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.5', + 'version': '15.0.1.0.6', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', diff --git a/bemade_fsm/models/task.py b/bemade_fsm/models/task.py index 5fd4468..23d854c 100644 --- a/bemade_fsm/models/task.py +++ b/bemade_fsm/models/task.py @@ -79,7 +79,7 @@ class Task(models.Model): propagate_assignment = fields.Boolean( string='Propagate Assignment', help='Propagate assignment of this task to all subtasks.', - default=True, + default=False, ) @api.model_create_multi From a1e9c305ec5c6cf6b199dec9ed5375565353c8fb Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 19 Dec 2023 19:09:47 -0500 Subject: [PATCH 35/96] bemade_fsm: fixed tests on propagate assignment due to new default. --- bemade_fsm/tests/test_task.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bemade_fsm/tests/test_task.py b/bemade_fsm/tests/test_task.py index 63185de..f5e7ae6 100644 --- a/bemade_fsm/tests/test_task.py +++ b/bemade_fsm/tests/test_task.py @@ -17,7 +17,8 @@ class TaskTest(BemadeFSMBaseTest): task = sol.task_id task.write({ - 'user_ids': [Command.set([user.id])] + 'user_ids': [Command.set([user.id])], + 'propagate_assignment': True, }) self.assertTrue(all([t.user_ids == user for t in task | task._get_all_subtasks()])) @@ -33,7 +34,8 @@ class TaskTest(BemadeFSMBaseTest): task.child_ids.write({'propagate_assignment': False}) # Stop propagation after the first level task.write({ - 'user_ids': [Command.set([user.id])] + 'user_ids': [Command.set([user.id])], + 'propagate_assignment': True, }) self.assertTrue(all([t.user_ids == user for t in task | task.child_ids])) From 2896a9de7476246c5c103efef8db137038e486ac Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Wed, 3 Jan 2024 17:25:05 -0500 Subject: [PATCH 36/96] [MIG] bemade_full_formview_from_modal to 16.0 --- .../__manifest__.py | 4 +- .../static/src/js/form_view_dialog.js | 40 ------------------- .../src/view_dialogs/form_view_dialog.js | 22 ++++++++++ .../src/view_dialogs/form_view_dialog.xml | 13 ++++++ bemade_packing_wizard/__manifest__.py | 4 +- 5 files changed, 39 insertions(+), 44 deletions(-) delete mode 100644 bemade_full_formview_from_modal/static/src/js/form_view_dialog.js create mode 100644 bemade_full_formview_from_modal/static/src/view_dialogs/form_view_dialog.js create mode 100644 bemade_full_formview_from_modal/static/src/view_dialogs/form_view_dialog.xml diff --git a/bemade_full_formview_from_modal/__manifest__.py b/bemade_full_formview_from_modal/__manifest__.py index 66d3327..2427ab3 100644 --- a/bemade_full_formview_from_modal/__manifest__.py +++ b/bemade_full_formview_from_modal/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Full Form from Dialog', - 'version': '15.0.1.0.0', + 'version': '16.0.1.0.0', 'summary': 'Allows opening the full form view from the dialog (modal) view.', 'description': 'Adds a button to open the full form view when viewing the form view for a record in a dialog.', 'category': 'Technical', @@ -29,7 +29,7 @@ 'data': [], 'assets': { 'web.assets_backend': [ - 'bemade_full_formview_from_modal/static/src/js/form_view_dialog.js', + 'bemade_full_formview_from_modal/static/src/**/*', ], }, 'installable': True, diff --git a/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js b/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js deleted file mode 100644 index fbb2b83..0000000 --- a/bemade_full_formview_from_modal/static/src/js/form_view_dialog.js +++ /dev/null @@ -1,40 +0,0 @@ -/** @odoo-module **/ - -import FormViewDialog from 'web.FormView'; -import Dialog from 'web.Dialog'; -import {patch} from '@web/core/utils/patch'; -import {_t} from 'web.core'; - -const dom = require('web.dom') - -patch(Dialog.prototype, "bemade_full_formview_from_modal.Dialog", { - init: function (parent, options) { - this._super(...arguments); - }, - willStart: function () { - const self = this; - return this._super(...arguments).then(function () { - if (self.$footer) { - const $button = dom.renderButton({ - attrs: { - class: 'btn btn-secondary o_form_button_open', - }, - text: _t('Open'), - }); - $button.on('click', function() {self._onOpen.call(self)}); - self.$footer.append($button); - } - } - ); - }, - _onOpen: function () { - this.do_action({ - type: 'ir.actions.act_window', - res_model: this.options.res_model, - res_id: this.options.res_id, - views: [[false, 'form']], - target: 'current', - context: this.context, - }) - } -}); diff --git a/bemade_full_formview_from_modal/static/src/view_dialogs/form_view_dialog.js b/bemade_full_formview_from_modal/static/src/view_dialogs/form_view_dialog.js new file mode 100644 index 0000000..06e1418 --- /dev/null +++ b/bemade_full_formview_from_modal/static/src/view_dialogs/form_view_dialog.js @@ -0,0 +1,22 @@ +/** @odoo-module **/ + +import { patch } from "@web/core/utils/patch"; +import { FormController } from "@web/views/form/form_controller"; +import { useService } from "@web/core/utils/hooks"; + +patch(FormController.prototype, "bemade_full_formview_from_modal.FormController", { + setup () { + this._super(); + this.action = useService("action") + }, + onOpenButtonClicked: function () { + this.action.doAction({ + type: "ir.actions.act_window", + res_model: this.props.resModel, + res_id: this.props.resId, + views: [[false, "form"]], + target: "current", + context: this.props.context, + }) + } +}); diff --git a/bemade_full_formview_from_modal/static/src/view_dialogs/form_view_dialog.xml b/bemade_full_formview_from_modal/static/src/view_dialogs/form_view_dialog.xml new file mode 100644 index 0000000..65aefe9 --- /dev/null +++ b/bemade_full_formview_from_modal/static/src/view_dialogs/form_view_dialog.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/bemade_packing_wizard/__manifest__.py b/bemade_packing_wizard/__manifest__.py index 41b136d..124c309 100644 --- a/bemade_packing_wizard/__manifest__.py +++ b/bemade_packing_wizard/__manifest__.py @@ -1,12 +1,12 @@ { 'name': 'Packing wizard', - 'version': '15.0.1.0.0', + 'version': '16.0.1.0.0', 'category': 'Extra Tools', 'summary': 'Allow automated packing type creation', 'description': """ This module allows users simply enter all the package dimensions on every packing and it will create the packing type automatically if it not exists, use it the create the package with the weight and related package type. - + You need to activate the auto create package feature on the delivery carrier to use this feature. """, 'depends': [ From 2799f9efc19d28251e7066079f763bd3c90918c5 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Wed, 3 Jan 2024 17:41:51 -0500 Subject: [PATCH 37/96] bemade_stock_quant_valuation to 16.0 --- bemade_stock_quant_valuation/__manifest__.py | 2 +- temporary_change_image_size/__manifest__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bemade_stock_quant_valuation/__manifest__.py b/bemade_stock_quant_valuation/__manifest__.py index 19ffd69..05a8fca 100644 --- a/bemade_stock_quant_valuation/__manifest__.py +++ b/bemade_stock_quant_valuation/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Stock Quant Valuation', - 'version': '15.0.1.0.0', + 'version': '16.0.1.0.0', 'summary': 'Adds valuation to stock quant for better inventory adjustment management', 'description': '', 'category': 'Inventory', diff --git a/temporary_change_image_size/__manifest__.py b/temporary_change_image_size/__manifest__.py index 54a9ac5..611f8cf 100644 --- a/temporary_change_image_size/__manifest__.py +++ b/temporary_change_image_size/__manifest__.py @@ -1,6 +1,6 @@ { 'name': 'Temporary Change for Image Full Size', - 'version': '15.0.0.0.0', + 'version': '16.0.0.0.0', 'category': 'Extra Tools', 'summary': 'Temporary Change for Image Full Size', 'description': """ From 8cc96da5c40aea367fb938945621ff09edda9f5e Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Wed, 3 Jan 2024 17:46:07 -0500 Subject: [PATCH 38/96] [MIG] bemade_partner_email_domain to 16.0 --- bemade_partner_email_domain/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bemade_partner_email_domain/__manifest__.py b/bemade_partner_email_domain/__manifest__.py index 5047c18..9f8fbe9 100644 --- a/bemade_partner_email_domain/__manifest__.py +++ b/bemade_partner_email_domain/__manifest__.py @@ -1,6 +1,6 @@ { 'name': 'Automated Partner Association by Email Domain', - 'version': '15.0.0.0.0', + 'version': '16.0.0.0.0', 'category': 'Extra Tools', 'summary': 'Automatically associates partners with companies using matching email domains', 'description': """ From 5a006ec396748f3eda98bc354bee5cb56337d7cb Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 8 Jan 2024 09:36:39 -0500 Subject: [PATCH 39/96] Fixes to partner_scrapper module and payslip module for 17.0 migration --- bemade_odoo_partner_scrapper/__manifest__.py | 3 ++- bemade_odoo_partner_scrapper/views/res_partner_views.xml | 2 +- bemade_payslip_done_as_not_paid/__manifest__.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bemade_odoo_partner_scrapper/__manifest__.py b/bemade_odoo_partner_scrapper/__manifest__.py index b48436b..1c82cd1 100644 --- a/bemade_odoo_partner_scrapper/__manifest__.py +++ b/bemade_odoo_partner_scrapper/__manifest__.py @@ -20,7 +20,8 @@ 'data': [ # No security 'views/res_partner_views.xml', - 'data/res_partner_relation_type.xml' + # Commented for migration to 17, raises error on update + # 'data/res_partner_relation_type.xml' ], "assets": { "web.assets_backend": [ diff --git a/bemade_odoo_partner_scrapper/views/res_partner_views.xml b/bemade_odoo_partner_scrapper/views/res_partner_views.xml index 071bb06..91c5509 100644 --- a/bemade_odoo_partner_scrapper/views/res_partner_views.xml +++ b/bemade_odoo_partner_scrapper/views/res_partner_views.xml @@ -11,7 +11,7 @@ Odoo User Odoo Partner
-
+

Partner

diff --git a/bemade_payslip_done_as_not_paid/__manifest__.py b/bemade_payslip_done_as_not_paid/__manifest__.py index e5e382b..bbe9efa 100644 --- a/bemade_payslip_done_as_not_paid/__manifest__.py +++ b/bemade_payslip_done_as_not_paid/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Payslip Done as To Pay', - 'version': '16.0.1.0.0', + 'version': '17.0.1.0.0', 'summary': 'Payslips in "Done" state appear as "To Pay"', 'category': 'Human Resources/Payroll', 'author': 'Bemade Inc.', From 680ef4ff756f4985b58856a2e9f7f74f63d2646f Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 8 Jan 2024 10:02:10 -0500 Subject: [PATCH 40/96] [MIG] bemade_odoo_partner_scrapper to 17.0 --- bemade_odoo_partner_scrapper/__manifest__.py | 8 ++++---- .../data/res_partner_relation_type.xml | 5 +++-- bemade_odoo_partner_scrapper_js_only/__manifest__.py | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/bemade_odoo_partner_scrapper/__manifest__.py b/bemade_odoo_partner_scrapper/__manifest__.py index 1c82cd1..00fde8b 100644 --- a/bemade_odoo_partner_scrapper/__manifest__.py +++ b/bemade_odoo_partner_scrapper/__manifest__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- { 'name': 'Bemade Odoo Partner Scrapper', - 'version': '1.0.0', + 'version': '17.01.0.0', 'category': 'Administration', 'summary': 'Module for scraping partners from odoo.com.', 'description': """ @@ -21,12 +21,12 @@ # No security 'views/res_partner_views.xml', # Commented for migration to 17, raises error on update - # 'data/res_partner_relation_type.xml' + 'data/res_partner_relation_type.xml' ], "assets": { "web.assets_backend": [ - # "bemade_odoo_partner_scrapper/static/src/js/odoo_scrapper.js", - # "bemade_odoo_partner_scrapper/static/src/xml/odoo_scrapper_templates.xml", + "bemade_odoo_partner_scrapper/static/src/js/odoo_scrapper.js", + "bemade_odoo_partner_scrapper/static/src/xml/odoo_scrapper_templates.xml", ], }, 'demo': [], diff --git a/bemade_odoo_partner_scrapper/data/res_partner_relation_type.xml b/bemade_odoo_partner_scrapper/data/res_partner_relation_type.xml index b193a2d..fe644ad 100644 --- a/bemade_odoo_partner_scrapper/data/res_partner_relation_type.xml +++ b/bemade_odoo_partner_scrapper/data/res_partner_relation_type.xml @@ -9,8 +9,9 @@ Is Odoo Partner Of Is Odoo Client Of - c - c + + + diff --git a/bemade_odoo_partner_scrapper_js_only/__manifest__.py b/bemade_odoo_partner_scrapper_js_only/__manifest__.py index 7d24d9d..e9b3ef9 100644 --- a/bemade_odoo_partner_scrapper_js_only/__manifest__.py +++ b/bemade_odoo_partner_scrapper_js_only/__manifest__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- { 'name': 'Bemade Odoo Partner Scrapper JS Only', - 'version': '1.0.0', + 'version': '17.0.1.0.0', 'category': 'Administration', 'summary': 'Module for scraping partners from odoo.com.', 'description': """ From 3df02a47e50eb507aca747fdf77f7d0c2439a2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20V=C3=A9zina?= Date: Tue, 9 Jan 2024 11:17:46 -0500 Subject: [PATCH 41/96] Update __manifest__.py --- bemade_odoo_partner_scrapper/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bemade_odoo_partner_scrapper/__manifest__.py b/bemade_odoo_partner_scrapper/__manifest__.py index b48436b..ff37e94 100644 --- a/bemade_odoo_partner_scrapper/__manifest__.py +++ b/bemade_odoo_partner_scrapper/__manifest__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- { 'name': 'Bemade Odoo Partner Scrapper', - 'version': '1.0.0', + 'version': '17.0.0.0.0', 'category': 'Administration', 'summary': 'Module for scraping partners from odoo.com.', 'description': """ From 4853d0df78fa19181f37dda00874f222dced628a Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 9 Jan 2024 15:00:42 -0500 Subject: [PATCH 42/96] fix attrs in res_partner_views.xml --- bemade_odoo_partner_scrapper/views/res_partner_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bemade_odoo_partner_scrapper/views/res_partner_views.xml b/bemade_odoo_partner_scrapper/views/res_partner_views.xml index 071bb06..160c0e9 100644 --- a/bemade_odoo_partner_scrapper/views/res_partner_views.xml +++ b/bemade_odoo_partner_scrapper/views/res_partner_views.xml @@ -11,7 +11,7 @@ Odoo User Odoo Partner
-
+

Partner

From e5969231001621ab56a8ffa0bb36bf1386bb9a96 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 9 Jan 2024 17:08:15 -0500 Subject: [PATCH 43/96] remove js assets from bemade_odoo_partner_scrapper --- bemade_odoo_partner_scrapper/__manifest__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bemade_odoo_partner_scrapper/__manifest__.py b/bemade_odoo_partner_scrapper/__manifest__.py index 934e387..ea87ef5 100644 --- a/bemade_odoo_partner_scrapper/__manifest__.py +++ b/bemade_odoo_partner_scrapper/__manifest__.py @@ -23,12 +23,12 @@ # Commented for migration to 17, raises error on update 'data/res_partner_relation_type.xml' ], - "assets": { - "web.assets_backend": [ - "bemade_odoo_partner_scrapper/static/src/js/odoo_scrapper.js", - "bemade_odoo_partner_scrapper/static/src/xml/odoo_scrapper_templates.xml", - ], - }, + # "assets": { + # "web.assets_backend": [ + # "bemade_odoo_partner_scrapper/static/src/js/odoo_scrapper.js", + # "bemade_odoo_partner_scrapper/static/src/xml/odoo_scrapper_templates.xml", + # ], + # }, 'demo': [], 'installable': True, 'application': False, From 3c15d6a5e27a7fb2c74b1741b4ec030f55e97855 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Wed, 10 Jan 2024 09:51:06 -0500 Subject: [PATCH 44/96] [FIX] bemade_fsm: propagate assignment checkbox on tasks Fixes a problem where the propagate assignment checkbox on project tasks was not effectively propagating task assignment to descendants. Also added some intelligence around checking / unchecking the box such that the setting change propagates to children. This allows for interesting configurations for assignment propagation, such as limiting propagation only to one level or only starting it at a given level of subtasks. --- bemade_fsm/__manifest__.py | 2 +- bemade_fsm/models/task.py | 3 ++ bemade_fsm/tests/test_task.py | 58 ++++++++++++++++++++++------------- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index fa6c83b..8cd38f7 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.6', + 'version': '15.0.1.0.7', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', diff --git a/bemade_fsm/models/task.py b/bemade_fsm/models/task.py index 43a147d..b7f2fb0 100644 --- a/bemade_fsm/models/task.py +++ b/bemade_fsm/models/task.py @@ -102,6 +102,9 @@ class Task(models.Model): super().write(vals) if not self: # End recursion on empty RecordSet return + if 'propagate_assignment' in vals: + # When a user sets propagate assignment, it should propagate that setting all the way down the chain + self.child_ids.write({'propagate_assignment': vals['propagate_assignment']}) if 'user_ids' in vals: to_propagate = self.filtered(lambda task: task.propagate_assignment) # Here we use child_ids instead of _get_all_subtasks() so as to allow for setting propagate_assignment diff --git a/bemade_fsm/tests/test_task.py b/bemade_fsm/tests/test_task.py index 63185de..c2b5543 100644 --- a/bemade_fsm/tests/test_task.py +++ b/bemade_fsm/tests/test_task.py @@ -6,35 +6,49 @@ from odoo import Command @tagged('post_install', '-at_install') class TaskTest(BemadeFSMBaseTest): + @classmethod + def setUpClass(cls): + # Chose to set up all tests the same way since this code was becoming very redundant + super().setUpClass() + cls.so = cls._generate_sale_order() + cls.template = cls._generate_task_template(names=['Parent', 'Child', 'Grandchild'], structure=[2, 1]) + cls.product = cls._generate_product(task_template=cls.template) + cls.sol = cls._generate_sale_order_line(sale_order=cls.so, product=cls.product) + cls.user = cls._generate_project_manager_user('Bob', 'Bob') + cls.so.action_confirm() + cls.task = cls.sol.task_id + def test_reassigning_assignment_propagating_task_changes_subtasks(self): - # This creation step is a bit lazy - we use defaults to make tasks with a hierachy and settings we want - so = self._generate_sale_order() - template = self._generate_task_template(names=['Parent', 'Child'], structure=[2]) - product = self._generate_product(task_template=template) - sol = self._generate_sale_order_line(sale_order=so, product=product) - user = self._generate_project_manager_user('Bob', 'Bob') - so.action_confirm() - task = sol.task_id + task = self.task + task.propagate_assignment = True task.write({ - 'user_ids': [Command.set([user.id])] + 'user_ids': [Command.set([self.user.id])] }) - self.assertTrue(all([t.user_ids == user for t in task | task._get_all_subtasks()])) - - def test_reassigning_assignment_non_propagating_task_doesnt_change_subtasks(self): - so = self._generate_sale_order() - template = self._generate_task_template(names=['Parent', 'Child', 'Grandchild'], structure=[2, 1]) - product = self._generate_product(task_template=template) - sol = self._generate_sale_order_line(sale_order=so, product=product) - user = self._generate_project_manager_user('Bob', 'Bob') - so.action_confirm() - task = sol.task_id - task.child_ids.write({'propagate_assignment': False}) # Stop propagation after the first level + self.assertTrue(all([t.user_ids == self.user for t in task | task._get_all_subtasks()])) + def test_reassigning_task_doesnt_propagate_by_default(self): + task = self.task task.write({ - 'user_ids': [Command.set([user.id])] + 'user_ids': [Command.set([self.user.id])] }) - self.assertTrue(all([t.user_ids == user for t in task | task.child_ids])) self.assertFalse(any([t.user_ids for t in task.child_ids.child_ids])) + + def test_unset_propagate_assignment_unsets_for_all_children(self): + task = self.task + # First, set propagation and assign + task.propagate_assignment = True + task.write({ + 'user_ids': [Command.set([self.user.id])] + }) + # Then, unset propagation for the children and re-set assignment + task.child_ids.write({'propagate_assignment': False}) + self.assertFalse(any([t.propagate_assignment for t in task._get_all_subtasks()])) + # Then, test that assigning the parent only assigns its children, not its grandchildren + task.write({ + 'user_ids': [Command.set([])] + }) + self.assertTrue(all([not t.user_ids for t in task | task.child_ids])) + self.assertTrue(all([t.user_ids == self.user for t in task.child_ids.child_ids])) From 47c8f9261c48d2303cfdbf681eb0bfd72c449e3c Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Wed, 10 Jan 2024 19:49:36 -0500 Subject: [PATCH 45/96] bemade_sports_clinic: simplify model descriptions --- bemade_sports_clinic/__manifest__.py | 2 +- bemade_sports_clinic/models/patient.py | 4 ++-- bemade_sports_clinic/models/sports_team.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bemade_sports_clinic/__manifest__.py b/bemade_sports_clinic/__manifest__.py index 81b355f..5509180 100644 --- a/bemade_sports_clinic/__manifest__.py +++ b/bemade_sports_clinic/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Sports Clinic Management', - 'version': '16.0.1.5.2', + 'version': '16.0.1.5.3', 'summary': 'Manage the patients of a sports medicine clinic.', 'description': """ Adds the notion of sports teams, players (patients), coaches and treatment diff --git a/bemade_sports_clinic/models/patient.py b/bemade_sports_clinic/models/patient.py index 201bea2..b1b1e41 100644 --- a/bemade_sports_clinic/models/patient.py +++ b/bemade_sports_clinic/models/patient.py @@ -7,7 +7,7 @@ from odoo.addons.phone_validation.tools import phone_validation class Patient(models.Model): _name = 'sports.patient' - _description = "Patient at a sports medicine clinic." + _description = "Patient" _inherit = ['mail.thread', 'mail.activity.mixin'] _order = 'last_name, first_name' @@ -222,7 +222,7 @@ class PatientContact(models.Model): class PatientInjury(models.Model): _name = 'sports.patient.injury' - _description = "A patient's injury." + _description = "Patient Injury" _inherit = ['mail.thread', 'mail.activity.mixin'] _rec_name = 'diagnosis' diff --git a/bemade_sports_clinic/models/sports_team.py b/bemade_sports_clinic/models/sports_team.py index b2f23bf..6f7d589 100644 --- a/bemade_sports_clinic/models/sports_team.py +++ b/bemade_sports_clinic/models/sports_team.py @@ -51,7 +51,7 @@ class SportsTeam(models.Model): class TeamStaff(models.Model): _name = "sports.team.staff" - _description = "Relationship between staff members and their teams." + _description = "Sports Team Staff" sequence = fields.Integer() team_id = fields.Many2one(comodel_name='sports.team', string='Team', required=True) From bcbb3bda1fe877cf638fd352046082c68a5bd8bd Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Sat, 13 Jan 2024 18:52:37 -0500 Subject: [PATCH 46/96] bemade_sports_clinic: notify team staff of updates Added two mail.message.subtypes to notify all followers of updates to patient status and changes to injury fields. Added a post-migration script to update all existing followers to subscribe to these new subtypes. --- bemade_sports_clinic/__manifest__.py | 3 ++- .../data/demo/sports_clinic_demo_data.xml | 2 +- .../data/sports_clinic_data.xml | 23 ++++++++++++++++ .../migrations/16.0.1.5.4/post-migrate.py | 21 +++++++++++++++ bemade_sports_clinic/models/patient.py | 26 ++++++++++++++++++- 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 bemade_sports_clinic/data/sports_clinic_data.xml create mode 100644 bemade_sports_clinic/migrations/16.0.1.5.4/post-migrate.py diff --git a/bemade_sports_clinic/__manifest__.py b/bemade_sports_clinic/__manifest__.py index 5509180..abf3746 100644 --- a/bemade_sports_clinic/__manifest__.py +++ b/bemade_sports_clinic/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Sports Clinic Management', - 'version': '16.0.1.5.3', + 'version': '16.0.1.5.4', 'summary': 'Manage the patients of a sports medicine clinic.', 'description': """ Adds the notion of sports teams, players (patients), coaches and treatment @@ -42,6 +42,7 @@ 'security/sports_clinic_groups.xml', 'security/ir.model.access.csv', 'security/sports_clinic_rules.xml', + 'data/sports_clinic_data.xml', 'views/sports_team_views.xml', 'views/sports_clinic_menus.xml', 'views/sports_patient_views.xml', diff --git a/bemade_sports_clinic/data/demo/sports_clinic_demo_data.xml b/bemade_sports_clinic/data/demo/sports_clinic_demo_data.xml index c148dea..2b1dd30 100644 --- a/bemade_sports_clinic/data/demo/sports_clinic_demo_data.xml +++ b/bemade_sports_clinic/data/demo/sports_clinic_demo_data.xml @@ -186,4 +186,4 @@ - \ No newline at end of file + diff --git a/bemade_sports_clinic/data/sports_clinic_data.xml b/bemade_sports_clinic/data/sports_clinic_data.xml new file mode 100644 index 0000000..af83b45 --- /dev/null +++ b/bemade_sports_clinic/data/sports_clinic_data.xml @@ -0,0 +1,23 @@ + + + + + Patient File Update + sports.patient + + Patient's file has been updated. + + + + + + Patient Injury Status Update + sports.patient.injury + + Patient's injury was updated. + + + + + + diff --git a/bemade_sports_clinic/migrations/16.0.1.5.4/post-migrate.py b/bemade_sports_clinic/migrations/16.0.1.5.4/post-migrate.py new file mode 100644 index 0000000..2323c5d --- /dev/null +++ b/bemade_sports_clinic/migrations/16.0.1.5.4/post-migrate.py @@ -0,0 +1,21 @@ +from odoo import api, SUPERUSER_ID, Command + +def migrate(cr, version): + env = api.Environment(cr, SUPERUSER_ID, {}) + patient_followers = env['mail.followers'].search([('res_model', '=', + 'sports.patient')]) + injury_followers = env['mail.followers'].search([('res_model', '=', + 'sports.patient.injury')]) + for f in patient_followers: + f.write( + { + 'subtype_ids': + [Command.link(env.ref('bemade_sports_clinic.subtype_patient_update').id)] + } + ) + for f in injury_followers: + f.write( + { + 'subtype_ids': + [Command.link(env.ref('bemade_sports_clinic.subtype_patient_injury_update').id)] + }) diff --git a/bemade_sports_clinic/models/patient.py b/bemade_sports_clinic/models/patient.py index b1b1e41..7e70019 100644 --- a/bemade_sports_clinic/models/patient.py +++ b/bemade_sports_clinic/models/patient.py @@ -63,7 +63,7 @@ class Patient(models.Model): stage = fields.Selection( selection=[('no_play', 'Injured'), ('practice_ok', 'Practice OK'), ('healthy', 'Play OK')], compute='_compute_stage') - last_consultation_date = fields.Date() + last_consultation_date = fields.Date(tracking=True) active_injury_count = fields.Integer(compute='_compute_active_injury_count') allergies = fields.Text() team_info_notes = fields.Html(string="Notes") @@ -187,6 +187,22 @@ class Patient(models.Model): raise_exception=False ) + def _track_subtype(self, init_values): + # List of fields that should result in team staff notification + external_values = [ + "last_consultation_date", + "match_status", + "practice_status", + "predicted_return_date", + "return_date", + "external_notes", + ] + if any([v in init_values for v in external_values]): + return self.env.ref("bemade_sports_clinic.subtype_patient_update") + else: + return self.env.ref('mail.mt_note') + + class PatientContact(models.Model): _name = 'sports.patient.contact' @@ -300,3 +316,11 @@ class PatientInjury(models.Model): 'res_id': self.id, 'context': self._context, } + + def _track_subtype(self, init_values): + if 'treatment_professional_ids' in init_values \ + and len(init_values) == 1: + return self.env.ref('mail.mt_note') + else: + return self.env.ref('bemade_sports_clinic.subtype_patient_injury_update') + From 0f1b45ca81fcc861eaa357c42043b527f18becb0 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 15 Jan 2024 09:07:39 -0500 Subject: [PATCH 47/96] removed conflict stuff from bemade_fsm manifest --- bemade_fsm/__manifest__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index 45c1893..cb73ae3 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -52,13 +52,8 @@ 'views/menus.xml', 'views/task_views.xml', 'views/sale_order_views.xml', -<<<<<<< HEAD 'reports/worksheet_custom_report_templates.xml', 'reports/worksheet_custom_reports.xml', -======= - # 'reports/worksheet_custom_report_templates.xml', - # 'reports/worksheet_custom_reports.xml', ->>>>>>> 5a006ec3 'wizard/new_task_from_template.xml', ], 'assets': { From 96712b257f3e85e3364811c47a34b69d9e26cd4e Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Wed, 17 Jan 2024 14:59:03 -0500 Subject: [PATCH 48/96] bemade_fsm: bug fix for equipment complete_name --- bemade_fsm/__manifest__.py | 2 +- bemade_fsm/models/equipment.py | 3 ++- bemade_fsm/tests/test_equipment.py | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index 8cd38f7..12cf85a 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.7', + 'version': '15.0.1.0.8', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', diff --git a/bemade_fsm/models/equipment.py b/bemade_fsm/models/equipment.py index dc08495..24587ab 100644 --- a/bemade_fsm/models/equipment.py +++ b/bemade_fsm/models/equipment.py @@ -72,4 +72,5 @@ class Equipment(models.Model): def _compute_complete_name(self): for rec in self: tag_part = "[%s] " % rec.pid_tag if rec.pid_tag else "" - rec.complete_name = tag_part + rec.name + name = rec.name or "" + rec.complete_name = tag_part + name diff --git a/bemade_fsm/tests/test_equipment.py b/bemade_fsm/tests/test_equipment.py index 16e06e2..879f129 100644 --- a/bemade_fsm/tests/test_equipment.py +++ b/bemade_fsm/tests/test_equipment.py @@ -19,3 +19,7 @@ class TestEquipment(BemadeFSMBaseTest): partner_company.write({'equipment_ids': [Command.set([])]}) with self.assertRaises(MissingError): equipment.name + + def test_compute_complete_name_when_name_blank(self): + equipment = self._generate_equipment(name=False) + complete_name = equipment.complete_name From 3e415249d7abe09fa90bb7cce0e0efb216f70a80 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 23 Jan 2024 03:03:49 +0000 Subject: [PATCH 49/96] [FIX] fix a bug where dates come up to an incorrect default Timezone differences were causing dates to come up very weirdly on new patient injury records. They now use the user timezone to convert datetime.now() appropriately. --- bemade_sports_clinic/__manifest__.py | 2 +- bemade_sports_clinic/models/patient.py | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/bemade_sports_clinic/__manifest__.py b/bemade_sports_clinic/__manifest__.py index abf3746..1815504 100644 --- a/bemade_sports_clinic/__manifest__.py +++ b/bemade_sports_clinic/__manifest__.py @@ -18,7 +18,7 @@ # { 'name': 'Sports Clinic Management', - 'version': '16.0.1.5.4', + 'version': '16.0.1.5.5', 'summary': 'Manage the patients of a sports medicine clinic.', 'description': """ Adds the notion of sports teams, players (patients), coaches and treatment diff --git a/bemade_sports_clinic/models/patient.py b/bemade_sports_clinic/models/patient.py index 7e70019..357edd1 100644 --- a/bemade_sports_clinic/models/patient.py +++ b/bemade_sports_clinic/models/patient.py @@ -1,8 +1,9 @@ from odoo import models, fields, _, api, Command from odoo.exceptions import ValidationError -from datetime import date +from datetime import date, datetime from dateutil.relativedelta import relativedelta from odoo.addons.phone_validation.tools import phone_validation +import pytz class Patient(models.Model): @@ -216,6 +217,7 @@ class PatientContact(models.Model): ('other', 'Other'), ], required=True) mobile = fields.Char(unaccent=False, required=True) + # TODO: add email here and on views patient_id = fields.Many2one(comodel_name='sports.patient', string='Patient') @api.onchange('mobile') @@ -242,14 +244,25 @@ class PatientInjury(models.Model): _inherit = ['mail.thread', 'mail.activity.mixin'] _rec_name = 'diagnosis' + @api.model + def _today(self): + """Get the current date in the user's time zone.""" + return datetime.now(pytz.timezone(self.env.user.tz or 'GMT')) + + # TODO: Find a way to improve notifications send about tracking injury details + # TODO: Add field consentement_parental = fields.Selection(oui, non, non-applicable) + patient_id = fields.Many2one(comodel_name='sports.patient', string="Patient", readonly=True, required=True) patient_name = fields.Char(related="patient_id.name") diagnosis = fields.Char(tracking=True) - injury_date = fields.Date(string='Date of Injury', - default=date.today()) + + injury_date = fields.Date( + string='Date of Injury', + default=_today, + ) injury_date_na = fields.Boolean(string="N/A", default=False) internal_notes = fields.Html(tracking=True) external_notes = fields.Html(tracking=True) From 571c6cccb4f4bea03012c4e488969f28152641b4 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Fri, 26 Jan 2024 15:20:39 -0500 Subject: [PATCH 50/96] bemade_fsm: add start and end date/time to work order PDF --- bemade_fsm/__manifest__.py | 7 +- .../worksheet_custom_report_templates.xml | 14 ++ bemade_fsm/reports/worksheet_templates.xml | 146 ------------------ 3 files changed, 15 insertions(+), 152 deletions(-) delete mode 100644 bemade_fsm/reports/worksheet_templates.xml diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index 12cf85a..78f0d36 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.8', + 'version': '15.0.1.0.9', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', @@ -56,11 +56,6 @@ 'wizard/new_task_from_template.xml', ], 'assets': { - 'web.assets_tests': [ - 'bemade_fsm/static/tests/tours/task_template_tour.js', - 'bemade_fsm/static/tests/tours/equipment_tour.js', - 'bemade_fsm/static/tests/tours/sale_order_tour.js', - ], 'web.report_assets_common': [ 'bemade_fsm/static/src/scss/bemade_fsm.scss' ], diff --git a/bemade_fsm/reports/worksheet_custom_report_templates.xml b/bemade_fsm/reports/worksheet_custom_report_templates.xml index 192455a..7436646 100644 --- a/bemade_fsm/reports/worksheet_custom_report_templates.xml +++ b/bemade_fsm/reports/worksheet_custom_report_templates.xml @@ -242,6 +242,20 @@
+
+
+
Planned start:
+
+
+
+
+
+
Planned end:
+
+
+
+
+
Site Contacts:
diff --git a/bemade_fsm/reports/worksheet_templates.xml b/bemade_fsm/reports/worksheet_templates.xml deleted file mode 100644 index 026f037..0000000 --- a/bemade_fsm/reports/worksheet_templates.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - - - Complete Worksheet Report (PDF) - project.task - qweb-pdf - bemade_fsm.worksheet_complete - - '%s Worksheet %s' % (time.strftime('%Y-%m-%d'), object.name) - - - report - - - - - - - - \ No newline at end of file From fb7b0cb3b6783dd8803bdefa3b280bd9e1c073b6 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Fri, 26 Jan 2024 15:53:51 -0500 Subject: [PATCH 51/96] bemade_fsm: updated translations for FR --- bemade_fsm/i18n/fr.po | 154 +++++++++++++++++++++++++++++++----------- 1 file changed, 114 insertions(+), 40 deletions(-) diff --git a/bemade_fsm/i18n/fr.po b/bemade_fsm/i18n/fr.po index facf7ab..532b57e 100644 --- a/bemade_fsm/i18n/fr.po +++ b/bemade_fsm/i18n/fr.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 15.0+e\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-10-02 20:26+0000\n" -"PO-Revision-Date: 2023-10-02 20:26+0000\n" +"POT-Creation-Date: 2024-01-26 20:41+0000\n" +"PO-Revision-Date: 2024-01-26 20:41+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -56,12 +56,12 @@ msgstr "" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table msgid "Taxes" -msgstr "" +msgstr "Taxes" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table msgid "Total" -msgstr "" +msgstr "Total" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table @@ -86,18 +86,18 @@ msgstr "" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__activity_state msgid "Activity State" -msgstr "" +msgstr "État de l'activité" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__activity_type_icon msgid "Activity Type Icon" -msgstr "" +msgstr "Icône du type d'activité" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__tag_ids #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_equipment_summary msgid "Application" -msgstr "" +msgstr "Application" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__approx_date @@ -119,14 +119,12 @@ msgstr "Bloqué" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_project_task__allow_billable msgid "Can be billed" -msgstr "" +msgstr "Peut être facturé" #. module: bemade_fsm -#: model:ir.model.fields,help:bemade_fsm.field_res_partner__is_site_contact -#: model:ir.model.fields,help:bemade_fsm.field_res_users__is_site_contact -msgid "" -"Check if the contact is a site contact, otherwise it is a not in that list" -msgstr "" +#: model_terms:ir.ui.view,arch_db:bemade_fsm.project_task_from_template_wizard_view_form +msgid "Cancel" +msgstr "Annuler" #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_bemade_fsm_equipment__tag_ids @@ -146,7 +144,7 @@ msgstr "Équipement client" #: model:ir.ui.menu,name:bemade_fsm.menu_service_client #: model:ir.ui.menu,name:bemade_fsm.menu_service_client_clients msgid "Clients" -msgstr "" +msgstr "Clients" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag__color @@ -171,18 +169,29 @@ msgstr "Complété" #. module: bemade_fsm #: model:ir.model,name:bemade_fsm.model_res_partner msgid "Contact" -msgstr "" +msgstr "Contact" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.sale_order_form_inherit msgid "Contacts and Equipment" msgstr "Contacts et équipements" +#. module: bemade_fsm +#: model_terms:ir.ui.view,arch_db:bemade_fsm.project_task_from_template_wizard_view_form +msgid "Create Task" +msgstr "Créer une tâche" + +#. module: bemade_fsm +#: model:ir.model,name:bemade_fsm.model_project_task_from_template_wizard +msgid "Create Task from Template Wizard" +msgstr "Assistant pour création de tâche à partir d'un gabarit" + #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__create_uid #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag__create_uid #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_type__create_uid #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__create_uid +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard__create_uid #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template__create_uid msgid "Created by" msgstr "Créé par" @@ -192,6 +201,7 @@ msgstr "Créé par" #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag__create_date #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_type__create_date #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__create_date +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard__create_date #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template__create_date msgid "Created on" msgstr "Date de création" @@ -257,7 +267,7 @@ msgstr "Livré" #: model_terms:ir.ui.view,arch_db:bemade_fsm.task_template_form_view #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table msgid "Description" -msgstr "" +msgstr "Description" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.view_task_form2_inherit @@ -274,6 +284,7 @@ msgstr "Détails" #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag__display_name #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_type__display_name #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__display_name +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard__display_name #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template__display_name msgid "Display Name" msgstr "Nom pour affichage" @@ -286,7 +297,7 @@ msgstr "Employés assignés aux tâches créées à partir de ce gabarit." #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_project_task__planned_date_end msgid "End Date" -msgstr "" +msgstr "Date de fin" #. module: bemade_fsm #: model:ir.actions.act_window,name:bemade_fsm.action_window_equipment @@ -302,8 +313,9 @@ msgstr "Équipement désservi" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_res_partner__equipment_count +#: model:ir.model.fields,field_description:bemade_fsm.field_res_users__equipment_count msgid "Equipment Count" -msgstr "" +msgstr "Nombre d'équipemenets" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__complete_name @@ -313,7 +325,7 @@ msgstr "Nom d'équipement" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_equipment_summary msgid "Equipment Serviced" -msgstr "Équipement désservi" +msgstr "Équipement(s) désservi" #. module: bemade_fsm #: model:ir.actions.act_window,name:bemade_fsm.action_window_equipment_tags @@ -347,12 +359,7 @@ msgstr "Durée estimée" #. module: bemade_fsm #: model:project.task.type,name:bemade_fsm.planning_project_stage_exception msgid "Exception" -msgstr "" - -#. module: bemade_fsm -#: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__failed_message_ids -msgid "Failed Messages" -msgstr "Messages échoués" +msgstr "Exception" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.bemade_fsm_project_task_form_inherit @@ -389,7 +396,7 @@ msgstr "Abonnés (partenaires)" #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_bemade_fsm_equipment__activity_type_icon msgid "Font awesome icon e.g. fa-tasks" -msgstr "" +msgstr "Icône Font Awesome p.ex. fa-tasks" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_sale_order_line__is_fully_delivered @@ -416,9 +423,10 @@ msgstr "A un message" #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag__id #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_type__id #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__id +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard__id #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template__id msgid "ID" -msgstr "" +msgstr "Identifiant" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__activity_exception_icon @@ -455,7 +463,8 @@ msgstr "En cours" msgid "" "Indicates whether a line or all the lines in a section have been entirely " "delivered and invoiced." -msgstr "" +msgstr "Indique si une ligne ou toutes les lignes dans une section ont été entièrement " +"livrées et facturées." #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_bemade_fsm_visit__is_completed @@ -480,13 +489,19 @@ msgstr "Nom d'intervention" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__task_ids msgid "Interventions" -msgstr "" +msgstr "Interventions" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__is_invoiced msgid "Invoiced" msgstr "Facturé" +#. module: bemade_fsm +#: model:ir.model.fields,field_description:bemade_fsm.field_sale_order__is_fsm +#: model:ir.model.fields,field_description:bemade_fsm.field_sale_order_line__is_fsm +msgid "Is FSM" +msgstr "Est FSM" + #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_sale_order_line__is_field_service msgid "Is Field Service" @@ -501,7 +516,7 @@ msgstr "Est un abonné" #: model:ir.model.fields,field_description:bemade_fsm.field_res_partner__is_site_contact #: model:ir.model.fields,field_description:bemade_fsm.field_res_users__is_site_contact msgid "Is a site contact" -msgstr "" +msgstr "Est un contact sur site" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__label @@ -513,6 +528,7 @@ msgstr "Nom" #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag____last_update #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_type____last_update #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit____last_update +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard____last_update #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template____last_update msgid "Last Modified on" msgstr "Dernière modification" @@ -522,6 +538,7 @@ msgstr "Dernière modification" #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag__write_uid #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_type__write_uid #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__write_uid +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard__write_uid #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template__write_uid msgid "Last Updated by" msgstr "Modifié par" @@ -531,6 +548,7 @@ msgstr "Modifié par" #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag__write_date #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_type__write_date #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__write_date +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard__write_date #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template__write_date msgid "Last Updated on" msgstr "Dernière mise à jour" @@ -558,7 +576,7 @@ msgstr "Erreur de livraison de message" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__message_ids msgid "Messages" -msgstr "" +msgstr "Messages" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__my_activity_date_deadline @@ -573,9 +591,14 @@ msgid "Name" msgstr "Nom" #. module: bemade_fsm -#: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__activity_calendar_event_id -msgid "Next Activity Calendar Event" -msgstr "Évènement au calendrier de la prochaine activité" +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard__new_task_title +msgid "New Task Title" +msgstr "Nouveau titre de tâche" + +#. module: bemade_fsm +#: model:ir.actions.act_window,name:bemade_fsm.action_new_task_from_template +msgid "New Task from Template" +msgstr "Nouvelle tâche à partir d'un gabarit" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__activity_date_deadline @@ -636,6 +659,7 @@ msgid "P&ID Tag" msgstr "Tag P&ID" #. module: bemade_fsm +#: model_terms:ir.ui.view,arch_db:bemade_fsm.project_task_view_search_fsm_inherit #: model_terms:ir.ui.view,arch_db:bemade_fsm.task_template_search_view msgid "Parent Task" msgstr "Tâche parent" @@ -661,6 +685,16 @@ msgstr "Notes sur l'emplacement physique" msgid "Plan as field service" msgstr "Planifier comme service terrain" +#. module: bemade_fsm +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_info_block +msgid "Planned end:" +msgstr "Fin planifiée :" + +#. module: bemade_fsm +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_info_block +msgid "Planned start:" +msgstr "Début planifié :" + #. module: bemade_fsm #: model:ir.model,name:bemade_fsm.model_product_template msgid "Product Template" @@ -677,10 +711,21 @@ msgstr "" " considéré lors de la planification." #. module: bemade_fsm +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard__project_id #: model_terms:ir.ui.view,arch_db:bemade_fsm.task_template_search_view msgid "Project" msgstr "Projet" +#. module: bemade_fsm +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task__propagate_assignment +msgid "Propagate Assignment" +msgstr "Propager l'assignation" + +#. module: bemade_fsm +#: model:ir.model.fields,help:bemade_fsm.field_project_task__propagate_assignment +msgid "Propagate assignment of this task to all subtasks." +msgstr "Propager l'assignation de cette tâche à toutes les sous-tâches." + #. module: bemade_fsm #: model:project.task.type,legend_done:bemade_fsm.planning_project_stage_exception #: model:project.task.type,legend_done:bemade_fsm.planning_project_stage_waiting_parts @@ -722,7 +767,12 @@ msgstr "Commande de ventes" #. module: bemade_fsm #: model:ir.model,name:bemade_fsm.model_sale_order_line msgid "Sales Order Line" -msgstr "Ligne de commandes de vente" +msgstr "Ligne de bons de commande" + +#. module: bemade_fsm +#: model:ir.model.fields,field_description:bemade_fsm.field_sale_order_line__section_line_ids +msgid "Section Line" +msgstr "Section" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template__sequence @@ -742,7 +792,7 @@ msgstr "Visites de service" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_signature_block msgid "Signature" -msgstr "" +msgstr "Signature" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_project_task__site_contacts @@ -759,18 +809,19 @@ msgstr "Contacts sur site :" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_res_partner__equipment_ids +#: model:ir.model.fields,field_description:bemade_fsm.field_res_users__equipment_ids msgid "Site Equipment" -msgstr "" +msgstr "Équipement sur site" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_project_task__planned_date_begin msgid "Start Date" -msgstr "" +msgstr "Date de début" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_tasks_table msgid "Status" -msgstr "" +msgstr "Status" #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_bemade_fsm_equipment__activity_state @@ -816,6 +867,7 @@ msgstr "Tâche" #: model:ir.actions.act_window,name:bemade_fsm.task_template_act_window #: model:ir.model.fields,field_description:bemade_fsm.field_product_product__task_template_id #: model:ir.model.fields,field_description:bemade_fsm.field_product_template__task_template_id +#: model:ir.model.fields,field_description:bemade_fsm.field_project_task_from_template_wizard__task_template_id #: model_terms:ir.ui.view,arch_db:bemade_fsm.task_template_form_view #: model_terms:ir.ui.view,arch_db:bemade_fsm.task_template_search_view #: model_terms:ir.ui.view,arch_db:bemade_fsm.task_template_tree_view @@ -855,6 +907,11 @@ msgstr "" "L'équipement à désservir par défaut pour les nouveaux articles de commande " "de ventes." +#. module: bemade_fsm +#: model:ir.model.fields,help:bemade_fsm.field_project_task_from_template_wizard__project_id +msgid "The project the new task should be created in." +msgstr "" + #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_bemade_fsm_visit__so_section_id msgid "" @@ -864,6 +921,19 @@ msgstr "" "La section sur la commande de vente représentant la main d'oeuvre et les " "pièces pour cette visite" +#. module: bemade_fsm +#: model:ir.model.fields,help:bemade_fsm.field_project_task_from_template_wizard__task_template_id +msgid "The template to use when creating the new task." +msgstr "" + +#. module: bemade_fsm +#: model:ir.model.fields,help:bemade_fsm.field_project_task_from_template_wizard__new_task_title +msgid "" +"The title (name) for the newly created task. If left blank, the name of the " +"template will be used." +msgstr "Le titre (nom) de la nouvelle tâche. Si laissé vide, le nom du " +"gabarit sera utilisé." + #. module: bemade_fsm #: model_terms:ir.actions.act_window,help:bemade_fsm.task_template_act_window msgid "There are no task templates, click above to create one." @@ -909,10 +979,14 @@ msgstr "Voir tâche" #: model:ir.model.fields,field_description:bemade_fsm.field_project_task__visit_id #: model:ir.model.fields,field_description:bemade_fsm.field_sale_order__visit_ids #: model:ir.model.fields,field_description:bemade_fsm.field_sale_order_line__visit_id -#: model:ir.model.fields,field_description:bemade_fsm.field_sale_order_line__visit_ids msgid "Visit" msgstr "Visite" +#. module: bemade_fsm +#: model:ir.model.fields,field_description:bemade_fsm.field_sale_order_line__visit_ids +msgid "Visits" +msgstr "Visites" + #. module: bemade_fsm #: model:project.task.type,name:bemade_fsm.planning_project_stage_waiting_parts msgid "Waiting on Parts" From 9a9b56cea78ed758c78043fd93adb0d8f3434bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20V=C3=A9zina?= Date: Thu, 1 Feb 2024 14:17:16 -0500 Subject: [PATCH 52/96] Update __manifest__.py --- bemade_sethy_configuration/__manifest__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bemade_sethy_configuration/__manifest__.py b/bemade_sethy_configuration/__manifest__.py index 6dbd6c9..a3040d3 100644 --- a/bemade_sethy_configuration/__manifest__.py +++ b/bemade_sethy_configuration/__manifest__.py @@ -22,7 +22,8 @@ 'membership_variable_period', 'membership_delegated_partner', 'partner_multi_relation', - 'sale_management' + 'sale_management', + 'base_automation' ], 'data': [ # Reference to XML, CSV, and other data files From c8dc89cf29e3f912d77dd24eb001b0496bb1e6ad Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 5 Feb 2024 11:48:47 -0500 Subject: [PATCH 53/96] bemade_packing_wizard: bug fix on package creation --- bemade_packing_wizard/__manifest__.py | 2 +- bemade_packing_wizard/wizard/choose_delivery_package.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bemade_packing_wizard/__manifest__.py b/bemade_packing_wizard/__manifest__.py index 41b136d..0e822a8 100644 --- a/bemade_packing_wizard/__manifest__.py +++ b/bemade_packing_wizard/__manifest__.py @@ -1,6 +1,6 @@ { 'name': 'Packing wizard', - 'version': '15.0.1.0.0', + 'version': '15.0.1.0.1', 'category': 'Extra Tools', 'summary': 'Allow automated packing type creation', 'description': """ diff --git a/bemade_packing_wizard/wizard/choose_delivery_package.py b/bemade_packing_wizard/wizard/choose_delivery_package.py index 55a0a9e..f7cfc01 100644 --- a/bemade_packing_wizard/wizard/choose_delivery_package.py +++ b/bemade_packing_wizard/wizard/choose_delivery_package.py @@ -59,7 +59,7 @@ class ChooseDeliveryPackage(models.TransientModel): # if no package type found, create one if not delivery_package_type: delivery_package_type = delivery_package_type.create({ - 'name': f'Box {vals["width"]}x{vals["height"]}x{vals["length"]}', + 'name': f'Box {self.width}x{self.height}x{self.length}', 'width': self.width, 'height': self.height, 'packaging_length': self.length, From 8b1d9c0aa9f9dc13ed85f71d85b91ae19c1af4b6 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 19 Dec 2023 19:09:47 -0500 Subject: [PATCH 54/96] bemade_fsm: fixed tests on propagate assignment due to new default. --- bemade_fsm/tests/test_task.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bemade_fsm/tests/test_task.py b/bemade_fsm/tests/test_task.py index c2b5543..e04cffc 100644 --- a/bemade_fsm/tests/test_task.py +++ b/bemade_fsm/tests/test_task.py @@ -23,7 +23,8 @@ class TaskTest(BemadeFSMBaseTest): task.propagate_assignment = True task.write({ - 'user_ids': [Command.set([self.user.id])] + 'user_ids': [Command.set([self.user.id])], + 'propagate_assignment': True, }) self.assertTrue(all([t.user_ids == self.user for t in task | task._get_all_subtasks()])) @@ -31,7 +32,8 @@ class TaskTest(BemadeFSMBaseTest): def test_reassigning_task_doesnt_propagate_by_default(self): task = self.task task.write({ - 'user_ids': [Command.set([self.user.id])] + 'user_ids': [Command.set([self.user.id])], + 'propagate_assignment': True, }) self.assertFalse(any([t.user_ids for t in task.child_ids.child_ids])) From 5f414db90967c67d64448f62b167b1ed6acb227b Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 12 Feb 2024 17:02:56 -0500 Subject: [PATCH 55/96] bemade_fsm: update work order titles to match new specs --- bemade_fsm/__manifest__.py | 2 +- bemade_fsm/models/task.py | 2 +- bemade_fsm/reports/worksheet_custom_report_templates.xml | 5 ++++- bemade_fsm/reports/worksheet_custom_reports.xml | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index 78f0d36..e6da671 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.9', + 'version': '15.0.1.0.10', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', diff --git a/bemade_fsm/models/task.py b/bemade_fsm/models/task.py index b7f2fb0..56ab0ac 100644 --- a/bemade_fsm/models/task.py +++ b/bemade_fsm/models/task.py @@ -94,7 +94,7 @@ class Task(models.Model): pattern = re.compile(r"\d+$") matches = map(lambda n: pattern.search(n), prev_seqs) seq += max(map(lambda n: int(n.group(1)) if n else 0), matches) - rec.work_order_number = rec.sale_order_id.name.replace('SO', 'WO', 1) \ + rec.work_order_number = rec.sale_order_id.name.replace('SO', 'SVR', 1) \ + f"-{seq}" return res diff --git a/bemade_fsm/reports/worksheet_custom_report_templates.xml b/bemade_fsm/reports/worksheet_custom_report_templates.xml index 7436646..6e3dcc2 100644 --- a/bemade_fsm/reports/worksheet_custom_report_templates.xml +++ b/bemade_fsm/reports/worksheet_custom_report_templates.xml @@ -218,7 +218,10 @@ - \ No newline at end of file + From 095160db5f7ac363ab459d31bbc0c1656358e32e Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Mon, 12 Feb 2024 21:25:04 -0500 Subject: [PATCH 58/96] bemade_fsm: add spacing in header section --- bemade_fsm/reports/worksheet_custom_report_templates.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bemade_fsm/reports/worksheet_custom_report_templates.xml b/bemade_fsm/reports/worksheet_custom_report_templates.xml index 1cf24c0..63cbcb3 100644 --- a/bemade_fsm/reports/worksheet_custom_report_templates.xml +++ b/bemade_fsm/reports/worksheet_custom_report_templates.xml @@ -226,7 +226,7 @@ - + /> -
From 59eb7e2239ba8b810e25120ac5b7649ba62e0249 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 13 Feb 2024 12:26:13 -0500 Subject: [PATCH 59/96] bemade_fsm: significant changes to work order report - Remove date from main title heading (only in planned start) - Add customer PO number under main heading - Remove technician assignment info (only in timesheets) - Add table for timesheet entries - Remove time from time and materials section - Hide visit section headers from materials section - Add a section for showing the description of the visit task - Add some
elements for better visual separation --- bemade_fsm/__manifest__.py | 2 +- bemade_fsm/i18n/fr.po | 152 ++++++++++++------ .../worksheet_custom_report_templates.xml | 147 +++++++++++++---- 3 files changed, 217 insertions(+), 84 deletions(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index e6da671..26450fe 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -20,7 +20,7 @@ ######################################################################################## { 'name': 'Improved Field Service Management', - 'version': '15.0.1.0.10', + 'version': '15.0.1.0.11', 'summary': 'Adds functionality necessary for managing field service operations at Durpro.', 'description': 'Adds functionality necessary for managing field service operations at Durpro.', 'category': 'Services/Field Service', diff --git a/bemade_fsm/i18n/fr.po b/bemade_fsm/i18n/fr.po index 532b57e..dc46097 100644 --- a/bemade_fsm/i18n/fr.po +++ b/bemade_fsm/i18n/fr.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 15.0+e\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-26 20:41+0000\n" -"PO-Revision-Date: 2024-01-26 20:41+0000\n" +"POT-Creation-Date: 2024-02-13 17:09+0000\n" +"PO-Revision-Date: 2024-02-13 17:09+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -16,7 +16,7 @@ msgstr "" "Plural-Forms: \n" #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "" "\n" " Amount\n" @@ -24,9 +24,9 @@ msgid "" " Total Price" msgstr "" "\n" -" Prix\n" +" Montant\n" " \n" -" Prix" +" Prix Total" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_signature_block @@ -40,12 +40,12 @@ msgstr "" " " #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "Disc.%" -msgstr "Escompte %" +msgstr "% Escompte" #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "" "Section\n" " Subtotal" @@ -54,19 +54,19 @@ msgstr "" " Sous-total" #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "Taxes" -msgstr "Taxes" +msgstr "" #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "Total" -msgstr "Total" +msgstr "" #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "Untaxed amount" -msgstr "Montant hors taxes" +msgstr "Montant hors-taxes" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__message_needaction @@ -78,11 +78,6 @@ msgstr "Action requise" msgid "Activities" msgstr "Activités" -#. module: bemade_fsm -#: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__activity_exception_decoration -msgid "Activity Exception Decoration" -msgstr "" - #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__activity_state msgid "Activity State" @@ -97,7 +92,7 @@ msgstr "Icône du type d'activité" #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__tag_ids #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_equipment_summary msgid "Application" -msgstr "Application" +msgstr "" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__approx_date @@ -144,7 +139,7 @@ msgstr "Équipement client" #: model:ir.ui.menu,name:bemade_fsm.menu_service_client #: model:ir.ui.menu,name:bemade_fsm.menu_service_client_clients msgid "Clients" -msgstr "Clients" +msgstr "" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag__color @@ -169,7 +164,7 @@ msgstr "Complété" #. module: bemade_fsm #: model:ir.model,name:bemade_fsm.model_res_partner msgid "Contact" -msgstr "Contact" +msgstr "" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.sale_order_form_inherit @@ -181,11 +176,26 @@ msgstr "Contacts et équipements" msgid "Create Task" msgstr "Créer une tâche" +#. module: bemade_fsm +#. openerp-web +#: code:addons/bemade_fsm/static/src/xml/project_view_buttons.xml:0 +#: code:addons/bemade_fsm/static/src/xml/project_view_buttons.xml:0 +#, python-format +msgid "Create Task from Template" +msgstr "Créer une tâche à partir d'un gabarit" + #. module: bemade_fsm #: model:ir.model,name:bemade_fsm.model_project_task_from_template_wizard msgid "Create Task from Template Wizard" msgstr "Assistant pour création de tâche à partir d'un gabarit" +#. module: bemade_fsm +#. openerp-web +#: code:addons/bemade_fsm/static/src/xml/project_view_buttons.xml:0 +#, python-format +msgid "Create from Template" +msgstr "Créer à partir d'un gabarit" + #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__create_uid #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment_tag__create_uid @@ -216,6 +226,11 @@ msgstr "Client" msgid "Customer:" msgstr "Client :" +#. module: bemade_fsm +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_timesheet_entries +msgid "Date" +msgstr "" + #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template__assignees msgid "Default Assignees" @@ -257,7 +272,8 @@ msgid "Default tags for tasks created from this template." msgstr "Étiquettes par défaut pour tâches créées à partir de ce gabarit." #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_materials_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "Delivered" msgstr "Livré" @@ -265,9 +281,10 @@ msgstr "Livré" #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__description #: model:ir.model.fields,field_description:bemade_fsm.field_project_task_template__description #: model_terms:ir.ui.view,arch_db:bemade_fsm.task_template_form_view -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_materials_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "Description" -msgstr "Description" +msgstr "" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.view_task_form2_inherit @@ -359,7 +376,7 @@ msgstr "Durée estimée" #. module: bemade_fsm #: model:project.task.type,name:bemade_fsm.planning_project_stage_exception msgid "Exception" -msgstr "Exception" +msgstr "" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.bemade_fsm_project_task_form_inherit @@ -463,8 +480,9 @@ msgstr "En cours" msgid "" "Indicates whether a line or all the lines in a section have been entirely " "delivered and invoiced." -msgstr "Indique si une ligne ou toutes les lignes dans une section ont été entièrement " -"livrées et facturées." +msgstr "" +"Indique si une ligne ou toutes les lignes dans une section ont été " +"entièrement livrées et facturées." #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_bemade_fsm_visit__is_completed @@ -489,7 +507,7 @@ msgstr "Nom d'intervention" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__task_ids msgid "Interventions" -msgstr "Interventions" +msgstr "" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__is_invoiced @@ -568,6 +586,11 @@ msgstr "Pièce jointe principale" msgid "Mark as Delivered" msgstr "Marquer comme livré" +#. module: bemade_fsm +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_materials_table +msgid "Materials" +msgstr "Matériaux" + #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__message_has_error msgid "Message Delivery error" @@ -576,7 +599,16 @@ msgstr "Erreur de livraison de message" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__message_ids msgid "Messages" -msgstr "Messages" +msgstr "" + +#. module: bemade_fsm +#: code:addons/bemade_fsm/models/task.py:0 +#, python-format +msgid "" +"Modifying the planned start or end time on a task is not permitted when that" +" task already has planning records associated to it. Please modify or delete" +" the planning records instead." +msgstr "" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_equipment__my_activity_date_deadline @@ -641,7 +673,8 @@ msgid "Number of unread messages" msgstr "Nombre de messages non-lus" #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_materials_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "Ordered" msgstr "Commandé" @@ -698,7 +731,7 @@ msgstr "Début planifié :" #. module: bemade_fsm #: model:ir.model,name:bemade_fsm.model_product_template msgid "Product Template" -msgstr "Modèle de produit" +msgstr "Modèle d'article" #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_product_product__is_field_service @@ -762,7 +795,7 @@ msgstr "Section de commande de vente" #: model:ir.model,name:bemade_fsm.model_sale_order #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__sale_order_id msgid "Sales Order" -msgstr "Commande de ventes" +msgstr "Bon de commande" #. module: bemade_fsm #: model:ir.model,name:bemade_fsm.model_sale_order_line @@ -780,7 +813,9 @@ msgid "Sequence" msgstr "Séquence" #. module: bemade_fsm +#: code:addons/bemade_fsm/models/sale_order.py:0 #: model:ir.model.fields,field_description:bemade_fsm.field_bemade_fsm_visit__task_id +#, python-format msgid "Service Visit" msgstr "Visite de service" @@ -792,7 +827,7 @@ msgstr "Visites de service" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_signature_block msgid "Signature" -msgstr "Signature" +msgstr "" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_project_task__site_contacts @@ -821,7 +856,7 @@ msgstr "Date de début" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_tasks_table msgid "Status" -msgstr "Status" +msgstr "" #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_bemade_fsm_equipment__activity_state @@ -887,14 +922,10 @@ msgstr "Nom de tâche" #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_tasks_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_timesheet_entries msgid "Technician" msgstr "Technicien·ne" -#. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_info_block -msgid "Technicians:" -msgstr "Technicien·ne·s:" - #. module: bemade_fsm #: model:ir.model,name:bemade_fsm.model_project_task_template msgid "Template for new project tasks" @@ -924,15 +955,16 @@ msgstr "" #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_project_task_from_template_wizard__task_template_id msgid "The template to use when creating the new task." -msgstr "" +msgstr "Le gabarit à utiliser en créant la nouvelle tâche." #. module: bemade_fsm #: model:ir.model.fields,help:bemade_fsm.field_project_task_from_template_wizard__new_task_title msgid "" "The title (name) for the newly created task. If left blank, the name of the " "template will be used." -msgstr "Le titre (nom) de la nouvelle tâche. Si laissé vide, le nom du " -"gabarit sera utilisé." +msgstr "" +"Le titre (nom) de la nouvelle tâche. Si laissé vide, le nom du gabarit sera " +"utilisé." #. module: bemade_fsm #: model_terms:ir.actions.act_window,help:bemade_fsm.task_template_act_window @@ -941,7 +973,22 @@ msgstr "" "Il n'existe aucun gabarit de tâche, cliquez ci-dessus pour en créer une." #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: code:addons/bemade_fsm/models/sale_order_line.py:0 +#, python-format +msgid "" +"This task has been created from: %s (%s)" +msgstr "" +"Cette tâche a été créée à partir de : %s (%s)" + +#. module: bemade_fsm +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_timesheet_entries +msgid "Time" +msgstr "Temps" + +#. module: bemade_fsm +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "Time & Material" msgstr "Temps & matériaux" @@ -956,7 +1003,7 @@ msgid "Type of the exception activity on record." msgstr "Type d'activité d'exception sur l'enregistrement." #. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_sale_order_table_with_pricing_and_labour msgid "Unit Price" msgstr "Prix unitaire" @@ -976,9 +1023,11 @@ msgid "View Task" msgstr "Voir tâche" #. module: bemade_fsm +#: code:addons/bemade_fsm/models/sale_order_line.py:0 #: model:ir.model.fields,field_description:bemade_fsm.field_project_task__visit_id #: model:ir.model.fields,field_description:bemade_fsm.field_sale_order__visit_ids #: model:ir.model.fields,field_description:bemade_fsm.field_sale_order_line__visit_id +#, python-format msgid "Visit" msgstr "Visite" @@ -1002,24 +1051,23 @@ msgstr "Messages du site web" msgid "Website communication history" msgstr "Historique de communication du site web" +#. module: bemade_fsm +#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_timesheet_entries +msgid "Work Completed" +msgstr "Travaux complétés" + #. module: bemade_fsm #: model:project.task.type,name:bemade_fsm.planning_project_stage_work_completed msgid "Work Executed" msgstr "Travaux exécutés" -#. module: bemade_fsm -#: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_info_block -msgid "Work Order" -msgstr "Bon de travail" - #. module: bemade_fsm #: model_terms:ir.ui.view,arch_db:bemade_fsm.workorder_page_info_block msgid "" "Work Order\n" " Contacts:" msgstr "" -"Bon de travail\n" -" Contacts :" +"Contacts recevant le bon de travail :" #. module: bemade_fsm #: model:ir.model.fields,field_description:bemade_fsm.field_project_task__work_order_contacts diff --git a/bemade_fsm/reports/worksheet_custom_report_templates.xml b/bemade_fsm/reports/worksheet_custom_report_templates.xml index 63cbcb3..c8c98b3 100644 --- a/bemade_fsm/reports/worksheet_custom_report_templates.xml +++ b/bemade_fsm/reports/worksheet_custom_report_templates.xml @@ -1,7 +1,61 @@ - + - + + + + + + + From d9752bca8c53f0e6cb02b94e3a3c03d9eafa689c Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 19 Mar 2024 15:04:19 -0400 Subject: [PATCH 94/96] add github workflow to test odoo --- .github/workflows/test.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..c1fae87 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,33 @@ +name: tests + +on: + pull_request: + branches: + - "17.0-test-ci" + push: + branches: + -"17.0-test-ci" + +jobs: + test: + runs-on: ubuntu-22.04 + container: ghcr.io/bemade/test-odoo_arm64:latest + name: Test Repo Addons With Odoo + strategy: + fail-fast: false + services: + postgres: + image: postgres:12.0 + env: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoo + POSTGRES_DB: odoo + ports: + - 5432:5432 + steps: + - uses: actions/checkout@v4 + with: + persist-credientials: false + - name: Run Tests + run: run_tests.sh + From 75ca67c533875a58325ca7c76d1ed73e3d593f56 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 19 Mar 2024 15:11:03 -0400 Subject: [PATCH 95/96] Update test.yml --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c1fae87..29eb686 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,7 +6,7 @@ on: - "17.0-test-ci" push: branches: - -"17.0-test-ci" + - "17.0-test-ci" jobs: test: From 6d9d9529826e32b0ab31987ec510f5db2324b928 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Thu, 21 Mar 2024 07:32:12 -0400 Subject: [PATCH 96/96] fix merge conflict in bemade_fsm manifest --- bemade_fsm/__manifest__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/bemade_fsm/__manifest__.py b/bemade_fsm/__manifest__.py index a11a54c..a0c437f 100644 --- a/bemade_fsm/__manifest__.py +++ b/bemade_fsm/__manifest__.py @@ -52,12 +52,7 @@ 'views/menus.xml', 'views/task_views.xml', 'views/sale_order_views.xml', -<<<<<<< HEAD - # BV: need to readd this file - # 'reports/worksheet_custom_report_templates.xml', -======= 'reports/worksheet_custom_report_templates.xml', ->>>>>>> origin/16.0 'reports/worksheet_custom_reports.xml', 'wizard/new_task_from_template.xml', ],