bemade_multiple_billing_contacts: Updated view to address a bug.

This commit is contained in:
Marc Durepos 2023-06-26 15:00:00 -04:00
parent e374c53e63
commit ecd5e2b55e
8 changed files with 0 additions and 221 deletions

View file

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

View file

@ -1,38 +0,0 @@
#
# Bemade Inc.
#
# Copyright (C) June 2023 Bemade Inc. (<https://www.bemade.org>).
# Author: mdurepos (Contact : it@bemade.org)
#
# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
# or modified copies of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
{
'name': 'bemade_multiple_billing_contacts',
'version': '15.0.1.0.1',
'summary': 'Send invoices to multiple contacts by default.',
'description': """By default, newly created invoices add all invoice addresses for the given partner as
followers on the invoice. If billing contacts are set manually on the sales order, those billing
contacts are added as followers on the invoice instead.""",
'category': 'Invoicing Management',
'author': 'Bemade Inc.',
'website': 'https://www.bemade.org',
'license': 'OPL-1',
'depends': ['sale',
'account',
'bemade_partner_root_ancestor',
],
'data': [],
'demo': [],
'installable': True,
'auto_install': False,
}

View file

@ -1,3 +0,0 @@
from . import res_partner
from . import sale_order
from . import account_move

View file

@ -1,32 +0,0 @@
from odoo import models, fields, api
class AccountMove(models.Model):
_inherit = 'account.move'
billing_contacts = fields.Many2many(comodel_name='res.partner',
string="Billing Contacts",
compute='_compute_billing_contacts',
inverse='_inverse_billing_contacts',
store=True)
@api.depends('line_ids.sale_line_ids.order_id', 'partner_id')
def _compute_billing_contacts(self):
for rec in self:
order_id = rec.line_ids and rec.line_ids.mapped('sale_line_ids').mapped('order_id')
if order_id and len(order_id) == 1 and order_id.billing_contacts:
rec.billing_contacts = order_id.billing_contacts
else:
rec.billing_contacts = rec.partner_id.billing_contacts
def _inverse_billing_contacts(self):
pass
def _post(self, soft=True):
# Override the original method to subscribe the partner's billing contacts instead of self.partner_id
initial_subscribers = self.message_partner_ids.ids
final_subscribers = initial_subscribers + self.billing_contacts.ids
posted = super()._post()
self.message_unsubscribe([s.id for s in self.message_partner_ids if s not in initial_subscribers])
self.message_subscribe(final_subscribers)
return posted

View file

@ -1,20 +0,0 @@
from odoo import models, fields, api, _, Command
class Partner(models.Model):
_inherit = 'res.partner'
billing_contacts = fields.Many2many(string='Default Billing Contacts',
comodel_name='res.partner',
compute='_compute_billing_contacts',
inverse='_inverse_billing_contacts')
@api.depends('child_ids.type')
def _compute_billing_contacts(self):
for rec in self:
rec.billing_contacts = rec.child_ids.filtered(lambda r: r.type == 'invoice')
@api.depends('billing_contacts')
def _inverse_billing_contacts(self):
for partner in self.mapped('billing_contacts'):
partner.type = 'invoice'

View file

@ -1,19 +0,0 @@
from odoo import models, fields, api, _, Command
class SaleOrder(models.Model):
_inherit = 'sale.order'
billing_contacts = fields.Many2many(comodel_name='res.partner',
string='Billing Contacts',
compute='_compute_billing_contacts',
inverse='_inverse_billing_contacts',
store=True)
@api.depends('partner_id')
def _compute_billing_contacts(self):
for rec in self:
rec.billing_contacts = rec.partner_id.billing_contacts
def _inverse_billing_contacts(self):
pass

View file

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

View file

@ -1,107 +0,0 @@
from odoo.tests import TransactionCase, tagged
from odoo import Command
import datetime
@tagged('-at_install', 'post_install')
class TestBillingContacts(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
partner = cls.env['res.partner'].create
cls.parent_co = partner({
'name': 'Partner',
'company_type': 'company',
})
cls.billing_contact1 = partner({
'name': 'Billing Contact 1',
'company_type': 'person',
'email': 'billingcontact1@partner.co',
'parent_id': cls.parent_co.id,
'type': 'invoice',
})
cls.billing_contact2 = partner({
'name': 'Billing Contact 2',
'company_type': 'person',
'email': 'billingcontact2@partner.co',
'parent_id': cls.parent_co.id,
'type': 'invoice',
})
cls.non_billing_contact = partner({
'name': 'Non-billing contact',
'company_type': 'person',
'email': 'not_billing@partner.co',
'parent_id': cls.parent_co.id,
'type': 'contact',
})
cls.product = cls.env['product.product'].with_company(cls.parent_co.company_id).create({
'name': 'Product',
'categ_id': cls.env['product.category'].create({'name': 'Product Category'}).id,
'list_price': 100.0,
'type': 'service',
'uom_id': cls.env.ref('uom.product_uom_unit').id,
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
'default_code': 'PRODUCT-X',
'invoice_policy': 'order',
'expense_policy': 'no',
'taxes_id': [(6, 0, [])],
'supplier_taxes_id': [(6, 0, [])],
})
cls.sale_order = cls.env['sale.order'].create({
'partner_id': cls.parent_co.id,
'client_order_ref': 'abc123',
})
cls.env['sale.order.line'].create({
'product_id': cls.product.id,
'name': cls.product.name,
'product_uom_qty': 2,
'product_uom': cls.product.uom_id.id,
'price_unit': cls.product.list_price,
'order_id': cls.sale_order.id,
'tax_id': False,
'qty_delivered_manual': 2,
})
def test_billing_contacts_structure(self):
self.assertTrue(self.billing_contact1 in self.parent_co.billing_contacts)
self.assertTrue(self.billing_contact2 in self.parent_co.billing_contacts)
self.assertTrue(self.non_billing_contact not in self.parent_co.billing_contacts)
def test_sale_order_default_billing_contacts(self):
self.assertTrue(self.sale_order.billing_contacts == self.parent_co.billing_contacts)
def test_sale_order_change_contacts(self):
# Test that changing the billing contacts on an SO doesn't change them on the partner
# Validate that changing them manually on the SO transfers to the invoice
self.sale_order.write({'billing_contacts': [Command.link(self.non_billing_contact.id)]})
self.assertTrue(all([c in self.sale_order.billing_contacts for c in self.parent_co.billing_contacts]))
self.assertTrue(self.non_billing_contact not in self.parent_co.billing_contacts)
self.assertTrue(self.non_billing_contact in self.sale_order.billing_contacts)
def test_sale_order_to_invoice_contacts(self):
# Test that the invoices created from sales orders take the billing contacts configured on the SO
self.sale_order.write({'billing_contacts': [Command.link(self.non_billing_contact.id)]})
self.sale_order.action_confirm()
wiz = self.env['sale.advance.payment.inv'].create({})
invoice = wiz._create_invoice(self.sale_order,self.sale_order.order_line[0],self.sale_order.order_line.price_total)
self.assertTrue(invoice)
self.assertTrue(invoice.billing_contacts == self.sale_order.billing_contacts)
def test_direct_invoice_contacts(self):
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': self.parent_co,
})
self.assertTrue(self.parent_co.billing_contacts == invoice.billing_contacts)
def test_invoice_followers_on_validate(self):
self.sale_order.action_confirm()
wiz = self.env['sale.advance.payment.inv'].create({})
invoice = wiz._create_invoice(self.sale_order,self.sale_order.order_line[0],self.sale_order.order_line.price_total)
invoice.write({'date': datetime.date.today()})
invoice.action_post()
self.assertTrue(all([r in invoice.message_partner_ids for r in self.parent_co.billing_contacts]))