diff --git a/models/lefilament_tdb.py b/models/lefilament_tdb.py index 3845edffdec49fb6733b2f7af67b90ed95e7bba2..32b947176ff9ddf3156475213434533b55d9c811 100644 --- a/models/lefilament_tdb.py +++ b/models/lefilament_tdb.py @@ -1,7 +1,7 @@ # © 2019 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from datetime import datetime +from datetime import date, datetime from dateutil.relativedelta import relativedelta @@ -18,92 +18,87 @@ class LeFilamentTdb(models.Model): date_tdb = fields.Date( "Date", required=True, default=Date.context_today, store=True ) - ca_mois = fields.Float("Facturé", compute="compute_dashboard_values", store=True) - cmd_mois = fields.Float("Commandes", compute="compute_dashboard_values", store=True) - pipe_mois = fields.Float("Pipe", compute="compute_dashboard_values", store=True) - treso = fields.Float("Trésorerie", compute="compute_dashboard_values", store=True) + ca_mois = fields.Float("Facturé", compute="_compute_dashboard_values", store=True) + cmd_mois = fields.Float( + "Commandes", compute="_compute_dashboard_values", store=True + ) + pipe_mois = fields.Float("Pipe", compute="_compute_dashboard_values", store=True) + treso = fields.Float("Trésorerie", compute="_compute_dashboard_values", store=True) variation = fields.Float( - "Variation", compute="compute_dashboard_values", store=True + "Variation", compute="_compute_dashboard_values", store=True ) - charges = fields.Float("Décaissé", compute="compute_dashboard_values", store=True) - encaisse = fields.Float("Encaissé", compute="compute_dashboard_values", store=True) + charges = fields.Float("Décaissé", compute="_compute_dashboard_values", store=True) + encaisse = fields.Float("Encaissé", compute="_compute_dashboard_values", store=True) charges_fixes = fields.Float("Charges Fixes", default=10000) runway = fields.Float("Runway", compute="_compute_runway_value") @api.depends("date_tdb") - def compute_dashboard_values(self): + def _compute_dashboard_values(self): for record in self: if record.date_tdb: - date_tdb = Date.from_string(record.date_tdb) + date_start = date(record.date_tdb.year, record.date_tdb.month, 1) + date_end = date( + record.date_tdb.year, record.date_tdb.month, 1 + ) + relativedelta(months=1) # FACTURÉ - self.env.cr.execute( - "SELECT SUM(amount_untaxed_signed) \ - FROM account_move \ - WHERE state != 'draft' \ - AND (move_type = 'out_invoice' OR move_type = 'out_refund') \ - AND date >= date_trunc('month', %s) \ - AND date < date_trunc('month', %s + interval '1' month);", - (date_tdb, date_tdb), + invoice_ids = self.env["account.move"].search( + [ + ("state", "=", "posted"), + ("move_type", "in", ("out_invoice", "out_refund")), + ("invoice_date", ">=", date_start), + ("invoice_date", "<", date_end), + ] ) - ca_mois = self.env.cr.fetchone()[0] + ca_mois = sum(invoice_ids.mapped("amount_untaxed_signed")) # COMMANDES TOTAL - self.env.cr.execute( - "SELECT SUM(amount_untaxed) \ - FROM sale_order \ - WHERE invoice_status = 'to invoice' \ - AND date_order >= date_trunc('month', %s) \ - AND date_order < date_trunc('month', %s \ - + interval '1' month);", - (date_tdb, date_tdb), + order_ids = self.env["sale.order"].search( + [ + ("invoice_status", "=", "to invoice"), + ("date_order", ">=", date_start), + ("date_order", "<", date_end), + ] ) - cmd_mois = self.env.cr.fetchone()[0] + cmd_mois = sum(order_ids.mapped("amount_untaxed")) # Trésorerie - self.env.cr.execute( - "SELECT SUM(amount) \ - FROM account_bank_statement_line \ - WHERE date < date_trunc('month', %s \ - + interval '1' month)", - (date_tdb,), + statement_line_ids = self.env["account.bank.statement.line"].search( + [ + ("date", "<", date_end), + ] ) - treso_total = self.env.cr.fetchone()[0] + treso_total = sum(statement_line_ids.mapped("amount")) + # CHARGES - self.env.cr.execute( - "SELECT SUM(amount) \ - FROM account_bank_statement_line \ - WHERE amount < 0 \ - AND date >= date_trunc('month', %s) \ - AND date < date_trunc('month', %s + interval '1' month)", - (date_tdb, date_tdb), + negative_line_ids = self.env["account.bank.statement.line"].search( + [ + ("amount", "<", 0), + ("date", ">=", date_start), + ("date", "<", date_end), + ] ) - charges = self.env.cr.fetchone()[0] + charges = sum(negative_line_ids.mapped("amount")) # ENCAISSE - self.env.cr.execute( - "SELECT SUM(amount) \ - FROM account_bank_statement_line \ - WHERE amount > 0 \ - AND date >= date_trunc('month', %s) \ - AND date < date_trunc('month', %s + interval '1' month)", - (date_tdb, date_tdb), + positive_line_ids = self.env["account.bank.statement.line"].search( + [ + ("amount", ">", 0), + ("date", ">=", date_start), + ("date", "<", date_end), + ] ) - encaisse = self.env.cr.fetchone()[0] + encaisse = sum(positive_line_ids.mapped("amount")) # CHARGES FIXES - self.env.cr.execute( - "SELECT charges_fixes \ - FROM res_company" - ) - charges_fixes = self.env.cr.fetchone()[0] + charges_fixes = self.env.company.charges_fixes # PIPE - self.env.cr.execute( - "SELECT SUM(expected_revenue * probability / 100) \ - FROM crm_lead \ - WHERE active = True" + opportunity_ids = self.env["crm.lead"].search([]) + pipe = sum( + opportunity_ids.mapped( + lambda o: o.expected_revenue * o.probability / 100 + ) ) - pipe = self.env.cr.fetchone()[0] if not encaisse: encaisse = 0 @@ -152,6 +147,10 @@ class LeFilamentTdb(models.Model): def _new_data(self): self.create({"date_tdb": Date.today()}) + def get_month_values(self): + for data in self: + data._compute_dashboard_values() + @api.model def retrieve_datas_dashboard(self): # Get fiscal years @@ -172,76 +171,144 @@ class LeFilamentTdb(models.Model): fiscal_year_next = "'" + Date.to_string(fiscal_date) + "'" res = {} - res['fiscal_year'] = fiscal_year - res['fiscal_year_next'] = fiscal_year_next - res['target'] = self.env.user.company_id.ca_target - - res['facture'] = sum(self.env['account.move'].search([ - ('move_type', 'in', ('out_invoice', 'out_refund')), - ('state', '=', 'posted'), - ('invoice_date', '>', fiscal_year), - ('invoice_date', '<=', fiscal_year_next) - ]).mapped('amount_untaxed_signed')) - - res['commandes'] = sum(self.env['sale.order.line'].search([ - ('invoice_status', '=', 'to invoice'), - ]).mapped('untaxed_amount_to_invoice')) - - res['pipe'] = sum(self.env['crm.lead'].search([ - '|', - ('date_deadline', '<=', fiscal_year_next), - ('date_deadline', '=', False), - ]).mapped(lambda l: l.expected_revenue * l.probability / 100)) - res['pipe_n1'] = sum(self.env['crm.lead'].search([ - ('date_deadline', '>', fiscal_year_next), - ]).mapped(lambda l: l.expected_revenue * l.probability / 100)) - res['pipe_win'] = sum(self.env['crm.lead'].search([ - ('probability', '=', 100), - '|', - ('date_deadline', '<=', fiscal_year_next), - ('date_deadline', '=', False), - ]).mapped(lambda l: l.expected_revenue * l.probability / 100)) - res['pipe_to_win'] = sum(self.env['crm.lead'].search([ - ('probability', '!=', 100), - '|', - ('date_deadline', '<=', fiscal_year_next), - ('date_deadline', '=', False), - ]).mapped(lambda l: l.expected_revenue * l.probability / 100)) - - res['a_encaisser'] = sum(self.env['account.move'].search([ - ('move_type', 'in', ('out_invoice', 'out_refund')), - ('state', '=', 'posted'), - ('payment_state', '!=', 'paid') - ]).mapped('amount_residual_signed')) - res['a_payer'] = sum(self.env['account.move'].search([ - ('move_type', 'in', ('in_invoice', 'in_refund')), - ('state', '=', 'posted'), - ('payment_state', '!=', 'paid') - ]).mapped('amount_residual_signed')) - - res['date_maj'] = self.env['account.bank.statement'].search([ - ('active', 'in', (True, False))], - order='date desc', - limit=1 - ).date - res['tresorerie'] = sum(self.env['account.bank.statement.line'].search([]).mapped('amount')) - res['treso_by_bank'] = self.env['account.bank.statement.line'].read_group( + res["fiscal_year"] = fiscal_year + res["fiscal_year_next"] = fiscal_year_next + res["target"] = self.env.user.company_id.ca_target + + res["facture"] = sum( + self.env["account.move"] + .search( + [ + ("move_type", "in", ("out_invoice", "out_refund")), + ("state", "=", "posted"), + ("invoice_date", ">", fiscal_year), + ("invoice_date", "<=", fiscal_year_next), + ] + ) + .mapped("amount_untaxed_signed") + ) + + res["commandes"] = sum( + self.env["sale.order.line"] + .search( + [ + ("invoice_status", "=", "to invoice"), + ] + ) + .mapped("untaxed_amount_to_invoice") + ) + + res["pipe"] = sum( + self.env["crm.lead"] + .search( + [ + "|", + ("date_deadline", "<=", fiscal_year_next), + ("date_deadline", "=", False), + ] + ) + .mapped(lambda l: l.expected_revenue * l.probability / 100) + ) + res["pipe_n1"] = sum( + self.env["crm.lead"] + .search( + [ + ("date_deadline", ">", fiscal_year_next), + ] + ) + .mapped(lambda l: l.expected_revenue * l.probability / 100) + ) + res["pipe_win"] = sum( + self.env["crm.lead"] + .search( + [ + ("probability", "=", 100), + "|", + ("date_deadline", "<=", fiscal_year_next), + ("date_deadline", "=", False), + ] + ) + .mapped(lambda l: l.expected_revenue * l.probability / 100) + ) + res["pipe_to_win"] = sum( + self.env["crm.lead"] + .search( + [ + ("probability", "!=", 100), + "|", + ("date_deadline", "<=", fiscal_year_next), + ("date_deadline", "=", False), + ] + ) + .mapped(lambda l: l.expected_revenue * l.probability / 100) + ) + + res["a_encaisser"] = sum( + self.env["account.move"] + .search( + [ + ("move_type", "in", ("out_invoice", "out_refund")), + ("state", "=", "posted"), + ("payment_state", "!=", "paid"), + ] + ) + .mapped("amount_residual_signed") + ) + res["a_payer"] = sum( + self.env["account.move"] + .search( + [ + ("move_type", "in", ("in_invoice", "in_refund")), + ("state", "=", "posted"), + ("payment_state", "!=", "paid"), + ] + ) + .mapped("amount_residual_signed") + ) + + res["date_maj"] = ( + self.env["account.bank.statement"] + .search([("active", "in", (True, False))], order="date desc", limit=1) + .date + ) + res["tresorerie"] = sum( + self.env["account.bank.statement.line"].search([]).mapped("amount") + ) + res["treso_by_bank"] = self.env["account.bank.statement.line"].read_group( domain=[], - fields=['journal_id', 'amount'], - groupby=['journal_id'], - orderby='journal_id' + fields=["journal_id", "amount"], + groupby=["journal_id"], + orderby="journal_id", + ) + res["entree"] = sum( + self.env["account.bank.statement.line"] + .search( + [ + ("amount", ">", 0), + ("date", ">", fiscal_year), + ] + ) + .mapped("amount") + ) + res["sortie"] = sum( + self.env["account.bank.statement.line"] + .search( + [ + ("amount", "<", 0), + ("date", ">", fiscal_year), + ] + ) + .mapped("amount") + ) + res["variation"] = sum( + self.env["account.bank.statement.line"] + .search( + [ + ("date", ">", fiscal_year), + ] + ) + .mapped("amount") ) - res['entree'] = sum(self.env['account.bank.statement.line'].search([ - ('amount', '>', 0), - ('date', '>', fiscal_year), - ]).mapped('amount')) - res['sortie'] = sum(self.env['account.bank.statement.line'].search([ - ('amount', '<', 0), - ('date', '>', fiscal_year), - ]).mapped('amount')) - res['variation'] = sum(self.env['account.bank.statement.line'].search([ - ('date', '>', fiscal_year), - ]).mapped('amount')) return res diff --git a/static/src/js/dashboard_year.js b/static/src/js/dashboard_year.js index e75085e9ca089d0a78506dc6960eee9c7cb2500c..82b69e7c48d5a9086dbf7e1a1dc9c50cc57817fb 100644 --- a/static/src/js/dashboard_year.js +++ b/static/src/js/dashboard_year.js @@ -105,12 +105,8 @@ odoo.define("lefilament_tdb.dashboard_year", function (require) { (self.values.pipe_to_win / self.values.target) * 100 ).toFixed(0); - self.ptarg = - 100 - - self.pfact; - self.ptarg2 = - self.values.target - - self.pfact2; + self.ptarg = 100 - self.pfact; + self.ptarg2 = self.values.target - self.pfact2; self.total = ( ((self.values.facture + self.values.commandes + @@ -148,7 +144,7 @@ odoo.define("lefilament_tdb.dashboard_year", function (require) { this.ctx = this.$el.find("#target")[0].getContext("2d"); - var yeartarget = this.yeartarget + var yeartarget = this.yeartarget; var ptarg = this.ptarg; var max_xaxis = 100; @@ -386,7 +382,7 @@ odoo.define("lefilament_tdb.dashboard_year", function (require) { name: "Factures en cours", context: context, }; - console.log(action) + console.log(action); this.do_action(action); }, fournisseur: function () { diff --git a/static/src/xml/lefilament_tdb.xml b/static/src/xml/lefilament_tdb.xml index 0ea55fe75a532f8b5004062429e7dafc21341530..5c8c32ef56f181b8b065f3ecaf341fb4d4bf5458 100644 --- a/static/src/xml/lefilament_tdb.xml +++ b/static/src/xml/lefilament_tdb.xml @@ -152,25 +152,41 @@ <div class="col-xs-12 dashboard-tab"> <ul class="nav nav-tabs" id="tresoTab"> <li class="nav-item"> - <a class="nav-link active" data-toggle="tab" href="#treso">Trésorerie</a> + <a + class="nav-link active" + data-toggle="tab" + href="#treso" + >Trésorerie</a> </li> <li class="nav-item"> - <a class="nav-link" data-toggle="tab" href="#by-bank">Solde banques</a> + <a + class="nav-link" + data-toggle="tab" + href="#by-bank" + >Solde banques</a> </li> </ul> <div class="tab-content card-tab" id="tresoContent"> <div id="treso" class="tab-pane fade show active in"> - <p class="card-maj">Denière mise à jour le <t t-esc="widget.render_date(widget.values.date_maj)"/></p> + <p class="card-maj">Denière mise à jour le <t + t-esc="widget.render_date(widget.values.date_maj)" + /></p> <p class="card-number"> - <a id="releve"><strong><t t-esc="widget.render_monetary(widget.values.tresorerie)"/></strong></a> + <a id="releve"><strong><t + t-esc="widget.render_monetary(widget.values.tresorerie)" + /></strong></a> </p> </div> <div id="by-bank" class="tab-pane fade"> - <table class="table table-striped table-sm table-bordered table-hover"> + <table + class="table table-striped table-sm table-bordered table-hover" + > <t t-foreach="widget.values.treso_by_bank" t-as="bank"> <tr> - <td><t t-esc="bank.journal_id[1]"/></td> - <td class="text-right"><t t-esc="widget.render_monetary_decimal(bank.amount)"/></td> + <td><t t-esc="bank.journal_id[1]" /></td> + <td class="text-right"><t + t-esc="widget.render_monetary_decimal(bank.amount)" + /></td> </tr> </t> </table> @@ -181,10 +197,18 @@ <div class="col-xs-12 dashboard-tab"> <ul class="nav nav-tabs" id="tab3"> <li class="nav-item"> - <a class="nav-link active" data-toggle="tab" href="#non_encaisse">Facturé non encaissé</a> + <a + class="nav-link active" + data-toggle="tab" + href="#non_encaisse" + >Facturé non encaissé</a> </li> <li class="nav-item"> - <a class="nav-link" data-toggle="tab" href="#fournisseur">Fournisseurs</a> + <a + class="nav-link" + data-toggle="tab" + href="#fournisseur" + >Fournisseurs</a> </li> </ul> <div class="tab-content card-tab" id="myTab3Content"> @@ -222,7 +246,9 @@ <div id="variation" class="tab-pane fade show active in"> <p class="card-number"> <a id="statement_lines"> - <t t-raw="widget.render_monetary_color(widget.values.variation)" /> + <t + t-raw="widget.render_monetary_color(widget.values.variation)" + /> </a> </p> </div> diff --git a/views/views.xml b/views/views.xml index 8bc5be2ebf0c9a9de753c0bab0e2b30a837e316f..1be129bc7e73edf22826bf5aebfa81055ebb5283 100644 --- a/views/views.xml +++ b/views/views.xml @@ -107,23 +107,51 @@ <field name="model">account.move</field> <field name="arch" type="xml"> <tree string="Invoices"> - <field name="name" decoration-bf="1"/> - <field name="invoice_date" string="Date Facturation"/> - <field name="partner_id" string="Client"/> + <field name="name" decoration-bf="1" /> + <field name="invoice_date" string="Date Facturation" /> + <field name="partner_id" string="Client" /> <field name="invoice_date_due" /> - <field name="invoice_origin"/> - <field name="payment_reference" optional="hide"/> - <field name="ref" optional="hide"/> - <field name="invoice_user_id" widget="many2one_avatar_user"/> - <field name="amount_untaxed_signed" string="Montant HT" sum="Total" decoration-bf="1" /> - <field name="amount_tax_signed" sum="Total" optional="hide"/> - <field name="amount_total_signed" string="Total" sum="Total" optional="show"/> - <field name="amount_residual_signed" string="Montant Dû" sum="Amount Due" optional="show"/> - <field name="currency_id" invisible="1"/> - <field name="company_currency_id" invisible="1"/> - <field name="state" widget="badge" decoration-success="state == 'posted'" decoration-info="state == 'draft'" optional="show"/> - <field name="payment_state" widget="badge" decoration-danger="payment_state == 'not_paid'" decoration-warning="payment_state in ('partial', 'in_payment')" decoration-success="payment_state in ('paid', 'reversed')" attrs="{'invisible': [('payment_state', 'in', ('invoicing_legacy'))]}"/> - <field name="move_type" invisible="1"/> + <field name="invoice_origin" /> + <field name="payment_reference" optional="hide" /> + <field name="ref" optional="hide" /> + <field name="invoice_user_id" widget="many2one_avatar_user" /> + <field + name="amount_untaxed_signed" + string="Montant HT" + sum="Total" + decoration-bf="1" + /> + <field name="amount_tax_signed" sum="Total" optional="hide" /> + <field + name="amount_total_signed" + string="Total" + sum="Total" + optional="show" + /> + <field + name="amount_residual_signed" + string="Montant Dû" + sum="Amount Due" + optional="show" + /> + <field name="currency_id" invisible="1" /> + <field name="company_currency_id" invisible="1" /> + <field + name="state" + widget="badge" + decoration-success="state == 'posted'" + decoration-info="state == 'draft'" + optional="show" + /> + <field + name="payment_state" + widget="badge" + decoration-danger="payment_state == 'not_paid'" + decoration-warning="payment_state in ('partial', 'in_payment')" + decoration-success="payment_state in ('paid', 'reversed')" + attrs="{'invisible': [('payment_state', 'in', ('invoicing_legacy'))]}" + /> + <field name="move_type" invisible="1" /> </tree> </field> </record> @@ -182,7 +210,7 @@ <button string="MaJ Valeurs" type="object" - name="compute_dashboard_values" + name="get_month_values" class="oe_highlight" /> </header>