Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions project_fte/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
===========
Project FTE
===========

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:a7f1bc48b07ef5a995fd3ac2b703dd2fd5451fd0dbd60fc515b77b46180357b3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fproject-lightgray.png?logo=github
:target: https://github.com/OCA/project/tree/17.0/project_fte
:alt: OCA/project
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/project-17-0/project-17-0-project_fte
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/project&target_branch=17.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

With this module you can manage FTE (Full-Time Equivalent) contracts and
evolution in projects.

**Table of contents**

.. contents::
:local:

Usage
=====

1. **Go to the desired project**, click the three dots (⋯) in the
top-right corner, and select **Settings**.
2. A new section named **FTE** will appear in the project form.
3. Click the **Generate FTE Lines** button to open the wizard.

🔧 In the wizard:
~~~~~~~~~~~~~~~~~

- Select the **Start Date**. This date will be stored on the project.
- **total FTE hours** will be calculated from the total of the
allocated_hours of the tasks.
- Fill in the **Monthly Hours** manually. These represent the typical
number of hours to distribute per month, and are used to calculate
the duration.
- Define the **Profile Distribution** by selecting the roles and
specifying the number of hours per role.

..

💡 If your roles have a **Price per Hour** defined (on the role
itself), the wizard will use it to compute the cost of each role’s
hours.

- The wizard will automatically compute:

- The **percentage** of each role's hours,
- The **Monthly Amount** and **Total Amount**,
- The **End Date**, based on the total hours and monthly
distribution.

--------------

🎯 Autofill from Milestones
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Instead of filling the profile distribution manually, you can click
**Load from Milestones**:

- This will gather all project tasks linked to milestones,
- And group their allocated hours by the **role assigned to each
milestone**,
- Creating a profile distribution automatically.

This is useful when project planning has already been done using
milestones.

--------------

📆 Generating the Lines
~~~~~~~~~~~~~~~~~~~~~~~

Once all fields are filled:

1. Click **Generate**.
2. FTE lines will be created month by month from the selected Start Date
to the computed End Date.
3. The hours and costs are distributed according to the profile
distribution.

--------------

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/project/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/project/issues/new?body=module:%20project_fte%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* APSL Nagarro

Contributors
------------

- ``APSL-Nagarro <https://apsl.tech>``\ \_:

- Miquel Alzanillas [email protected]
- Miquel Pascual [email protected]
- Bernat Obrador [email protected]

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

.. |maintainer-miquelalzanillas| image:: https://github.com/miquelalzanillas.png?size=40px
:target: https://github.com/miquelalzanillas
:alt: miquelalzanillas
.. |maintainer-mpascuall| image:: https://github.com/mpascuall.png?size=40px
:target: https://github.com/mpascuall
:alt: mpascuall

Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-miquelalzanillas| |maintainer-mpascuall|

This module is part of the `OCA/project <https://github.com/OCA/project/tree/17.0/project_fte>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
2 changes: 2 additions & 0 deletions project_fte/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizard
31 changes: 31 additions & 0 deletions project_fte/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright 2025 APSL Nagarro
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Project FTE",
"summary": "Manage FTE (Full-Time Equivalent) contracts and evolution in projects.",
"version": "17.0.1.0.0",
"category": "Project",
"website": "https://github.com/OCA/project",
"author": "APSL Nagarro, Odoo Community Association (OCA)",
"maintainers": ["miquelalzanillas", "mpascuall"],
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"project",
"project_role",
"hr_timesheet",
"hr_timesheet_type_non_billable",
],
"data": [
"security/ir.model.access.csv",
"data/templates/mail_template.xml",
"data/ir_cron.xml",
"wizard/project_fte_mass_generator_views.xml",
"views/project_fte_month_line_views.xml",
"views/project_project_views.xml",
"views/project_role.xml",
"views/project_milestone.xml",
],
}
12 changes: 12 additions & 0 deletions project_fte/data/ir_cron.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<odoo>
<record id="ir_cron_check_fte_execution" model="ir.cron">
<field name="name">FTE Execution Monitoring</field>
<field name="model_id" ref="project_fte.model_project_fte_month_line" />
<field name="state">code</field>
<field name="code">model._cron_check_fte_execution()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="active" eval="True" />
</record>
</odoo>
96 changes: 96 additions & 0 deletions project_fte/data/templates/mail_template.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">

<!-- Template: FTE Execution Warning -->
<record id="mail_template_fte_execution_warning" model="mail.template">
<field name="name">FTE Execution Warning</field>
<field name="model_id" ref="project_fte.model_project_fte_month_line" />
<field name="subject">⚠ FTE Execution Alert: {{object.project_id.name}}</field>
<field name="email_from">{{object.project_id.company_id.email or ''}}</field>
<field name="email_to">{{object.project_id.user_id.email}}</field>
<field name="lang">{{object.project_id.user_id.lang}}</field>
<field name="body_html">
<![CDATA[
<t t-set="project_id" t-value="object.project_id.id"/>
<div style="font-family: Arial, sans-serif; background-color: #f5f6fa; padding: 40px 20px;">
<div style="max-width: 600px; margin: auto; background: #ffffff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">

<h2 style="color: #dc3545;">⚠ Low FTE Execution</h2>

<p style="font-size: 15px; color: #333333;">Dear <strong><t t-out="object.project_id.user_id.name or 'User'"/></strong>,</p>

<p style="font-size: 15px; color: #333;">
The FTE execution for project <strong><t t-out="object.project_id.name"/></strong>
in <strong><t t-out="object.month"/>/<t t-out="object.year"/></strong> is:
</p>

<ul style="font-size: 15px; color: #333; padding-left: 20px; margin: 0 0 10px 0;">
<li><strong><t t-out="round(object.fte_hours, 2)"/></strong> expected hours</li>
<li><strong><t t-out="round(object.executed_hours, 2)"/></strong> hours executed</li>
<li><strong><t t-out="round(object.executed_percent)"/>%</strong> of execution</li>
</ul>

<p style="font-size: 15px;">This is below the expected progress. Please review the execution and make sure timesheets are properly filled in.</p>

<div style="margin: 30px 0; text-align: center;">
<a t-att-href="'/web#id=%s&model=project.project&view_type=form' % project_id"
style="background-color: #007BFF; color: white; padding: 12px 25px; text-decoration: none; border-radius: 6px; display: inline-block;">
🔍 View Project
</a>
</div>

<p style="font-size: 14px; color: #666;">Best regards,<br/>Odoo System</p>
</div>
</div>
]]>
</field>
<field name="auto_delete" eval="True" />
</record>

<!-- Template: FTE Execution Overload Warning -->
<record id="mail_template_fte_execution_overload" model="mail.template">
<field name="name">FTE Execution Overload Warning</field>
<field name="model_id" ref="project_fte.model_project_fte_month_line" />
<field name="subject">⚠ Excess FTE Execution: {{object.project_id.name}}</field>
<field name="email_from">{{object.project_id.company_id.email or ''}}</field>
<field name="email_to">{{object.project_id.user_id.email}}</field>
<field name="lang">{{object.project_id.user_id.lang}}</field>
<field name="body_html">
<![CDATA[
<t t-set="project_id" t-value="object.project_id.id"/>
<div style="font-family: Arial, sans-serif; background-color: #f5f6fa; padding: 40px 20px;">
<div style="max-width: 600px; margin: auto; background: #ffffff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">

<h2 style="color: #c82333;">⚠ Excessive FTE Execution</h2>

<p style="font-size: 15px; color: #333333;">Dear <strong><t t-out="object.project_id.user_id.name or 'User'"/></strong>,</p>

<p style="font-size: 15px; color: #333;">
The FTE execution for project <strong><t t-out="object.project_id.name"/></strong>
in <strong><t t-out="object.month"/>/<t t-out="object.year"/></strong> is:
</p>

<ul style="font-size: 15px; color: #333; padding-left: 20px; margin: 0 0 10px 0;">
<li><strong><t t-out="round(object.fte_hours, 2)"/></strong> expected hours</li>
<li><strong><t t-out="round(object.executed_hours, 2)"/></strong> hours executed</li>
<li><strong><t t-out="round(object.executed_percent)"/>%</strong> of execution</li>
</ul>

<p style="font-size: 15px;">This exceeds the expected progress. Please review the timesheets to confirm accurate reporting.</p>

<div style="margin: 30px 0; text-align: center;">
<a t-att-href="'/web#id=%s&model=project.project&view_type=form' % project_id"
style="background-color: #007BFF; color: white; padding: 12px 25px; text-decoration: none; border-radius: 6px; display: inline-block;">
🔍 View Project
</a>
</div>

<p style="font-size: 14px; color: #666;">Best regards,<br/>Odoo System</p>
</div>
</div>
]]>
</field>
<field name="auto_delete" eval="True" />
</record>

</odoo>
Loading