diff --git a/__manifest__.py b/__manifest__.py index 55d8491878866520649857046ffc8629ae14f5bd..d6adf916defa14e2660a127f7be9c4f59cdef2db 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -1,20 +1,8 @@ -# -*- coding: utf-8 -*- # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { 'name': 'Le Filament - Link Sales Order to Project', - 'version': '10.0.1.0.0', + 'version': '12.0.1.0.0', 'license': 'AGPL-3', - 'description': """ - MODULE LINK SALE ORDER / PROJECT LE FILAMENT - - This module depends upon *sale_service* and *lefilament_projets* modules. - - - This module provides a new functionality to transform your sale order in - projects and tasks (and to update those in case sale order is updated) - - Product template has been enhanced, invoicing policy section in order to - set how each product should behave when transformed from sale order to - project/task. - """, 'author': 'LE FILAMENT', 'category': 'LE FILAMENT', 'depends': ['sale_timesheet', 'lefilament_projets'], @@ -23,8 +11,6 @@ ], 'website': 'http://www.le-filament.com', 'data': [ - 'views/product_views.xml', - 'views/sale_config_settings_views.xml', 'wizard/sale_views_wizard.xml', 'views/sale_views.xml', 'views/res_config_views.xml', diff --git a/i18n/fr.po b/i18n/fr.po index e675b4775cfcd4f774a16fd7b2d8161f6857c34a..b22618f8f503f8a7ded4e5a6a99165aceb1fdd19 100644 --- a/i18n/fr.po +++ b/i18n/fr.po @@ -206,6 +206,6 @@ msgid "sale.config.settings" msgstr "sale.config.settings" #. module: lefilament_link_sale_project -#: selection:product.template,track_service:0 +#: selection:product.template,service_tracking:0 msgid "Create a project and link tasks" msgstr "Créer un projet et lier des tâches" diff --git a/models/__init__.py b/models/__init__.py index b98ff0d95189d8b2b71a54ac21d375da3cf7b35c..b40f313571c05e53b29cae31c1d2988e5744abbd 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,10 +1,9 @@ # -*- coding: utf-8 -*- # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from . import product -from . import sale_config_settings -from . import res_config -from . import project_task_type from . import project from . import project_task -from . import sale_order \ No newline at end of file +from . import project_task_type +from . import res_company +from . import res_config +from . import sale_order diff --git a/models/product.py b/models/product.py deleted file mode 100644 index 8e39c66c6f60f36a1157654238cea886ef4b6036..0000000000000000000000000000000000000000 --- a/models/product.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- - -# © 2017 Le Filament (<https://le-filament.com>) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from odoo import fields, models - - -class LeFilamentProductTemplate(models.Model): - _inherit = 'product.template' - - project_task_type_id = fields.Many2one( - 'project.task.type', 'Project task stage') - track_service = fields.Selection(selection_add=[ - ('project', 'Create a project and link tasks')]) diff --git a/models/res_company.py b/models/res_company.py new file mode 100644 index 0000000000000000000000000000000000000000..c2b5970bc4bbc794f25f56282f8a5b587cccc8bb --- /dev/null +++ b/models/res_company.py @@ -0,0 +1,17 @@ +# © 2017 Le Filament (<https://le-filament.com>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = 'res.company' + + ## Project + lf_tarif_jour = fields.Float(string='Day Price',) + lf_alias_prefix = fields.Char(string='Alias prefix') + + ## Sale + project_task_type_id = fields.Many2one( + comodel_name='project.task.type', + string='Initial step') diff --git a/models/res_config.py b/models/res_config.py index 7b1bc4de0965400c50127f57f091a173869a4809..c9a40d34cb64150191766eb8a92426067dcb7fcf 100644 --- a/models/res_config.py +++ b/models/res_config.py @@ -1,35 +1,23 @@ -# -*- coding: utf-8 -*- - # © 2017 Le Filament (<https://le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models - - -class ProjectLFConfiguration(models.TransientModel): - _name = 'project.config.settings' - _inherit = 'project.config.settings' +from odoo import fields, models - lf_tarif_jour = fields.Float('Day Price') - lf_alias_prefix = fields.Char('Alias prefix') - @api.multi - def set_default_generate_project_alias(self): - Values = self.env['ir.values'].sudo() or self.env['ir.values'] - for config in self: - Values.set_default('project.config.settings', - 'generate_project_alias', - config.generate_project_alias) +class ResConfiguration(models.TransientModel): + _inherit = 'res.config.settings' - @api.multi - def set_default_lf_tarif_jour(self): - return self.env['ir.values'].sudo().set_default( - 'project.config.settings', 'lf_tarif_jour', self.lf_tarif_jour) + ## Project + lf_tarif_jour = fields.Float( + string='Day Price', + related='company_id.lf_tarif_jour', + readonly=False) + lf_alias_prefix = fields.Char( + string='Alias prefix', + related='company_id.lf_alias_prefix', + readonly=False) - @api.multi - def set_default_alias_prefix(self): - return self.env['ir.values'].sudo().set_default( - 'project.config.settings', - 'lf_alias_prefix', - self.lf_alias_prefix - ) + ## Sale + project_task_type_id = fields.Many2one( + related='company_id.project_task_type_id', + string='Initial step') diff --git a/models/sale_config_settings.py b/models/sale_config_settings.py deleted file mode 100644 index f41b27f9231c20a8ee357346d3f1a41637003811..0000000000000000000000000000000000000000 --- a/models/sale_config_settings.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- - -# © 2017 Le Filament (<https://le-filament.com>) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from odoo import api, fields, models - - -class LeFilamentSaleConfiguration(models.TransientModel): - _inherit = 'sale.config.settings' - - project_task_type_id = fields.Many2one( - 'project.task.type', 'Initial step') - - @api.multi - def set_project_task_type(self): - return self.env['ir.values'].sudo().set_default( - 'sale.config.settings', - 'project_task_type_id', - self.project_task_type_id.id - ) diff --git a/models/sale_order.py b/models/sale_order.py index a0fbc69e5ebc143d7e14b00565e80532922e71e3..ef815e39a5cc86567ce67eac49ddde1c9ce11241 100644 --- a/models/sale_order.py +++ b/models/sale_order.py @@ -14,15 +14,12 @@ class SaleOrder(models.Model): @api.multi def lefilament_update_tasks(self): for order in self: - stage_id_new = self.env['ir.values'].get_default( - 'sale.config.settings', 'project_task_type_id') + stage_id_new = self.env.user.company_id.project_task_type_id stage_new = self.env['project.task.type'].browse(stage_id_new) - lf_tarif_jour = self.env['ir.values'].get_default( - 'project.config.settings', 'lf_tarif_jour') - lf_heures_jour = self.env['ir.values'].get_default( - 'project.config.settings', 'lf_heures_jour') - sale_project_id = order.project_project_id - project_id = sale_project_id.id + lf_tarif_jour = self.env.user.company_id.lf_tarif_jour + lf_heures_jour = self.env.user.company_id.lf_heures_jour + + project_id = order.project_ids[0].id project_total_budget = 0 for line in order.order_line: task_id_refer = self.env['project.task'].search( @@ -50,7 +47,7 @@ class SaleOrder(models.Model): task_id_refer.planned_hours = planned_hours task_id_refer.price_subtotal = line.price_subtotal else: - if line.product_id.track_service == 'project': + if line.product_id.service_tracking == 'task_new_project': if line.product_id.project_id: project = line.product_id.project_id project_id = project.id @@ -119,7 +116,7 @@ class LeFilamentSaleOrderLine(models.Model): ) expense_type_id = expense_type_id and expense_type_id.id prod_list = self.env['product.template'].search( - [('track_service', 'in', ['task', 'timesheet'])] + [('service_type', 'in', ['task', 'timesheet'])] ) domain = [ ('product_id', 'in', prod_list.ids), diff --git a/views/product_views.xml b/views/product_views.xml deleted file mode 100644 index 0e936eb110b08372ec1f75838eb95677affaeb59..0000000000000000000000000000000000000000 --- a/views/product_views.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2017 Le Filament (<https://le-filament.com>) - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> -<odoo> - <record id="lefilament_view_product_timesheet_form" model="ir.ui.view"> - <field name="name">lefilament.product.template.timesheet.form</field> - <field name="model">product.template</field> - <field name="inherit_id" ref="sale_timesheet.view_product_timesheet_form"/> - <field name="arch" type="xml"> - <xpath expr="//field[@name='project_id']" position="attributes"> - <attribute name="attrs">{'invisible':['|', ('type','!=','service'), ('track_service', '<>', 'task'), ('track_service', '<>', 'project')]}</attribute> - </xpath> - <field name="project_id" position="after"> - <field name="project_task_type_id" attrs="{'invisible':['|', ('type','!=','service'), ('track_service', '<>', 'project')]}"/> - </field> - </field> - </record> -</odoo> diff --git a/views/project_views.xml b/views/project_views.xml index c28863c704ec0a639189ea683293dd0f35e3973c..8e10ca617ba2bd4f74a1f3889f5acb676ac84d17 100644 --- a/views/project_views.xml +++ b/views/project_views.xml @@ -31,7 +31,6 @@ <field name="arch" type="xml"> <xpath expr="//notebook" position="inside"> <page string="Project Stages" - attrs="{'invisible': [('use_tasks', '=', False)]}" name="project_stages"> <field name="type_ids"/> </page> diff --git a/views/res_config_views.xml b/views/res_config_views.xml index 6c33c6f545ab2a808b2cb866a90843f5cd163a96..ff96be7e8ce8aa6614e3a42e83edff4c6ed4b697 100644 --- a/views/res_config_views.xml +++ b/views/res_config_views.xml @@ -3,14 +3,58 @@ License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> <odoo> <record id="view_lefilament_project_config_settings" model="ir.ui.view"> - <field name="name">project.lefilament.settings</field> - <field name="model">project.config.settings</field> - <field name="inherit_id" ref="project.view_config_settings"/> + <field name="name">res.config.lefilament.project.settings</field> + <field name="model">res.config.settings</field> + <field name="inherit_id" ref="project.res_config_settings_view_form"/> <field name="arch" type="xml"> - <xpath expr="//field[@name='module_rating_project']" position="after"> - <field name="lf_tarif_jour" class="oe_inline oe_text_right" /> - <field name="lf_alias_prefix" class="oe_inline" /> + <xpath expr="//div[@id='use_collaborative_pad']" position="before"> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_left_pane"> + </div> + <div class="o_setting_right_pane"> + <div class="text-muted"> + Link Sale Project + </div> + <div class="content-group" > + <div class="row mt16"> + <label class="col-lg-3 o_light_label" for="lf_tarif_jour"/> + <field name="lf_tarif_jour"/> + </div> + <div class="row mt16"> + <label class="col-lg-3 o_light_label" for="lf_alias_prefix"/> + <field name="lf_alias_prefix"/> + </div> + </div> + </div> + </div> + </xpath> + </field> + </record> + + <record id="view_lefilament_sale_config_settings" model="ir.ui.view"> + <field name="name">res.config.lefilament.sale.settings</field> + <field name="model">res.config.settings</field> + <field name="inherit_id" ref="sale.res_config_settings_view_form"/> + <field name="arch" type="xml"> + <xpath expr="//div[@data-key='sale_management']" position="inside"> + <h2>Task</h2> + <div class="row mt16 o_settings_container" id="lefilament_link_sale_project"> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_left_pane"> + </div> + <div class="o_setting_right_pane"> + <div class="content-group" > + <div class="row mt16"> + <label class="col-lg-3 o_light_label" for="project_task_type_id"/> + <field name="project_task_type_id"/> + </div> + </div> + </div> + </div> + </div> </xpath> </field> </record> </odoo> + + diff --git a/views/sale_config_settings_views.xml b/views/sale_config_settings_views.xml deleted file mode 100644 index 94987bd6a464c4b821feb1d4e65857c92cdf6861..0000000000000000000000000000000000000000 --- a/views/sale_config_settings_views.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2017 Le Filament (<https://le-filament.com>) - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> -<odoo> - <record id="lefilament_view_sales_config" model="ir.ui.view"> - <field name="name">lefilament.sale.settings</field> - <field name="model">sale.config.settings</field> - <field name="inherit_id" ref="sale.view_sales_config"/> - <field name="arch" type="xml"> - <div id="main" position="inside"> - <group string="Task"> - <field name="project_task_type_id" class="oe_inline"/> - </group> - </div> - </field> - </record> -</odoo> diff --git a/views/sale_views.xml b/views/sale_views.xml index 5babd05b9a3d4204c25e66c7c305d7cc1d8e52d4..dee12bad228dcba25b9fee420c71caadcf2a6db9 100644 --- a/views/sale_views.xml +++ b/views/sale_views.xml @@ -10,8 +10,8 @@ <field name="inherit_id" ref="sale.view_order_form"/> <field name="arch" type="xml"> <header> - <button name="%(lefilament_open_create_project)d" type="action" string="Create project" attrs="{'invisible': ['|', ('project_project_id', '!=', False), ('state', '!=', 'sale')]}"/> - <button name="lefilament_update_tasks" type="object" string="Update tasks" attrs="{'invisible': ['|', ('project_project_id', '=', False), ('state', '!=', 'sale')]}" class="btn-primary"/> + <button name="%(lefilament_open_create_project)d" type="action" string="Create project" attrs="{'invisible': ['|', ('project_ids', '!=', False), ('state', '!=', 'sale')]}"/> + <button name="lefilament_update_tasks" type="object" string="Update tasks" attrs="{'invisible': ['|', ('project_ids', '=', False), ('state', '!=', 'sale')]}" class="btn-primary"/> </header> </field> </record> diff --git a/wizard/sale_views_wizard.py b/wizard/sale_views_wizard.py index 1e4ea7bf4d9c1799c4ce544372403ebe06983adb..f107bd48bb4924bb3e870d8067562ba8b96f0f41 100644 --- a/wizard/sale_views_wizard.py +++ b/wizard/sale_views_wizard.py @@ -17,8 +17,8 @@ class LeFilamentSaleWizard(models.TransientModel): return self.env['sale.order'].browse(self.env.context.get('active_id')) @api.model - def _default_project_project_id(self): - return self._default_sale_id().project_project_id + def _default_project_ids(self): + return self._default_sale_id().project_ids[0] @api.model def _default_related_project_id(self): @@ -34,7 +34,7 @@ class LeFilamentSaleWizard(models.TransientModel): sale_id = fields.Many2one('sale.order', string='Sale', default=_default_sale_id) project_id = fields.Many2one('project.project', string='Existing project', - default=_default_project_project_id) + default=_default_project_ids) project_name = fields.Char('New project', default=_default_project_name) related_project_id = fields.Many2one('account.analytic.account', string='Analytical account related', @@ -52,25 +52,21 @@ class LeFilamentSaleWizard(models.TransientModel): self.env.context.get('active_id')) if self.project_id: sale_id.project_id = self.project_id.analytic_account_id - sale_id.project_project_id = self.project_id + sale_id.project_ids = self.project_id project_id_new = self.project_id.id else: sale_id._create_analytic_account(prefix=None) project_id_new = sale_id.project_id.project_create( {'name': self.project_name, 'use_tasks': True}) - stage_id_new = self.env['ir.values'].get_default( - 'sale.config.settings', 'project_task_type_id') + + stage_id_new = self.env.user.company_id.project_task_type_id stage_new = self.env['project.task.type'].browse(stage_id_new) - lf_tarif_jour = self.env['ir.values'].get_default( - 'project.config.settings', 'lf_tarif_jour') - lf_heures_jour = self.env['ir.values'].get_default( - 'project.config.settings', 'lf_heures_jour') - lf_alias_prefix = self.env['ir.values'].get_default( - 'project.config.settings', 'lf_alias_prefix') - ir_values = self.env['ir.values'].get_default( - 'project.config.settings', 'generate_project_alias') + lf_tarif_jour = self.env.user.company_id.lf_tarif_jour + lf_heures_jour = self.env.user.company_id.lf_heures_jour + lf_alias_prefix = self.env.user.company_id.lf_alias_prefix + for line in sale_id.order_line: - if line.product_id.track_service == 'project': + if line.product_id.service_tracking == 'task_new_project': if line.product_id.project_id: project = line.product_id.project_id project_id = project.id @@ -103,7 +99,7 @@ class LeFilamentSaleWizard(models.TransientModel): + line.price_subtotal) project_date.lf_tarif_jour = lf_tarif_jour if not line.product_id.project_id: - if ir_values and lf_alias_prefix: + if lf_alias_prefix: lf_alias_name = lf_alias_prefix + project_date.name project_date.alias_name = lf_alias_name planned_hours = ((line.price_subtotal / lf_tarif_jour)