19 Commits

Author SHA1 Message Date
Boris Gallet
5d74a26247 [MIG] project_visibility_followers_portal: Migration to 16.0 2023-11-14 17:09:32 +01:00
Boris Gallet
93a6768716 [CLN] remove obsolete addon : project_timesheet_funding_wish 2023-11-08 16:18:59 +01:00
Boris Gallet
16c1da3c42 [MIG] project_timebox: Migration to 16.0 2023-11-08 16:05:05 +01:00
Boris Gallet
792c3d602a [FIX] project_parent_task : correct manifest 2023-11-08 14:52:25 +01:00
Boris Gallet
a06cd29014 [MIG] project_parent_task: Migration to 16.0 2023-11-08 14:51:57 +01:00
Boris Gallet
e9ec522405 [MIG] project_link_from_invoice: Migration to 16.0 2023-11-07 13:02:29 +01:00
Boris Gallet
6dc94c02fa [MIG] project_name_from_quote : Migration to 16.0 2023-11-07 11:44:52 +01:00
Boris Gallet
0e36b3d9e3 [MIG] project_name_from_lead: Migration to 16.0 2023-11-07 10:41:30 +01:00
Boris Gallet
a240b6cf71 [MIG] project_task_portal_form : migration to 16.0 2023-11-02 15:36:54 +01:00
Boris Gallet
2cd17ce8ef [MIG] project_average_acceptable_time : migration to 16.0 2023-11-02 15:10:49 +01:00
Boris Gallet
eb85069ff8 [MIG] project_user_default_project : migrate to 16’0 2023-11-02 11:27:56 +01:00
Boris Gallet
38e12ee2ed [MIG] project_request_data : migrate to 16.0 2023-11-02 09:49:21 +01:00
Boris Gallet
15b21771dd [MIG] project_assignees : migrate to 16.0 2023-11-02 09:14:47 +01:00
Boris Gallet
e6595ec6f7 [MIG] project_funders : migrate to 16.0 2023-10-30 09:27:53 +01:00
45e38de4ff [ADD]project_disable_last_sol_as_sol_by_default: do not use last sol as sol by default in a task 2023-09-27 16:27:35 +02:00
1a342d3b8b [IMP] project_assignees:add 'assigned to' filter in tasks kanban view 2023-09-26 12:42:23 +02:00
0bff01ad76 [IMP] Kanban view of project tasks : add create date 2023-09-26 12:42:23 +02:00
cd884b967e [ADD] project_request_data: add service and request type to kanban view 2023-09-26 12:42:23 +02:00
22a703d9bd [ADD]field parent tasks : display only current project's tasks 2023-09-26 12:42:23 +02:00
43 changed files with 233 additions and 307 deletions

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_assignees", "name": "project_assignees",
"version": "14.0.1.0.0", "version": "16.0.1.1.0",
"author": "Elabore", "author": "Elabore",
"website": "https://github.com/elabore-coop/project-tools", "website": "https://github.com/elabore-coop/project-tools",
"maintainer": "Stéphan Sainléger", "maintainer": "Stéphan Sainléger",
@@ -69,6 +69,7 @@ This module is maintained by Elabore.
"depends": [ "depends": [
"base", "base",
"project", "project",
"project_task_portal_form",
], ],
"qweb": [ "qweb": [
# "static/src/xml/*.xml", # "static/src/xml/*.xml",

View File

@@ -4,10 +4,10 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 14.0\n" "Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-26 07:38+0000\n" "POT-Creation-Date: 2023-11-02 07:56+0000\n"
"PO-Revision-Date: 2022-07-26 07:38+0000\n" "PO-Revision-Date: 2023-11-02 07:56+0000\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -16,17 +16,21 @@ msgstr ""
"Plural-Forms: \n" "Plural-Forms: \n"
#. module: project_assignees #. module: project_assignees
#: model_terms:ir.ui.view,arch_db:project_assignees.portal_my_task_timebox #: model_terms:ir.ui.view,arch_db:project_assignees.portal_my_task_assignees
msgid "<strong>Other assignements</strong>" msgid "<strong>Other assignees</strong>"
msgstr "<strong>Autres intervenants</strong>" msgstr "<strong>Autres intervenants</strong>"
#. module: project_assignees #. module: project_assignees
#: model:ir.model.fields,field_description:project_assignees.field_project_task__assignee_ids | #: model:ir.model.fields,field_description:project_assignees.field_project_task__assignee_ids
msgid "Assignees" | msgid "Assignees"
msgstr "Autres assignations" msgstr "Autres assignations"
#. module: project_assignees
#: model_terms:ir.ui.view,arch_db:project_assignees.portal_my_task_assignees
msgid "Contact"
msgstr ""
#. module: project_assignees #. module: project_assignees
#: model:ir.model,name:project_assignees.model_project_task #: model:ir.model,name:project_assignees.model_project_task
msgid "Task" msgid "Task"
msgstr "Tâche" msgstr "Tâche"

View File

@@ -1,21 +1,20 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<template id="portal_my_task_assignees" name="My Task: Assignees" inherit_id="project.portal_my_task" priority="40"> <template id="portal_my_task_assignees" name="My Task: Assignees" inherit_id="project.portal_my_task" priority="40">
<xpath expr="//div[hasclass('flex-grow-0')]/../../.." position="inside"> <xpath expr="//t[@t-foreach='task.user_ids']" position="after">
<div class="col-12 col-md-6 pb-2" t-if="task.assignee_ids"> <div class="col-12 col-md-12 pb-2" t-if="task.assignee_ids">
<strong>Other assignees</strong> <strong>Other assignees</strong>
<div class="row"> <div class="row">
<t t-foreach="task.assignee_ids" t-as="assignee"> <t t-foreach="task.assignee_ids" t-as="user">
<div class="col flex-grow-0 pr-3"> <div class="d-flex mb-3 flex-nowrap">
<img t-if="assignee.image" class="rounded-circle mt-1 o_portal_contact_img" t-att-src="image_data_uri(assignee.image)" alt="Contact" /> <img class="rounded-circle mt-1 o_portal_contact_img" t-att-src="image_data_uri(user.avatar_1024)" alt="Contact"/>
<img t-else="" class="rounded-circle mt-1 o_portal_contact_img" src="/web/static/src/img/user_menu_avatar.png" alt="Contact" /> <div class="ms-2">
</div> <div t-esc="user" t-options='{"widget": "contact", "fields": ["name"]}'/>
<div class="col pl-md-0"> <a t-attf-href="tel:{{user.phone}}" t-if="user.phone"><div t-esc="user" t-options='{"widget": "contact", "fields": ["phone"]}'/></a>
<strong> <a t-if="user.email" class="text-break" t-attf-href="mailto:{{user.email}}">
<span t-field="assignee.name" /> <div t-out="user" t-options='{"widget": "contact", "fields": ["email"]}'/>
</strong> </a>
<span t-field="assignee.email" /> </div>
<span t-field="assignee.phone" />
</div> </div>
</t> </t>
</div> </div>

View File

@@ -6,7 +6,7 @@
<field name="inherit_id" ref="project.view_task_form2" /> <field name="inherit_id" ref="project.view_task_form2" />
<field name="priority" eval="99" /> <field name="priority" eval="99" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='user_id']" position="after"> <xpath expr="//field[@name='user_ids']" position="after">
<field name="assignee_ids" widget="many2many_tags" /> <field name="assignee_ids" widget="many2many_tags" />
</xpath> </xpath>
</field> </field>
@@ -19,8 +19,11 @@
<field name="priority" eval="99" /> <field name="priority" eval="99" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<filter name="my_tasks" position="attributes"> <filter name="my_tasks" position="attributes">
<attribute name="domain">['|', ('user_id', '=', uid), ('assignee_ids', 'in', uid)]</attribute> <attribute name="domain">['|', ('user_ids', 'in', uid), ('assignee_ids', 'in', uid)]</attribute>
</filter> </filter>
<xpath expr="//field[@name='partner_id']" position="after">
<field name="assignee_ids" filter_domain="[('assignee_ids.user_ids.name', 'ilike', self)]"/>
</xpath>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_average_acceptable_time", "name": "project_average_acceptable_time",
"version": "12.0.1.0.0", "version": "16.0.1.0.0",
"author": "Elabore", "author": "Elabore",
"website": "https://github.com/elabore-coop/project-tools", "website": "https://github.com/elabore-coop/project-tools",
"maintainer": "Clément Thomas", "maintainer": "Clément Thomas",

View File

@@ -8,7 +8,7 @@
<field name="inherit_id" ref="project.view_project_kanban"/> <field name="inherit_id" ref="project.view_project_kanban"/>
<field name="priority">999</field> <field name="priority">999</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//div[@class='o_project_kanban_main']" position="inside"> <xpath expr="//div[@class='o_project_kanban_main ']" position="inside">
<div class="o_project_kanban_boxes"> <div class="o_project_kanban_boxes">
<span>Average acceptable time:<![CDATA[&nbsp;]]></span> <span>Average acceptable time:<![CDATA[&nbsp;]]></span>
<field name="average_acceptable_time" widget="float_time"/> <field name="average_acceptable_time" widget="float_time"/>
@@ -23,10 +23,14 @@
<field name="model">project.project</field> <field name="model">project.project</field>
<field name="inherit_id" ref="project.edit_project"/> <field name="inherit_id" ref="project.edit_project"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="subtask_project_id" position="after"> <xpath expr="//div[@id='subtask_settings']/div[@class='o_setting_right_pane']" position="inside">
<label for="average_acceptable_time" /> <div class="o_settings_average_acceptable_time" style="margin-top:10px;">
<field name="average_acceptable_time" widget="float_time"/> <!-- <span>Average acceptable time:<![CDATA[&nbsp;]]></span> -->
</field> <label for="average_acceptable_time"/>
<field name="average_acceptable_time" widget="float_time"/>
</div>
</xpath>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@@ -0,0 +1,43 @@
==========================================
project_disable_last_sol_as_sol_by_default
==========================================
If there is no sale order line in a task, do not add automaticly the last sol of customer as the sale order line by default
Installation
============
Use Odoo normal module installation procedure to install ``project_disable_last_sol_as_sol_by_default``.
Known issues / Roadmap
======================
None yet.
Bug Tracker
===========
Bugs are tracked on `our issues website <https://github.com/elabore-coop/project-tools/issues>`_. In case of
trouble, please check there if your issue has already been
reported. If you spotted it first, help us smashing it by providing a
detailed and welcomed feedback.
Credits
=======
Contributors
------------
* Laetitia Da Costa (https://github.com/LaetitiaElabore)
Funders
-------
The development of this module has been financially supported by:
* Elabore (https://elabore.coop)
Maintainer
----------
This module is maintained by Elabore.

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,37 @@
# Copyright 2022 Stéphan Sainléger (Elabore)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "project_disable_last_sol_as_sol_by_default",
"version": "14.0.1.0.0",
"author": "Elabore",
"website": "https://elabore.coop",
"maintainer": "Laetitia Da Costa",
"license": "AGPL-3",
"category": "Project",
"summary": "Do not add last sale order line automaticly as the sale order line by default in a task",
# any module necessary for this one to work correctly
"depends": [
"base",
"project",
"sale_timesheet"
],
"qweb": [
# "static/src/xml/*.xml",
],
"external_dependencies": {
"python": [],
},
# always loaded
"data": [
],
# only loaded in demonstration mode
"demo": [],
"js": [],
"css": [],
"installable": True,
# Install this module automatically if all dependency have been previously
# and independently installed. Used for synergetic or glue modules.
"auto_install": False,
"application": False,
}

View File

@@ -0,0 +1 @@
from . import project_task

View File

@@ -0,0 +1,7 @@
from odoo import models
class Task(models.Model):
_inherit = "project.task"
def _get_last_sol_of_customer(self):
return False

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_funders", "name": "project_funders",
"version": "14.0.1.0.0", "version": "16.0.1.0.0",
"author": "Alusage", "author": "Alusage",
"website": "https://alusage.fr", "website": "https://alusage.fr",
"data": [ "data": [

View File

@@ -1,3 +1,2 @@
# -*- coding: utf-8 -*-
from . import models from . import models

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_link_from_invoice", "name": "project_link_from_invoice",
"version": "14.0.0.0.0", "version": "16.0.1.0.0",
"author": "Elabore", "author": "Elabore",
"website": "https://github.com/elabore-coop/project-tools", "website": "https://github.com/elabore-coop/project-tools",
"maintainer": "Clément Thomas", "maintainer": "Clément Thomas",

View File

@@ -1,3 +1,2 @@
# -*- coding: utf-8 -*-
from . import account_move from . import account_move

View File

@@ -1,3 +1,2 @@
# -*- coding: utf-8 -*-
from . import models from . import models

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_name_from_lead", "name": "project_name_from_lead",
"version": "14.0.1.0.0", "version": "16.0.1.0.0",
"author": "Elabore", "author": "Elabore",
"website": "https://elabore.coop", "website": "https://elabore.coop",
"maintainer": "Clément Thomas", "maintainer": "Clément Thomas",
@@ -13,6 +13,7 @@
# any module necessary for this one to work correctly # any module necessary for this one to work correctly
"depends": [ "depends": [
"base", "base",
"crm",
"sale_project", "sale_project",
], ],
"qweb": [ "qweb": [

View File

@@ -1,3 +1,2 @@
# -*- coding: utf-8 -*-
from . import models from . import models

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_name_from_quote", "name": "project_name_from_quote",
"version": "14.0.1.0.0", "version": "16.0.1.0.0",
"author": "Elabore", "author": "Elabore",
"website": "https://elabore.coop", "website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger", "maintainer": "Stéphan Sainléger",

View File

View File

@@ -1,70 +1,68 @@
# Copyright 2022 Stéphan Sainléger (Elabore) # Copyright 2022 Laetitia Da Costa (Elabore)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
"name": "project_timesheet_funding_wish", "name": "project_parent_tasks",
"version": "14.0.1.0.0", "version": "14.0.1.0.0",
"author": "Elabore", "author": "Elabore",
"website": "https://github.com/elabore-coop/project-tools", "website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger", "maintainer": "Laetitia Da Costa",
"license": "AGPL-3", "license": "AGPL-3",
"category": "Tools", "category": "Project",
"summary": "Add a funding wish select field to timesheet line.", "summary": "in parent's tasks dropdown field, show only tasks from the current projet",
"description": """ "description": """
:image: https://img.shields.io/badge/licence-AGPL--3-blue.svg :image: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3 :alt: License: AGPL-3
============================== ====================
project_timesheet_funding_wish project_parent_tasks
============================== ====================
Add a funding wish select field to timesheet line. when selecting a parent task in a task, display only tasks from the current project
Installation Installation
============ ============
Use Odoo normal procedure to install add-ons to install Use Odoo normal module installation procedure to install ``project_parent_tasks``.
``project_timesheet_funding_wish``.
Known issues / Roadmap Known issues / Roadmap
====================== ======================
None yet.
Bug Tracker Bug Tracker
=========== ===========
Bugs are tracked on `our issues website <https://github.com/elabore-coop/project-tools/issues>`_. In Bugs are tracked on `our issues website <https://github.com/elabore-coop/project-tools/issues>`_. In case of
case of trouble, please check there if your issue has already been trouble, please check there if your issue has already been
reported. If you spotted it first, help us smashing it by providing a reported. If you spotted it first, help us smashing it by providing a
detailed and welcomed feedback. detailed and welcomed feedback.
Credits Credits
======= =======
Images
------
* Elabore: `Icon <https://elabore.coop/web/image/res.company/1/logo?unique=f3db262>`_.
Contributors Contributors
------------ ------------
* Stéphan Sainléger <https://github.com/stephansainleger>
* Valentin Lab <valentin.lab@kalysto.org> * Laetitia Da Costa (https://github.com/LaetitiaElabore)
* Nicolas Jeudy <https://github.com/njeudy>
Funders Funders
------- -------
The development of this module has been financially supported by: The development of this module has been financially supported by:
* Elabore (https://elabore.coop) * Elabore (https://elabore.coop)
Maintainer Maintainer
---------- ----------
This module is maintained by Elabore. This module is maintained by Elabore.
""", """,
# any module necessary for this one to work correctly # any module necessary for this one to work correctly
"depends": [ "depends": [
"base", "base",
"hr_timesheet", "project",
], ],
"qweb": [ "qweb": [
# "static/src/xml/*.xml", # "static/src/xml/*.xml",
@@ -74,7 +72,7 @@ This module is maintained by Elabore.
}, },
# always loaded # always loaded
"data": [ "data": [
"views/hr_timesheet.xml", "views/project_task.xml",
], ],
# only loaded in demonstration mode # only loaded in demonstration mode
"demo": [], "demo": [],
@@ -85,4 +83,4 @@ This module is maintained by Elabore.
# and independently installed. Used for synergetic or glue modules. # and independently installed. Used for synergetic or glue modules.
"auto_install": False, "auto_install": False,
"application": False, "application": False,
} }

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record model="ir.ui.view" id="view_tasks_form2_parent_project_inherited">
<field name="name">view.tasks.form2.parent.project.inherited</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="project.view_task_form2" />
<field name="arch" type="xml">
<xpath expr="//page[@name='extra_info']//field[@name='parent_id']" position="attributes">
<attribute name="domain">[('project_id','=', project_id)]</attribute>
</xpath>
</field>
</record>
</odoo>

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_request_data", "name": "project_request_data",
"version": "14.0.1.0.0", "version": "16.0.1.2.0",
"author": "Elabore", "author": "Elabore",
"website": "https://elabore.coop", "website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger", "maintainer": "Stéphan Sainléger",

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<template id="portal_my_task_request_data" name="My Task: Request Data" inherit_id="project.portal_my_task" priority="40"> <template id="portal_my_task_request_data" name="My Task: Request Data" inherit_id="project.portal_my_task" priority="40">
<xpath expr="//t[@t-set='card_body']/div[hasclass('row','mb-4')]" position="after"> <xpath expr="//div[@id='card_body']/div[hasclass('row','mb-4','container')]" position="after">
<div id="request_data" class="row mb-4"> <div id="request_data" class="row mb-4">
<div class="col-12 col-md-6" t-if="task.service_id"> <div class="col-12 col-md-6" t-if="task.service_id">
<strong>Service:</strong> <strong>Service:</strong>

View File

@@ -12,4 +12,18 @@
</xpath> </xpath>
</field> </field>
</record> </record>
<record id="view_task_kanban_request_data" model="ir.ui.view">
<field name="name">project.task.kanban.request.data</field>
<field name="inherit_id" ref="project.view_task_kanban" />
<field name="model">project.task</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="before">
<div style="font-size:11px; margin-bottom: 8px;"><field name="create_date" widget="date"/></div>
</xpath>
<xpath expr="//field[@name='tag_ids']" position="before">
<span style="background:lightblue; font-size:11px"><field name="service_id"/></span>
<span style="background:lightsteelblue; font-size:11px"><field name="request_type_id"/></span>
</xpath>
</field>
</record>
</odoo> </odoo>

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_task_portal_form", "name": "project_task_portal_form",
"version": "14.0.1.1.0", "version": "16.0.1.1.0",
"author": "Elabore", "author": "Elabore",
"website": "https://elabore.coop", "website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger", "maintainer": "Stéphan Sainléger",

View File

@@ -51,7 +51,7 @@ class PortalTaskCreation(CustomerPortal):
website=True, website=True,
) )
def portal_task_creation(self, access_token=None, redirect=None, **kw): def portal_task_creation(self, access_token=None, redirect=None, **kw):
values = self._task_get_page_view_values(request.env.user.partner_id, access_token, **kw) values = self._taskform_get_page_view_values(request.env.user.partner_id, access_token, **kw)
request_types = request.env["request.type"].sudo().search([]) request_types = request.env["request.type"].sudo().search([])
task_services = request.env["task.service"].sudo().search([]) task_services = request.env["task.service"].sudo().search([])
priorities = self._get_task_priorities() priorities = self._get_task_priorities()
@@ -105,7 +105,9 @@ class PortalTaskCreation(CustomerPortal):
values = self._compute_form_data(kwargs) values = self._compute_form_data(kwargs)
values["project_id"] = user.default_project_id.id values["project_id"] = user.default_project_id.id
values["partner_id"] = user.partner_id.id values["partner_id"] = user.partner_id.id
values["user_id"] = user.id values["user_ids"] = [(6, 0, [user.id])]
files = values.get("attachments", False) files = values.get("attachments", False)
del values['attachments'] del values['attachments']

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_timebox", "name": "project_timebox",
"version": "14.0.1.0.0", "version": "16.0.1.0.0",
"author": "Elabore", "author": "Elabore",
"website": "https://elabore.coop", "website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger", "maintainer": "Stéphan Sainléger",

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<template id="portal_my_task_timebox" name="My Task: Timebox" inherit_id="project.portal_my_task" priority="40"> <template id="portal_my_task_timebox" name="My Task: Timebox" inherit_id="project.portal_my_task" priority="40">
<xpath expr="//t[@t-set='card_body']/div[hasclass('row','mb-4')]" position="before"> <xpath expr="//div[@t-if='task.date_deadline']" position="after">
<div id="timebox" class="row mb-2"> <div id="timebox" class="row mb-2">
<div class="col-12 col-md-6" t-if="task.timebox_min_id"> <div t-if="task.timebox_min_id">
<strong>Timebox Min:</strong> <strong>Timebox Min:</strong>
<span t-field="task.timebox_min_id" /> <span t-field="task.timebox_min_id" />
</div> </div>
<div class="col-12 col-md-6" t-if="task.timebox_max_id"> <div t-if="task.timebox_max_id">
<strong>Timebox Max:</strong> <strong>Timebox Max:</strong>
<span t-field="task.timebox_max_id" /> <span t-field="task.timebox_max_id" />
</div> </div>

View File

@@ -1,47 +0,0 @@
==============================
project_timesheet_funding_wish
==============================
Add a funding wish select field to timesheet line.
Installation
============
Use Odoo normal procedure to install add-ons to install
``project_timesheet_funding_wish``.
Known issues / Roadmap
======================
Bug Tracker
===========
Bugs are tracked on `our issues website <https://github.com/elabore-coop/project-tools/issues>`_. In
case of trouble, please check there if your issue has already been
reported. If you spotted it first, help us smashing it by providing a
detailed and welcomed feedback.
Credits
=======
Images
------
* Elabore: `Icon <https://elabore.coop/web/image/res.company/1/logo?unique=f3db262>`_.
Contributors
------------
* Stéphan Sainléger <https://github.com/stephansainleger>
* Valentin Lab <valentin.lab@kalysto.org>
* Nicolas Jeudy <https://github.com/njeudy>
Funders
-------
The development of this module has been financially supported by:
* Elabore (https://elabore.coop)
Maintainer
----------
This module is maintained by Elabore.

View File

@@ -1 +0,0 @@
from . import models

View File

@@ -1 +0,0 @@
This directory should contain the *.po for Odoo translation.

View File

@@ -1,65 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * project_timesheet_funding_wish
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-25 17:02+0000\n"
"PO-Revision-Date: 2022-07-25 17:02+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: project_timesheet_funding_wish
#: model:ir.model,name:project_timesheet_funding_wish.model_account_analytic_line
msgid "Analytic Line"
msgstr "Ligne analytique"
#. module: project_timesheet_funding_wish
#: model:ir.model.fields,field_description:project_timesheet_funding_wish.field_account_analytic_line__display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: project_timesheet_funding_wish
#: model:ir.model.fields.selection,name:project_timesheet_funding_wish.selection__account_analytic_line__funding_wish__free
msgid "Free"
msgstr "Offert"
#. module: project_timesheet_funding_wish
#: code:addons/project_timesheet_funding_wish/models/hr_timesheet.py:0
#: model:ir.model.fields,field_description:project_timesheet_funding_wish.field_account_analytic_line__funding_wish
#, python-format
msgid "Funding wish"
msgstr "Type de financement"
#. module: project_timesheet_funding_wish
#: model:ir.model.fields,field_description:project_timesheet_funding_wish.field_account_analytic_line__id
msgid "ID"
msgstr ""
#. module: project_timesheet_funding_wish
#: model:ir.model.fields,field_description:project_timesheet_funding_wish.field_account_analytic_line____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: project_timesheet_funding_wish
#: model:ir.model.fields.selection,name:project_timesheet_funding_wish.selection__account_analytic_line__funding_wish__accepted
msgid "Payment accepted"
msgstr "Paiement accepté"
#. module: project_timesheet_funding_wish
#: model:ir.model.fields.selection,name:project_timesheet_funding_wish.selection__account_analytic_line__funding_wish__expected
msgid "Payment expected"
msgstr "Paiement attendu"
#. module: project_timesheet_funding_wish
#: code:addons/project_timesheet_funding_wish/models/hr_timesheet.py:0
#: model:ir.model.fields,field_description:project_timesheet_funding_wish.field_account_analytic_line__treated
#, python-format
msgid "Treated"
msgstr "Traité"

View File

@@ -1 +0,0 @@
from . import hr_timesheet

View File

@@ -1,16 +0,0 @@
from odoo import _, fields, models
class AccountAnalyticLine(models.Model):
_inherit = "account.analytic.line"
funding_wish = fields.Selection(
[
("free", "Free"),
("accepted", "Payment accepted"),
("expected", "Payment expected"),
],
string=_("Funding wish"),
copy=False,
)
treated = fields.Boolean(string=_("Treated"), copy=False)

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="hr_timesheet_line_tree_funding_view" model="ir.ui.view">
<field name="name">hr.timesheet.line.tree.funding.view</field>
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_tree" />
<field name="arch" type="xml">
<xpath expr="//field[@name='date']" position="after">
<field name="treated" />
<field name="funding_wish" />
</xpath>
</field>
</record>
<record id="view_task_form2_inherited_funding" model="ir.ui.view">
<field name="name">view.task.form2.inherited.funding</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="hr_timesheet.view_task_form2_inherited" />
<field name="arch" type="xml">
<xpath expr="//field[@name='timesheet_ids']/tree/field[@name='date']" position="after">
<field name="treated" />
<field name="funding_wish" />
</xpath>
</field>
</record>
</odoo>

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_user_default_project", "name": "project_user_default_project",
"version": "14.0.1.0.0", "version": "16.0.1.0.0",
"author": "Elabore", "author": "Elabore",
"website": "https://elabore.coop", "website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger", "maintainer": "Stéphan Sainléger",

View File

@@ -1,3 +1,2 @@
# -*- coding: utf-8 -*-
from . import models from . import models

View File

@@ -3,7 +3,7 @@
{ {
"name": "project_visibility_followers_portal", "name": "project_visibility_followers_portal",
"version": "14.0.1.0.0", "version": "16.0.1.0.0",
"author": "Elabore", "author": "Elabore",
"website": "https://github.com/elabore-coop/project-tools", "website": "https://github.com/elabore-coop/project-tools",
"maintainer": "Clément Thomas", "maintainer": "Clément Thomas",
@@ -77,7 +77,6 @@ This module is maintained by Elabore.
}, },
# always loaded # always loaded
"data": [ "data": [
"views/project_views.xml",
"security/project_security.xml" "security/project_security.xml"
], ],
# only loaded in demonstration mode # only loaded in demonstration mode

View File

@@ -5,6 +5,7 @@ from odoo import models, fields, api
class Project(models.Model): class Project(models.Model):
_inherit = "project.project" _inherit = "project.project"
# A reprendre pour ajouter loption de visibilité
privacy_visibility = fields.Selection( privacy_visibility = fields.Selection(
selection_add=[('followers_portal','Invited portal users and invited internal users')], selection_add=[('followers_portal','Invited portal users and invited internal users')],
ondelete={'followers_portal': 'set default'}) ondelete={'followers_portal': 'set default'})
@@ -16,7 +17,7 @@ class Project(models.Model):
""" """
project = super(Project, self).create(vals) project = super(Project, self).create(vals)
if project.privacy_visibility == 'followers_portal' and project.partner_id.user_ids: if project.privacy_visibility == 'followers_portal' and project.partner_id.user_ids:
project.allowed_user_ids |= project.partner_id.user_ids project.message_partner_ids |= project.partner_id
return project return project
def write(self, vals): def write(self, vals):
@@ -26,5 +27,6 @@ class Project(models.Model):
res = super(Project, self).write(vals) res = super(Project, self).write(vals)
if vals.get('partner_id') or vals.get('privacy_visibility'): if vals.get('partner_id') or vals.get('privacy_visibility'):
for project in self.filtered(lambda project: project.privacy_visibility == 'followers_portal'): for project in self.filtered(lambda project: project.privacy_visibility == 'followers_portal'):
project.allowed_user_ids |= project.partner_id.user_ids project.message_partner_ids |= project.partner_id
return res return res

View File

@@ -6,49 +6,20 @@ from odoo.exceptions import ValidationError
class Task(models.Model): class Task(models.Model):
_inherit = "project.task" _inherit = "project.task"
@api.constrains('allowed_user_ids') @api.constrains('message_partner_ids')
def _check_no_portal_allowed(self): def _check_no_portal_allowed(self):
for task in self.filtered(lambda t: t.project_id.privacy_visibility not in ('portal','followers_portal')): for task in self.filtered(lambda t: t.project_id.privacy_visibility not in ('portal','followers_portal')):
portal_users = task.allowed_user_ids.filtered('share') portal_users = task.message_partner_ids.user_ids.filtered('share')
if portal_users: if portal_users:
user_names = ', '.join(portal_users[:10].mapped('name')) user_names = ', '.join(portal_users[:10].mapped('name'))
raise ValidationError(_("The project visibility setting doesn't allow portal users to see the project's tasks. (%s)", user_names)) raise ValidationError(_("The project visibility setting doesn't allow portal users to see the project's tasks. (%s)", user_names))
@api.depends('project_id.allowed_user_ids', 'project_id.privacy_visibility')
def _compute_allowed_user_ids(self):
for task in self.with_context(prefetch_fields=False):
portal_users = task.allowed_user_ids.filtered('share')
internal_users = task.allowed_user_ids - portal_users
if task.project_id.privacy_visibility == 'followers':
task.allowed_user_ids |= task.project_id.allowed_internal_user_ids
task.allowed_user_ids -= portal_users
elif task.project_id.privacy_visibility == 'portal':
task.allowed_user_ids |= task.project_id.allowed_portal_user_ids
elif task.project_id.privacy_visibility == 'followers_portal':
task.allowed_user_ids |= task.project_id.allowed_internal_user_ids
task.allowed_user_ids |= task.project_id.allowed_portal_user_ids
if task.project_id.privacy_visibility not in ('portal','followers_portal'):
task.allowed_user_ids -= portal_users
elif task.project_id.privacy_visibility not in ('followers','followers_portal'):
task.allowed_user_ids -= internal_users
def _compute_access_warning(self): def _compute_access_warning(self):
for task in self.filtered(lambda x: x.project_id.privacy_visibility not in ('portal','followers_portal')): for task in self.filtered(lambda x: x.project_id.privacy_visibility not in ('portal','followers_portal')):
task.access_warning = _( task.access_warning = _(
"The task cannot be shared with the recipient(s) because the privacy of the project is too restricted. Set the privacy of the project to 'Visible by following customers' in order to make it accessible by the recipient(s).") "The task cannot be shared with the recipient(s) because the privacy of the project is too restricted. Set the privacy of the project to 'Visible by following customers' in order to make it accessible by the recipient(s).")
def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None):
"""
Add the users subscribed to allowed portal users
"""
res = super(Task, self).message_subscribe(partner_ids=partner_ids, channel_ids=channel_ids, subtype_ids=subtype_ids)
if partner_ids:
new_allowed_users = self.env['res.partner'].browse(partner_ids).user_ids.filtered('share')
tasks = self.filtered(lambda task: task.project_id.privacy_visibility == 'followers_portal')
tasks.sudo().allowed_user_ids |= new_allowed_users
return res
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):
@@ -71,18 +42,18 @@ class Task(models.Model):
group_func = lambda pdata: pdata['type'] == 'user' and project_user_group_id in pdata['groups'] group_func = lambda pdata: pdata['type'] == 'user' and project_user_group_id in pdata['groups']
if self.project_id.privacy_visibility == 'followers_portal': if self.project_id.privacy_visibility == 'followers_portal':
allowed_user_ids = self.project_id.allowed_internal_user_ids.partner_id.ids message_partner_ids = self.project_id.message_partner_ids.partner_id.ids
group_func = lambda pdata:\ group_func = lambda pdata:\
pdata['type'] == 'user'\ pdata['type'] == 'user'\
and ( and (
project_manager_group_id in pdata['groups']\ project_manager_group_id in pdata['groups']\
or (project_user_group_id in pdata['groups'] and pdata['id'] in allowed_user_ids) or (project_user_group_id in pdata['groups'] and pdata['id'] in message_partner_ids)
) )
groups = [('group_project_user', group_func, {})]+groups groups = [('group_project_user', group_func, {})]+groups
allowed_user_ids = self.project_id.allowed_portal_user_ids.partner_id.ids message_partner_ids = self.project_id.message_partner_ids
groups.insert(0, ( groups.insert(0, (
'allowed_portal_users', 'message_partner_ids',
lambda pdata: pdata['type'] == 'portal' and pdata['id'] in allowed_user_ids, lambda pdata: pdata['type'] == 'portal' and pdata['id'] in message_partner_ids,
{} {}
)) ))

View File

@@ -8,8 +8,7 @@
<field name="model_id" ref="model_project_project"/> <field name="model_id" ref="model_project_project"/>
<field name="domain_force">[ <field name="domain_force">[
('privacy_visibility', '=', 'followers_portal'), ('privacy_visibility', '=', 'followers_portal'),
'|', ('allowed_portal_user_ids', 'in', user.ids), ('message_partner_ids', 'in', [user.partner_id.id])
('allowed_internal_user_ids', 'in', user.ids),
]</field> ]</field>
<field name="groups" eval="[(4, ref('base.group_user')),(4, ref('base.group_portal'))]"/> <field name="groups" eval="[(4, ref('base.group_user')),(4, ref('base.group_portal'))]"/>
</record> </record>
@@ -19,36 +18,46 @@
<field name="model_id" ref="model_project_task"/> <field name="model_id" ref="model_project_task"/>
<field name="domain_force">[ <field name="domain_force">[
('project_id.privacy_visibility', '=', 'followers_portal'), ('project_id.privacy_visibility', '=', 'followers_portal'),
('allowed_user_ids', 'in', user.ids), '|',
('project_id.message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
]</field> ]</field>
<field name="groups" eval="[(4, ref('base.group_user')),(4, ref('base.group_portal'))]"/> <field name="groups" eval="[(4, ref('base.group_user')),(4, ref('base.group_portal'))]"/>
</record> </record>
<!-- change existing rule --> <!-- extend existing rule -->
<record model="ir.rule" id="project.project_public_members_rule"> <record model="ir.rule" id="project.project_public_members_rule">
<field name="domain_force">[ <field name="domain_force">[
'|', '|',
('privacy_visibility', '!=', 'followers_portal'), ('privacy_visibility', '!=', 'followers_portal'),
('allowed_internal_user_ids', 'in', user.ids), ('message_partner_ids', 'in', [user.partner_id.id]),
'|', '|',
('privacy_visibility', '!=', 'followers'), ('privacy_visibility', '!=', 'followers'),
('allowed_internal_user_ids', 'in', user.ids), ('message_partner_ids', 'in', [user.partner_id.id])
]</field> ]</field>
</record> </record>
<record model="ir.rule" id="project.task_visibility_rule"> <record model="ir.rule" id="project.task_visibility_rule">
<field name="domain_force">[ <field name="domain_force">[
'|', '|',
('project_id.privacy_visibility', '!=', 'followers_portal'), '&amp;',
('allowed_user_ids', 'in', user.ids), ('project_id', '!=', False),
'|', (
('project_id.privacy_visibility', '!=', 'followers'), '|',
('allowed_user_ids', 'in', user.ids), ('project_id.privacy_visibility', '!=', 'followers_portal'),
('project_id.message_partner_ids', 'in', [user.partner_id.id]),
'|',
('project_id.privacy_visibility', '!=', 'followers'),
('project_id.message_partner_ids', 'in', [user.partner_id.id]),
),
'|',
('message_partner_ids', 'in', [user.partner_id.id]),
# to subscribe check access to the record, follower is not enough at creation
('user_ids', 'in', user.id)
]</field> ]</field>
<field name="groups" eval="[(4,ref('base.group_user'))]"/> <field name="groups" eval="[(4,ref('base.group_user'))]"/>
</record> </record>
</data> </data>
</odoo> </odoo>

View File

@@ -1,20 +0,0 @@
<!-- todo: remove the date_start and date_end from the Extra Info Tab -->
<odoo>
<data>
<record id="view_project_form_visibility_followers_portal" model="ir.ui.view">
<field name="name">project.form.visibility.followers.portal</field>
<field name="model">project.project</field>
<field name="inherit_id" ref="project.edit_project"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='allowed_internal_user_ids']" position="attributes">
<attribute name="attrs">{'invisible': [('privacy_visibility', '!=', 'followers'),('privacy_visibility', '!=', 'followers_portal')]}</attribute>
</xpath>
<xpath expr="//field[@name='allowed_portal_user_ids']" position="attributes">
<attribute name="attrs">{'invisible': [('privacy_visibility', '!=', 'portal'),('privacy_visibility', '!=', 'followers_portal')]}</attribute>
</xpath>
</field>
</record>
</data>
</odoo>