diff --git a/__init__.py b/__init__.py index bab6ee4efb0b22a7440dd3c6864664d23a615fe0..95389ec8280db207857ab02500147133fac62c4e 100644 --- a/__init__.py +++ b/__init__.py @@ -1,4 +1,4 @@ # Copyright 2020 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from . import models, report +from . import controllers, models, report diff --git a/__manifest__.py b/__manifest__.py index e1b81f1d5b153b64b1c73a562440ab134da5f150..de4502e6bba38733b389fd410341f91440bde197 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -11,10 +11,14 @@ "security/ir.model.access.csv", # templates "templates/account_invoice_templates.xml", + "templates/invoice_allocation_templates.xml", # templates "report/account_invoice_employee_report.xml", # views + "views/assets.xml", "views/account_invoice_views.xml", "views/res_partner_views.xml", + # menus + "views/menus.xml", ], } diff --git a/models/account_invoice.py b/models/account_invoice.py index fa7aaf95ea210793d93afa8dde183c6bc7bf5fe2..a5ae05538bede7eea734354d82e7d2fff26a584d 100644 --- a/models/account_invoice.py +++ b/models/account_invoice.py @@ -8,10 +8,18 @@ class AccountInvoice(models.Model): _inherit = "account.invoice" with_detail = fields.Boolean("Facture avec détail", default=False) + subcontracting_amount = fields.Monetary("Montant sous-traitance (HT)", track_visibility=True,) + expense_amount = fields.Monetary("Montant frais (HT)", track_visibility=True,) + production_amount = fields.Monetary( + string="CA production", + compute="_compute_production_amount", + store=True, + ) employee_allocation_ids = fields.One2many( comodel_name="account.invoice.employee.assign", inverse_name="invoice_id", string="Ventilation facture", + tracking=True, ) is_allocated = fields.Boolean( string="Facture ventilée", @@ -25,6 +33,7 @@ class AccountInvoice(models.Model): store=True, default=False, ) + suspicious_client = fields.Boolean("Client douteux", default=False, tracking=True,) # ------------------------------------------------------ # Computed field @@ -42,3 +51,28 @@ class AccountInvoice(models.Model): else: invoice.is_allocated = False invoice.is_allocation_error = False + + @api.depends("amount_untaxed_signed", "subcontracting_amount", "expense_amount") + @api.multi + def _compute_production_amount(self): + for invoice in self: + invoice.production_amount = ( + invoice.amount_untaxed_signed + - invoice.subcontracting_amount + - invoice.expense_amount + ) + + # ------------------------------------------------------ + # Business function + # ------------------------------------------------------ + def get_employee_allocation(self, partner_id): + self.ensure_one() + emp_values = self.employee_allocation_ids.filtered( + lambda e: e.partner_id == partner_id + ) + return sum(emp_values.mapped("percentage")) + + def create_employee_lines(self, vals): + self.ensure_one() + self.employee_allocation_ids.unlink() + self.update(vals) diff --git a/models/account_invoice_employee_assign.py b/models/account_invoice_employee_assign.py index 96ccb24e55f2ade91cc83cf603aa8494210b8164..14ecb08b1ecdac680b983e98d547e21bbc9c051c 100644 --- a/models/account_invoice_employee_assign.py +++ b/models/account_invoice_employee_assign.py @@ -36,3 +36,53 @@ class AccountInvoiceEmployeeAssign(models.Model): for record in self: if record.percentage < 0 or record.percentage > 100: raise UserError(_("Le pourcentage doit être entre 0 et 100")) + + # ------------------------------------------------------ + # Override ORM + # ------------------------------------------------------ + @api.model + def create(self, vals): + res = super(AccountInvoiceEmployeeAssign, self).create(vals) + if vals: + message = "Création ligne d'affectation : " + for val in vals: + message += ( + self.env["res.partner"].browse(val.get("partner_id")).name + + " - " + val.get("percent") + "%" + ) + res.invoice_id.message_post(message) + return res + + @api.model + def create(self, vals): + res = super(AccountInvoiceEmployeeAssign, self).create(vals) + if vals: + print(vals) + message = "<strong>Affectation</strong> | Création ligne d'affectation : " + message += ( + self.env["res.partner"].browse(vals.get("partner_id")).name + + " - " + str(vals.get("percentage")) + "%" + ) + res.invoice_id.message_post(body=message) + return res + + @api.multi + def write(self, vals): + for line in self: + message = ( + "<strong>Affectation</strong> | Modification de la ligne : " + + line.partner_id.name + " - " + str(line.percentage) + "%" + ) + line.invoice_id.message_post(body=message) + result = super(AccountInvoiceEmployeeAssign, self).write(vals) + return result + + @api.multi + def unlink(self): + for line in self: + message = ( + "<strong>Affectation</strong> | Suppression de la ligne : " + + line.partner_id.name + " - " + str(line.percentage) + "%" + ) + line.invoice_id.message_post(body=message) + return super(AccountInvoiceEmployeeAssign, self).unlink() diff --git a/report/account_invoice_employee_report.py b/report/account_invoice_employee_report.py index 29159f5313873d4162f58f3c6a3d1ff1e900183d..b9aa4e017014985e04779e40fc44adae710b252d 100644 --- a/report/account_invoice_employee_report.py +++ b/report/account_invoice_employee_report.py @@ -16,7 +16,8 @@ class AccountInvoiceEmployeeReport(models.Model): string="Facture", readonly=True, ) - amount_untaxed_signed = fields.Monetary("Montant H.T", readonly=True) + amount_untaxed_signed = fields.Monetary("Facturé H.T", readonly=True) + production_amount = fields.Monetary("Production H.T", readonly=True) state = fields.Selection( [ ("open", "Ouverte"), @@ -47,6 +48,7 @@ class AccountInvoiceEmployeeReport(models.Model): "user_id", "amount_untaxed_signed", "date_invoice", + "production_amount", ], "account.invoice.employee.assign": [ "partner_id", @@ -63,13 +65,14 @@ class AccountInvoiceEmployeeReport(models.Model): e.id, i.id as "invoice_id", i.date_invoice, + i.production_amount, i.amount_untaxed_signed, i.state, i.user_id, i.currency_id, e.partner_id, e.percentage, - i.amount_untaxed_signed * e.percentage / 100 as "revenue" + i.production_amount * e.percentage / 100 as "revenue" FROM account_invoice_employee_assign e LEFT JOIN diff --git a/report/account_invoice_employee_report.xml b/report/account_invoice_employee_report.xml index 493a282e000d2e064f08912bff773a32c0c16c94..1acf2362ec4e30517ddff050fc2bce1974aa6ef0 100644 --- a/report/account_invoice_employee_report.xml +++ b/report/account_invoice_employee_report.xml @@ -44,6 +44,7 @@ <field name="revenue" widget="monetary" /> <field name="user_id" /> <field name="invoice_id" /> + <field name="production_amount" /> <field name="amount_untaxed_signed" /> <field name="state" /> </tree> diff --git a/views/account_invoice_views.xml b/views/account_invoice_views.xml index 33d8f7b13585c7ed09ce74ebb9fc766413c31957..59996ff30d521aa06d575e1ce53390f3a642d32d 100644 --- a/views/account_invoice_views.xml +++ b/views/account_invoice_views.xml @@ -3,6 +3,7 @@ License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> <odoo> <data> + <!-- FORM --> <record id="legicoop_invoice_form" model="ir.ui.view"> <field name="name">legicoop.account.invoice.form</field> <field name="model">account.invoice</field> @@ -11,6 +12,7 @@ <!-- Détail de la facture --> <xpath expr="//field[@name='payment_term_id']" position="after"> <field name="with_detail" /> + <field name="suspicious_client" widget="boolean_toggle" /> </xpath> <xpath expr="//page[@name='other_info']/group/group[2]/field[@name='origin']" @@ -21,6 +23,12 @@ <!-- Ventilation de la facture --> <xpath expr="//notebook" position="inside"> <page name="employee_assign" string="Répartition par employé"> + <group> + <group> + <field name="subcontracting_amount"/> + <field name="expense_amount"/> + </group> + </group> <field name="is_allocation_error" invisible="1" /> <div class="alert alert-danger" @@ -65,6 +73,12 @@ sum="Total HT" /> </xpath> + <xpath + expr="//field[@name='state']" + position="after" + > + <field name="suspicious_client" widget="boolean_toggle" /> + </xpath> </field> </record> @@ -75,6 +89,12 @@ <field name="inherit_id" ref="account.view_account_invoice_filter" /> <field name="arch" type="xml"> <xpath expr="//filter[@name='late']" position="after"> + <separator /> + <filter + string="Clients douteur" + name="is_suspicious" + domain="[('suspicious_client', '=', True)]" + /> <separator /> <filter string="Factures à répartir"