diff --git a/__manifest__.py b/__manifest__.py index 84c541455f296f3b95311ece9f25a912a573a76d..9888b78303a168ff27ae70fb54ce787c376b2e7d 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -1,16 +1,25 @@ { 'name': 'Le Filament - Projets', + + 'summary': """ + Projets Le Filament""", + 'version': '10.0.1.0', + 'license': 'AGPL-3', 'description': """ - MODULE PROJET LE FILAMENT - Etend l'application Projet : - - Crée un champ financier sur le projet - - Ajoute le taux horaire - - Calcule le temps max + Module Projet Le Filament + + Hérite du module project Odoo et ajoute : + - le calcul des heures imputées et des coûts sur le projet + - le prévisionnel du projet + - la progressbar dépensé/budget + - le graphe du cash flow projet + - prévisionnel de la trésorerie sur 6 mois """, + 'author': 'LE FILAMENT', - 'category': 'LE FILAMENT', + 'category': 'Project', 'depends': ['hr_timesheet'], 'contributors': [ 'Benjamin Rivier <benjamin@le-filament.com>', diff --git a/models/__init__.py b/models/__init__.py index a2414a159c5b62f2dea848852c637fdf8db01d09..6fbc08ffc22c855d3c37569e9b2205f427a4336b 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- -import lefilament_projets +import project import res_config \ No newline at end of file diff --git a/models/lefilament_projets.py b/models/lefilament_projets.py deleted file mode 100644 index 3d6423a09f2156530a1026acb16b2b7b80bcc0db..0000000000000000000000000000000000000000 --- a/models/lefilament_projets.py +++ /dev/null @@ -1,233 +0,0 @@ -# -*- coding: utf-8 -*- - -from datetime import datetime, date -import time -from odoo import tools -from odoo import models, fields, api, osv - -class FilamentProjet(models.Model): - _name = 'project.project' - _inherit = 'project.project' - - lf_total_budget = fields.Float('Budget Projet',) - lf_heures_budget = fields.Float('Budget Heures', compute='_budget_heures') - lf_tarif_jour = fields.Float('Tarif Jour',) - lf_taux_horaire = fields.Float('Taux Horaire', compute='_taux_horaire') - lf_heures_projet = fields.Float('Allouées (h)', compute='_total_heures') - lf_heures_passees = fields.Float('Heures passées', compute='_total_heures_passees') - lf_heures_restantes = fields.Float('Restant (h)', compute='_total_heures_restantes') - lf_heures_planifiees = fields.Float('Planifiées (h)', compute='_total_heures_planifiees') - lf_couts_annexes = fields.Float('Coûts Annexes', compute='_couts_annexes') - lf_couts_estimes = fields.Float('Coûts Estimés') - lf_commentaire = fields.Text('Commentaires') - lf_delay = fields.Integer('Délai facture', compute='_delay') - lf_total_days = fields.Integer('Durée projet', compute='_total_days') - lf_advance = fields.Float('Cash avancé', compute='_advance') - lf_balance = fields.Float('Balance Actuelle', compute='_balance') - - #################################################### - ### Fields Function ### - #################################################### - - @api.one - def _taux_horaire(self): - lf_heures_jour = self.env['ir.values'].get_default('project.config.settings', 'lf_heures_jour') - self.lf_taux_horaire = self.lf_tarif_jour / lf_heures_jour - - @api.one - def _total_heures_passees(self): - res = 0.0 - project = self.id - ## Calcul heures - self.env.cr.execute("select sum(unit_amount) from account_analytic_line where project_id=%s;", (project, ) ) - heures_passees = self.env.cr.fetchone()[0] - if heures_passees: - self.lf_heures_passees = heures_passees - else: - self.lf_heures_passees = 0.0 - - - @api.one - def _total_heures_planifiees(self): - res = 0.0 - for record in self.task_ids: - res = res + record.planned_hours - self.lf_heures_planifiees = res - - @api.one - def _couts_annexes(self): - account = self.analytic_account_id.id - ############## Calcul couts annexes ################ - self.env.cr.execute("select sum(untaxed_amount) from hr_expense where analytic_account_id=%s;", (account, ) ) - couts_annexes = self.env.cr.fetchone()[0] - if couts_annexes: - self.lf_couts_annexes = couts_annexes - else: - self.lf_couts_annexes = 0.0 - - @api.one - @api.depends('lf_total_budget','lf_couts_annexes') - def _budget_heures(self): - self.lf_heures_budget = self.lf_total_budget - self.lf_couts_estimes - - @api.one - def _total_heures(self): - lf_heures_jour = self.env['ir.values'].get_default('project.config.settings', 'lf_heures_jour') - if (self.lf_tarif_jour != 0.0): - self.lf_heures_projet = (self.lf_heures_budget / self.lf_tarif_jour) * lf_heures_jour - else: - self.lf_heures_projet = 0.0 - - @api.one - def _total_heures_restantes(self): - self.lf_heures_restantes = self.lf_heures_projet - self.lf_heures_passees - - ## Time to first invoice - @api.one - def _delay(self): - account_id = self.analytic_account_id.id - self.env.cr.execute(""" - SELECT date - FROM account_analytic_line - where account_id=%s and amount < 0 order by date limit 1 - ;""", (account_id, ) ) - d_cost = self.env.cr.fetchone() - - self.env.cr.execute(""" - SELECT date - FROM account_analytic_line - where account_id=%s and amount < 0 order by date desc limit 1 - ;""", (account_id, ) ) - d_cost_last = self.env.cr.fetchone() - - self.env.cr.execute(""" - SELECT date - FROM account_analytic_line - where account_id=%s and amount > 0 order by date limit 1 - ;""", (account_id, ) ) - d_invoice = self.env.cr.fetchone() - - if d_cost: - if d_invoice: - self.lf_delay = (datetime.strptime(d_invoice[0], "%Y-%m-%d").date() - datetime.strptime(d_cost[0], "%Y-%m-%d").date()).days - else: - self.lf_delay = (datetime.strptime(d_cost_last[0], "%Y-%m-%d").date() - datetime.strptime(d_cost[0], "%Y-%m-%d").date()).days - else: - self.lf_delay = 0 - - ## Total Days - @api.one - def _total_days(self): - account_id = self.analytic_account_id.id - self.env.cr.execute(""" - SELECT - date(d_last) - date(d_first) as datediff - from - (select date FROM account_analytic_line where account_id=%s order by date limit 1) as d_first, - (select date FROM account_analytic_line where account_id=%s order by date desc limit 1) as d_last - ;""", (account_id, account_id, ) ) - lf_total_days = self._cr.fetchone() - - if lf_total_days: - self.lf_total_days = lf_total_days[0] - else: - self.lf_total_days = 0 - - ## Balance - @api.one - def _balance(self): - account_id = self.analytic_account_id.id - self.env.cr.execute(""" - SELECT sum(amount) as Total - FROM account_analytic_line - WHERE account_id=%s - ;""", (account_id, ) ) - self.lf_balance = self._cr.fetchone()[0] - - - ## Advance cash - @api.one - def _advance(self): - account_id = self.analytic_account_id.id - self.env.cr.execute(""" - SELECT sum(amount) as Total - FROM account_analytic_line - WHERE account_id=%s - and date < (case when - (select date FROM account_analytic_line where account_id=%s and amount > 0 order by date limit 1) IS NOT NULL then - (select date FROM account_analytic_line where account_id=%s and amount > 0 order by date limit 1) else current_date end - );""", (account_id, account_id, account_id, ) ) - self.lf_advance = self._cr.fetchone()[0] - - - #################################################### - ### Actions ### - #################################################### - - def open_project(self): - return { - 'type': 'ir.actions.act_window', - 'name': 'Projet' + self.name, - 'view_mode': 'kanban', - 'res_model': 'project.project', - 'res_id': self.id, - 'views': [(False, 'kanban')], - } - - def open_cash_flow(self): - return { - 'type': 'ir.actions.client', - 'name': 'Cash Flow - ' + self.analytic_account_id.name, - 'tag': 'lefilament_projets.cashFlow', - 'target': 'new', - 'params': { - 'account_id': self.analytic_account_id.id, - 'project_id': self.id, - }, - } - - #################################################### - ### Widget Function ### - #################################################### - - @api.model - def cash_flow(self, account_id, project_id): - account = self.env['account.analytic.account'].search([('id', '=', account_id)]) - project = self.env['project.project'].search([('id', '=', project_id)]) - - ## Analytic account name - nom = account.name - - ## Cash Flow Request - self.env.cr.execute(""" - SELECT date, sum(sum(amount)) over (order by date) as Total, - sum(sum(case when product_uom_id = 5 then amount else 0 end)) over (order by date) as Timesheet, - sum(sum(case when (product_uom_id = 1 or product_uom_id is null) and amount < 0 then amount else 0 end)) over (order by date) as Fournisseurs, - sum(sum(case when product_uom_id = 1 and amount > 0 then amount else 0 end)) over (order by date) as Clients - FROM account_analytic_line - WHERE account_id=%s - group by date; - """, (account_id, ) ) - cash_flow = self._cr.dictfetchall() - - ## Time to first invoice - delay = project.lf_delay - - ## Total Days - total_days = project.lf_total_days - - ## Balance - balance = project.lf_balance - - ## Advance cash - advance = project.lf_advance - - return { - 'nom' : nom, - 'cash_flow': cash_flow, - 'delay': delay, - 'balance': balance, - 'advance': advance, - 'total_days': total_days, - } - diff --git a/models/res_config.py b/models/res_config.py index f17f990974cdc58a6080df98cdf6d02c865280b0..ad5288440b948cc60621ea8a36515706eeafe12e 100644 --- a/models/res_config.py +++ b/models/res_config.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +# © 2017 Le Filament (<http://www.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): diff --git a/static/src/js/cash_flow.js b/static/src/js/cash_flow.js index c91e5505d5681924efaae0729d5b58fc72353bfb..01860703de71e835b17c14da4903c4faa3401261 100644 --- a/static/src/js/cash_flow.js +++ b/static/src/js/cash_flow.js @@ -1,3 +1,6 @@ +// # © 2017 Le Filament (<http://www.le-filament.com>) +// # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + odoo.define('lefilament_projets.cashFlow', function(require) { 'use strict'; diff --git a/static/src/js/widget.js b/static/src/js/widget.js index b6ea2098e4c7350872fd65559a90470a2ad7f0f6..bbf70f53959831b31ee8935b13503e6d7f1894b9 100644 --- a/static/src/js/widget.js +++ b/static/src/js/widget.js @@ -1,4 +1,7 @@ -// path_to_your_module/static/src/js/form_widgets.js + +// # © 2017 Le Filament (<http://www.le-filament.com>) +// # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + odoo.define('lefilament_projets.progress_bar', function (require) { "use strict";