Initial commit account_invoice_change and account_invoice_change_analytic for 10.0

This commit is contained in:
Jared Kipe
2018-05-12 14:11:37 -07:00
parent b3ffa831af
commit 35a7031feb
14 changed files with 323 additions and 0 deletions

View File

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

View File

@@ -0,0 +1,30 @@
{
'name': 'Account Invoice Change',
'author': 'Hibou Corp. <hello@hibou.io>',
'version': '10.0.1.0.0',
'category': 'Accounting',
'sequence': 95,
'summary': 'Technical foundation for changing invoices.',
'description': """
Technical foundation for changing invoices.
Creates wizard and permissions for making invoice changes that can be
handled by other individual modules.
This module implements, as examples, how to change the Salesperson and Date fields.
Abstractly, individual 'changes' should come from specific 'fields' or capability
modules that handle the consequences of changing that field in whatever state the
the invoice is currently in.
""",
'website': 'https://hibou.io/',
'depends': [
'account',
],
'data': [
'wizard/invoice_change_views.xml',
],
'installable': True,
'application': False,
}

View File

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

View File

@@ -0,0 +1,60 @@
from odoo.addons.account.tests.account_test_users import AccountTestUsers
from odoo import fields
class TestInvoiceChange(AccountTestUsers):
def test_invoice_change_basic(self):
self.account_invoice_obj = self.env['account.invoice']
self.payment_term = self.env.ref('account.account_payment_term_advance')
self.journalrec = self.env['account.journal'].search([('type', '=', 'sale')])[0]
self.partner3 = self.env.ref('base.res_partner_3')
account_user_type = self.env.ref('account.data_account_type_receivable')
self.account_rec1_id = self.account_model.sudo(self.account_manager.id).create(dict(
code="cust_acc",
name="customer account",
user_type_id=account_user_type.id,
reconcile=True,
))
invoice_line_data = [
(0, 0,
{
'product_id': self.env.ref('product.product_product_5').id,
'quantity': 10.0,
'account_id': self.env['account.account'].search(
[('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id,
'name': 'product test 5',
'price_unit': 100.00,
}
)
]
self.invoice_basic = self.account_invoice_obj.sudo(self.account_user.id).create(dict(
name="Test Customer Invoice",
reference_type="none",
payment_term_id=self.payment_term.id,
journal_id=self.journalrec.id,
partner_id=self.partner3.id,
account_id=self.account_rec1_id.id,
invoice_line_ids=invoice_line_data
))
self.assertEqual(self.invoice_basic.state, 'draft')
self.invoice_basic.action_invoice_open()
self.assertEqual(self.invoice_basic.state, 'open')
self.assertEqual(self.invoice_basic.date, fields.Date.today())
self.assertEqual(self.invoice_basic.user_id, self.account_user)
self.assertEqual(self.invoice_basic.move_id.date, fields.Date.today())
self.assertEqual(self.invoice_basic.move_id.line_ids[0].date, fields.Date.today())
ctx = {'active_model': 'account.invoice', 'active_ids': [self.invoice_basic.id]}
change = self.env['account.invoice.change'].with_context(ctx).create({})
self.assertEqual(change.date, self.invoice_basic.date)
self.assertEqual(change.user_id, self.invoice_basic.user_id)
change_date = '2018-01-01'
change_user = self.env.user
change.write({'user_id': change_user.id, 'date': change_date})
change.affect_change()
self.assertEqual(self.invoice_basic.date, change_date)
self.assertEqual(self.invoice_basic.user_id, change_user)
self.assertEqual(self.invoice_basic.move_id.date, change_date)
self.assertEqual(self.invoice_basic.move_id.line_ids[0].date, change_date)

View File

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

View File

@@ -0,0 +1,56 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class InvoiceChangeWizard(models.TransientModel):
_name = 'account.invoice.change'
_description = 'Invoice Change'
invoice_id = fields.Many2one('account.invoice', string='Invoice', readonly=True, required=True)
invoice_company_id = fields.Many2one('res.company', readonly=True, related='invoice_id.company_id')
user_id = fields.Many2one('res.users', string='Salesperson')
date = fields.Date(string='Accounting Date')
@api.model
def default_get(self, fields):
rec = super(InvoiceChangeWizard, self).default_get(fields)
context = dict(self._context or {})
active_model = context.get('active_model')
active_ids = context.get('active_ids')
# Checks on context parameters
if not active_model or not active_ids:
raise UserError(
_("Programmation error: wizard action executed without active_model or active_ids in context."))
if active_model != 'account.invoice':
raise UserError(_(
"Programmation error: the expected model for this action is 'account.invoice'. The provided one is '%d'.") % active_model)
# Checks on received invoice records
invoice = self.env[active_model].browse(active_ids)
if len(invoice) != 1:
raise UserError(_("Invoice Change expects only one invoice."))
rec.update({
'invoice_id': invoice.id,
'user_id': invoice.user_id.id,
'date': invoice.date,
})
return rec
def _new_invoice_vals(self):
vals = {}
if self.invoice_id.user_id != self.user_id:
vals['user_id'] = self.user_id.id
if self.invoice_id.date != self.date:
vals['date'] = self.date
return vals
@api.multi
def affect_change(self):
self.ensure_one()
vals = self._new_invoice_vals()
if vals:
self.invoice_id.write(vals)
if 'date' in vals and self.invoice_id.move_id:
self.invoice_id.move_id.write({'date': vals['date']})
return True

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="account_invoice_change_form" model="ir.ui.view">
<field name="name">Invoice Change</field>
<field name="model">account.invoice.change</field>
<field name="arch" type="xml">
<form string="Invoice Change">
<group>
<group name="group_left">
<field name="invoice_id" invisible="1"/>
<field name="invoice_company_id" invisible="1"/>
<field name="user_id"/>
<field name="date"/>
</group>
<group name="group_right"/>
</group>
<footer>
<button name="affect_change" string="Change" type="object" class="btn-primary"/>
<button string="Cancel" class="btn-default" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_view_account_invoice_change" model="ir.actions.act_window">
<field name="name">Invoice Change Wizard</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">account.invoice.change</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record id="invoice_form_inherit" model="ir.ui.view">
<field name="name">account.invoice.form.inherit</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='state']" position="before">
<button name="%(action_view_account_invoice_change)d" string="Change"
type="action" class="btn-secondary"
attrs="{'invisible': [('state', 'in', ('sale', 'done', 'cancel'))]}"
context="{'default_invoice_id': id}"
groups="account.group_account_manager" />
</xpath>
</field>
</record>
</odoo>

View File

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

View File

@@ -0,0 +1,23 @@
{
'name': 'Account Invoice Change - Analytic',
'author': 'Hibou Corp. <hello@hibou.io>',
'version': '10.0.1.0.0',
'category': 'Accounting',
'sequence': 95,
'summary': 'Change Analytic Account on Invoice.',
'description': """
Adds fields and functionality to change the analytic account on all invoice lines
and subsequent documents.
""",
'website': 'https://hibou.io/',
'depends': [
'account_invoice_change',
'analytic',
],
'data': [
'wizard/invoice_change_views.xml',
],
'installable': True,
'application': False,
}

View File

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

View File

@@ -0,0 +1,46 @@
from odoo.addons.account_invoice_change.tests.test_invoice_change import TestInvoiceChange
class TestWizard(TestInvoiceChange):
def test_invoice_change_basic(self):
self.analytic_account = self.env['account.analytic.account'].create({
'name': 'test account',
})
self.analytic_account2 = self.env['account.analytic.account'].create({
'name': 'test account2',
})
super(TestWizard, self).test_invoice_change_basic()
# Tests Adding an Analytic Account
self.assertFalse(self.invoice_basic.invoice_line_ids.mapped('account_analytic_id'))
ctx = {'active_model': 'account.invoice', 'active_ids': [self.invoice_basic.id]}
change = self.env['account.invoice.change'].with_context(ctx).create({})
change.analytic_account_id = self.analytic_account
change.affect_change()
self.assertTrue(self.invoice_basic.invoice_line_ids.mapped('account_analytic_id'))
self.assertEqual(self.invoice_basic.move_id.mapped('line_ids.analytic_account_id'), self.analytic_account)
# Tests Removing Analytic Account
new_invoice = self.invoice_basic.copy()
new_invoice.invoice_line_ids.account_analytic_id = self.analytic_account
new_invoice.action_invoice_open()
self.assertEqual(new_invoice.state, 'open')
self.assertEqual(new_invoice.move_id.mapped('line_ids.analytic_account_id'), self.analytic_account)
ctx = {'active_model': 'account.invoice', 'active_ids': [new_invoice.id]}
change = self.env['account.invoice.change'].with_context(ctx).create({})
change.analytic_account_id = False
change.affect_change()
self.assertFalse(new_invoice.invoice_line_ids.mapped('account_analytic_id'))
self.assertFalse(new_invoice.move_id.mapped('line_ids.analytic_account_id'))
# Tests Changing Analytic Account
new_invoice = self.invoice_basic.copy()
new_invoice.invoice_line_ids.account_analytic_id = self.analytic_account
new_invoice.action_invoice_open()
self.assertEqual(new_invoice.state, 'open')
self.assertEqual(new_invoice.move_id.mapped('line_ids.analytic_account_id'), self.analytic_account)
ctx = {'active_model': 'account.invoice', 'active_ids': [new_invoice.id]}
change = self.env['account.invoice.change'].with_context(ctx).create({})
change.analytic_account_id = self.analytic_account2
change.affect_change()
self.assertEqual(new_invoice.move_id.mapped('line_ids.analytic_account_id'), self.analytic_account2)

View File

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

View File

@@ -0,0 +1,41 @@
from odoo import api, fields, models, _
class InvoiceChangeWizard(models.TransientModel):
_inherit = 'account.invoice.change'
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account')
def _analytic_account_id(self, invoice):
analytics = invoice.invoice_line_ids.mapped('account_analytic_id')
if len(analytics):
return analytics[0].id
return False
@api.model
def default_get(self, fields):
rec = super(InvoiceChangeWizard, self).default_get(fields)
invoice = self.env['account.invoice'].browse(rec['invoice_id'])
rec.update({
'analytic_account_id': self._analytic_account_id(invoice),
})
return rec
@api.multi
def affect_change(self):
old_analytic_id = self._analytic_account_id(self.invoice_id)
res = super(InvoiceChangeWizard, self).affect_change()
self._affect_analytic_change(old_analytic_id)
return res
def _affect_analytic_change(self, old_analytic_id):
if old_analytic_id != self.analytic_account_id.id:
self.invoice_id.invoice_line_ids \
.filtered(lambda l: l.account_analytic_id.id == old_analytic_id) \
.write({'account_analytic_id': self.analytic_account_id.id})
if self.invoice_id.move_id:
lines_to_affect = self.invoice_id.move_id \
.line_ids.filtered(lambda l: l.analytic_account_id.id == old_analytic_id)
lines_to_affect.write({'analytic_account_id': self.analytic_account_id.id})
lines_to_affect.create_analytic_lines()

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="account_invoice_change_form_inherit" model="ir.ui.view">
<field name="name">account.invoice.change.form.inherit</field>
<field name="model">account.invoice.change</field>
<field name="inherit_id" ref="account_invoice_change.account_invoice_change_form"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='group_right']" position="inside">
<field name="analytic_account_id" domain="[('company_id', '=', invoice_company_id)]"/>
</xpath>
</field>
</record>
</odoo>