[REV] account: revert feature to create recurrent vendor bills
This reverts commit 7642754122.
The reason is that we finally decided to implement that in another way and we want to avoid people start using this feature as it would be replaced in next saas. Yes, I know, that sucks.
New task ID: 1823153
This commit is contained in:
@@ -17,7 +17,6 @@ Core mechanisms for the accounting modules. To display the menuitems, install th
|
||||
'security/ir.model.access.csv',
|
||||
'data/data_account_type.xml',
|
||||
'data/account_data.xml',
|
||||
'data/ir_cron_data.xml',
|
||||
'views/account_menuitem.xml',
|
||||
'views/account_payment_view.xml',
|
||||
'wizard/account_reconcile_view.xml',
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
<!-- Cron job for creating recurring vendor bills -->
|
||||
<record id="recurrent_vendor_bills_cron" model="ir.cron">
|
||||
<field name="name">Account: generate recurring vendor bills</field>
|
||||
<field name="model_id" ref="account.model_account_invoice"/>
|
||||
<field name="state">code</field>
|
||||
<field name="active">False</field>
|
||||
<field name="code">model._cron_generate_recurring_vendor_bill()</field>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="numbercall">-1</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -229,12 +229,6 @@ class AccountInvoice(models.Model):
|
||||
payment_lines.update(line.mapped('matched_debit_ids.debit_move_id.id'))
|
||||
self.payment_move_line_ids = self.env['account.move.line'].browse(list(payment_lines))
|
||||
|
||||
@api.depends('date_invoice', 'is_recurrency_enabled', 'recurrency_interval', 'recurrency_type')
|
||||
def _compute_next_recurrency_date(self):
|
||||
#initially set the recurrency_date
|
||||
for invoice in self.filtered(lambda inv: inv.is_recurrency_enabled and inv.recurrency_interval and inv.recurrency_type and inv.date_invoice and not inv.next_recurrency_date):
|
||||
invoice.next_recurrency_date = invoice._get_next_recurrency_date(invoice.date_invoice)
|
||||
|
||||
name = fields.Char(string='Reference/Description', index=True,
|
||||
readonly=True, states={'draft': [('readonly', False)]}, copy=False, help='The name that will be used on account move lines')
|
||||
|
||||
@@ -373,18 +367,6 @@ class AccountInvoice(models.Model):
|
||||
#fields use to set the sequence, on the first invoice of the journal
|
||||
sequence_number_next = fields.Char(string='Next Number', compute="_get_sequence_number_next", inverse="_set_sequence_next")
|
||||
sequence_number_next_prefix = fields.Char(string='Next Number Prefix', compute="_get_sequence_prefix")
|
||||
#recurrent vendor bills fields
|
||||
is_recurrency_enabled = fields.Boolean(string="Generate Recurring Document(s)", copy=False, help="Tick this box to generate recurring bills. The recurring bills will only be generated if this bill is validated.")
|
||||
recurrency_interval = fields.Integer(string='Every', default=1, copy=False, help="Define the recurrency of the vendor bill.")
|
||||
recurrency_type = fields.Selection([
|
||||
('days', 'Day(s)'),
|
||||
('weeks', 'Week(s)'),
|
||||
('months', 'Month(s)'),
|
||||
('years', 'Year(s)'),
|
||||
], string="Recurrency Type", default='months', copy=False)
|
||||
# Technical field depicting whether the document is generated by cron or by user
|
||||
is_recurring_document = fields.Boolean(string="Recurring Document", copy=False)
|
||||
next_recurrency_date = fields.Date(compute=_compute_next_recurrency_date, _string='Next Recurrency Date', copy=False, store=True)
|
||||
|
||||
_sql_constraints = [
|
||||
('number_uniq', 'unique(number, company_id, journal_id, type)', 'Invoice Number must be unique per Company!'),
|
||||
@@ -468,52 +450,6 @@ class AccountInvoice(models.Model):
|
||||
self.type == 'in_refund' and self.state == 'draft' and _('Vendor Credit Note') or \
|
||||
self.type == 'in_refund' and _('Vendor Credit Note - %s') % (self.number)
|
||||
|
||||
def _get_next_recurrency_date(self, current_date):
|
||||
"""
|
||||
This method is used to return next date based on recurrency configuration of the record.
|
||||
|
||||
:param current_date: Origin date from which next date is to be generated.
|
||||
:returns: future date on which a duplicated document will be generated by crons.
|
||||
"""
|
||||
assert self.recurrency_type, "Invalid `Recurrency` interval! Please set it to either of these: 'Day(s)', 'Week(s)', 'Month(s)' or 'Year(s)'."
|
||||
self.ensure_one()
|
||||
recurring_next_date = fields.Date.from_string(current_date) + relativedelta(**{self.recurrency_type: self.recurrency_interval})
|
||||
# In case of monthly recurrent invoice, future invoices should always be created on same day as of it's main invoice but
|
||||
# if the reference invoice was made on last day of the month, then the recurring invoice should be created on last day of next month.
|
||||
# example, main invoice is set to 31st Jan, the next invoices should be created on 28/29th Feb, 31st Mar, 30 Apr and so on
|
||||
if self.recurrency_type == 'months':
|
||||
reference_invoice_day = fields.Date.from_string(self.date_invoice).day
|
||||
recurring_next_date += relativedelta(day=reference_invoice_day)
|
||||
if reference_invoice_day == fields.Date.from_string(self.date_invoice) + relativedelta(day=31):
|
||||
recurring_next_date += relativedelta(day=31)
|
||||
return recurring_next_date
|
||||
|
||||
@api.model
|
||||
def _cron_generate_recurring_vendor_bill(self):
|
||||
today = fields.Date.today()
|
||||
domain = [
|
||||
('is_recurrency_enabled', '=', True),
|
||||
('state', 'not in', ['draft', 'cancel']),
|
||||
('next_recurrency_date', '<=', today)
|
||||
]
|
||||
for invoice in self.search(domain):
|
||||
while invoice.next_recurrency_date <= today:
|
||||
invoice._create_recurrent_invoice()
|
||||
invoice.next_recurrency_date = invoice._get_next_recurrency_date(invoice.next_recurrency_date)
|
||||
|
||||
def _create_recurrent_invoice(self):
|
||||
self.ensure_one()
|
||||
invoice = self.copy({
|
||||
'origin': '',
|
||||
'date_invoice': self.next_recurrency_date,
|
||||
'is_recurring_document': True,
|
||||
})
|
||||
# set the due date
|
||||
invoice._onchange_payment_term_date_invoice()
|
||||
link = '<a href=# data-oe-model=account.invoice data-oe-id=%d>%s</a>' % (self.id, self.number)
|
||||
invoice.message_post(body=_('This bill has been generated by %s') % link)
|
||||
return invoice
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
onchanges = {
|
||||
|
||||
@@ -57,12 +57,10 @@ class ResConfigSettings(models.TransientModel):
|
||||
tax_exigibility = fields.Boolean(string='Cash Basis', related='company_id.tax_exigibility')
|
||||
tax_cash_basis_journal_id = fields.Many2one('account.journal', related='company_id.tax_cash_basis_journal_id', string="Tax Cash Basis Journal")
|
||||
account_hide_setup_bar = fields.Boolean(string='Hide Setup Bar', related='company_id.account_setup_bar_closed',help="Tick if you wish to hide the setup bar on the dashboard")
|
||||
group_allow_recurring = fields.Boolean(string="Recurring Vendor Bills", implied_group="account.group_allow_recurring")
|
||||
|
||||
@api.multi
|
||||
def set_values(self):
|
||||
super(ResConfigSettings, self).set_values()
|
||||
self.env.ref('account.recurrent_vendor_bills_cron').write({'active': self.group_allow_recurring})
|
||||
if self.group_multi_currency:
|
||||
self.env.ref('base.group_user').write({'implied_ids': [(4, self.env.ref('product.group_sale_pricelist').id)]})
|
||||
""" install a chart of accounts for the given company (if required) """
|
||||
|
||||
@@ -32,11 +32,6 @@
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<record id="group_allow_recurring" model="res.groups">
|
||||
<field name="name">Allow to create recurring vendor bills</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<record id="group_cash_rounding" model="res.groups">
|
||||
<field name="name">Allow the cash rounding management</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
|
||||
@@ -6,7 +6,6 @@ from . import test_account_move_closed_period
|
||||
from . import test_account_supplier_invoice
|
||||
from . import test_account_validate_account_move
|
||||
from . import test_account_invoice_rounding
|
||||
from . import test_account_supplier_invoice_recurrent
|
||||
from . import test_bank_statement_reconciliation
|
||||
#TODO re-enableand fix this test
|
||||
#from . import test_bank_stmt_reconciliation_widget_ui
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo.addons.account.tests.account_test_classes import AccountingTestCase
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAccountRecurrent(AccountingTestCase):
|
||||
|
||||
def apply_vendor_cron(self):
|
||||
self.env.ref('account.recurrent_vendor_bills_cron').method_direct_trigger()
|
||||
|
||||
def test_create_recurring_vendor_bills(self):
|
||||
AccountInvoice = self.env['account.invoice']
|
||||
invoice_account_id = self.env['account.account'].search([('user_type_id', '=', self.ref('account.data_account_type_receivable'))], limit=1).id
|
||||
invoice_line_account_id = self.env['account.account'].search([('user_type_id', '=', self.ref('account.data_account_type_expenses'))], limit=1).id
|
||||
purchase_journal = self.env['account.journal'].search([('type', '=', 'purchase')], limit=1)
|
||||
|
||||
invoice_line_data = [
|
||||
(0, 0,
|
||||
{
|
||||
'product_id': self.ref('product.product_product_4'),
|
||||
'name': 'product 4 that cost 100',
|
||||
'quantity': 1.0,
|
||||
'price_unit': 100.0,
|
||||
'account_id': invoice_line_account_id,
|
||||
}
|
||||
),
|
||||
(0, 0,
|
||||
{
|
||||
'product_id': self.ref('product.product_product_5'),
|
||||
'name': 'product 5 that cost 200',
|
||||
'quantity': 2.0,
|
||||
'price_unit': 200.0,
|
||||
'account_id': invoice_line_account_id,
|
||||
}
|
||||
)
|
||||
]
|
||||
|
||||
# Create an invoice dated 2 months before today
|
||||
invoice = AccountInvoice.create({
|
||||
'partner_id': self.ref('base.res_partner_2'),
|
||||
'account_id': invoice_account_id,
|
||||
'name': 'invoice test recurrent',
|
||||
'type': 'in_invoice',
|
||||
'reference_type': 'none',
|
||||
'date_invoice': datetime.today() + relativedelta(months=-2),
|
||||
'journal_id': purchase_journal.id,
|
||||
'is_recurrency_enabled': True,
|
||||
'recurrency_interval': 1,
|
||||
'recurrency_type': 'months',
|
||||
'invoice_line_ids': invoice_line_data
|
||||
})
|
||||
recurring_domain = [('type', '=', 'in_invoice'), ('state', '=', 'draft'), ('is_recurring_document', '=', True)]
|
||||
|
||||
# After executing cron, verify that no bill is auto generated if the recurrent bill is in `draft` state
|
||||
self.apply_vendor_cron()
|
||||
recurring_invoice_count = AccountInvoice.search_count(recurring_domain)
|
||||
self.assertEquals(recurring_invoice_count, 0, 'Recurring bills should not be generated when reference bill is still `draft`.')
|
||||
|
||||
# After validating bill, run cron and check that 2 recurring bill have been generated
|
||||
invoice.action_invoice_open() # Validate invoice
|
||||
self.apply_vendor_cron()
|
||||
recurring_invoice_count = previous_recurring_invoice_count = AccountInvoice.search_count(recurring_domain)
|
||||
self.assertEquals(recurring_invoice_count, 2, '2 recurring bills should be generated.')
|
||||
|
||||
# verify that bills aren't generated if reference bill is in `cancel` state
|
||||
purchase_journal.write({'update_posted': True}) # Allow to cancel the invoice
|
||||
inv2_data = {
|
||||
'name': 'invoice test recurrent 2',
|
||||
'date_invoice': datetime.today() + relativedelta(months=-2),
|
||||
'is_recurrency_enabled': True,
|
||||
'recurrency_interval': 1,
|
||||
'recurrency_type': 'months',
|
||||
}
|
||||
invoice2 = invoice.copy(default=inv2_data)
|
||||
invoice2.action_invoice_cancel() # Cancel the invoice
|
||||
self.apply_vendor_cron()
|
||||
recurring_invoice_count = AccountInvoice.search_count(recurring_domain)
|
||||
self.assertEquals(previous_recurring_invoice_count, recurring_invoice_count, 'Recurring bills should not be generated when reference bill is in `cancel` state.')
|
||||
|
||||
# verify that vendor bills are generated even when invoice is in `paid` state
|
||||
inv3_data = {
|
||||
'name': 'invoice test recurrent 3',
|
||||
'date_invoice': datetime.today() + relativedelta(months=-2),
|
||||
'is_recurrency_enabled': True,
|
||||
'recurrency_interval': 1,
|
||||
'recurrency_type': 'months',
|
||||
}
|
||||
|
||||
invoice3 = invoice.copy(default=inv3_data)
|
||||
invoice3.action_invoice_open() # Validate invoice
|
||||
Payment = self.env['account.payment']
|
||||
payment_vals = Payment.with_context(default_invoice_ids=[(4, invoice3.id, None)]).default_get(Payment._fields.keys())
|
||||
payment_vals.update({
|
||||
'payment_method_id': self.ref("account.account_payment_method_manual_out"),
|
||||
'journal_id': self.env['account.journal'].search([('type', '=', 'bank')], limit=1).id
|
||||
})
|
||||
Payment.create(payment_vals).action_validate_invoice_payment() # Register the payment
|
||||
self.apply_vendor_cron()
|
||||
recurring_invoice_count = AccountInvoice.search_count(recurring_domain)
|
||||
self.assertEquals(recurring_invoice_count, 4, '4 recurring bills should be generated.')
|
||||
@@ -335,12 +335,6 @@
|
||||
<field name="move_id" groups="account.group_account_user" attrs="{'invisible': [('move_id', '=', False)]}"/>
|
||||
<field name="date" domain="[('state', '=', 'draft'), ('company_id', '=', company_id)]" groups="account.group_account_user"/>
|
||||
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
|
||||
<field name="is_recurrency_enabled" string="Recurring Bills" help="Tick this box to generate recurring bills. The recurring bills will only be generated if this bill is validated." groups="account.group_allow_recurring" attrs="{'invisible': [('type', '!=', 'in_invoice')]}"/>
|
||||
<label for="recurrency_interval" attrs="{'invisible': [('is_recurrency_enabled', '=', False)]}" groups="account.group_allow_recurring"/>
|
||||
<div class="o_row" attrs="{'invisible': [('is_recurrency_enabled', '=', False)]}" groups="account.group_allow_recurring">
|
||||
<field name="recurrency_interval" help="Define the recurrency of the vendor bill." attrs="{'required': [('is_recurrency_enabled', '=', True)]}"/>
|
||||
<field name="recurrency_type" attrs="{'required': [('is_recurrency_enabled', '=', True)]}"/>
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
@@ -546,8 +540,6 @@
|
||||
<field name="date" string="Period"/>
|
||||
<separator/>
|
||||
<filter domain="[('user_id','=',uid)]" name="myinvoices" help="My Invoices"/>
|
||||
<filter domain="[('is_recurrency_enabled','=',True)]" name="is_recurrency_enabled" help="Bills Generating Recurring Bills" groups="account.group_allow_recurring" invisible="context.get('type') != 'in_invoice'"/>
|
||||
<filter domain="[('is_recurring_document','=',True)]" name="is_recurring_document" help="Bills Generated Automatically" groups="account.group_allow_recurring" invisible="context.get('type') != 'in_invoice'"/>
|
||||
<separator/>
|
||||
<filter string="My Activities" name="activities_my"
|
||||
domain="[('activity_ids.user_id', '=', uid)]"/>
|
||||
|
||||
@@ -446,20 +446,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Automated Entries</h2>
|
||||
<div class="row mt16 o_settings_container" id="recommended_apps">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="group_allow_recurring"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="group_allow_recurring"/>
|
||||
<div class="text-muted">
|
||||
Create recurring vendor bills
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div groups="account.group_account_user" class="col-xs-12 col-md-6 o_setting_box" id="asset_types" title="This allows you to manage the assets owned by a company or a person. It keeps track of the depreciation occurred on those assets, and creates account move for those depreciation lines.">
|
||||
<h2 groups="account.group_account_user">Automated Entries</h2>
|
||||
<div class="row mt16 o_settings_container" id="recommended_apps" groups="account.group_account_user">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" id="asset_types" title="This allows you to manage the assets owned by a company or a person. It keeps track of the depreciation occurred on those assets, and creates account move for those depreciation lines.">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_account_asset"/>
|
||||
</div>
|
||||
@@ -475,7 +464,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div groups="account.group_account_user" class="col-xs-12 col-md-6 o_setting_box" title="This allows you to manage the revenue recognition on selling products. It keeps track of the installments occurred on those revenue recognitions, and creates account moves for those installment lines.">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" title="This allows you to manage the revenue recognition on selling products. It keeps track of the installments occurred on those revenue recognitions, and creates account moves for those installment lines.">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_account_deferred_revenue" widget="upgrade_boolean"/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user