mirror of
https://github.com/bringout/oca-ocb-accounting.git
synced 2026-04-22 14:21:59 +02:00
Initial commit: Accounting packages
This commit is contained in:
commit
4ef34c2317
2661 changed files with 1709616 additions and 0 deletions
|
|
@ -0,0 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_bank_statement
|
||||
from . import account_journal
|
||||
from . import account_move
|
||||
from . import account_payment
|
||||
from . import account_reconcile_model
|
||||
from . import res_company
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,145 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Classes defining the populate factory for Bank Statements and related models."""
|
||||
|
||||
from odoo import models, Command
|
||||
from odoo.tools import populate
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from functools import lru_cache
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountBankStatement(models.Model):
|
||||
"""Populate factory part for account.bank.statements."""
|
||||
|
||||
_inherit = "account.bank.statement"
|
||||
_populate_dependencies = ['account.bank.statement.line']
|
||||
|
||||
def _populate(self, size):
|
||||
"""
|
||||
Populate the bank statements with random lines.
|
||||
:param size:
|
||||
:return:
|
||||
"""
|
||||
rand = populate.Random('account_bank_statement+Populate')
|
||||
|
||||
read_group_res = self.env['account.bank.statement.line'].read_group(
|
||||
[('statement_id', '=', False)],
|
||||
['ids:array_agg(id)'],
|
||||
['journal_id'],
|
||||
)
|
||||
|
||||
bank_statement_vals_list = []
|
||||
for res in read_group_res:
|
||||
available_ids = res['ids']
|
||||
nb_ids = len(available_ids)
|
||||
while nb_ids > 0:
|
||||
batch_size = min(rand.randint(1, 19), nb_ids)
|
||||
nb_ids -= batch_size
|
||||
|
||||
# 50% to create a statement.
|
||||
statement_needed = bool(rand.randint(0, 1))
|
||||
if not statement_needed:
|
||||
continue
|
||||
|
||||
bank_statement_vals_list.append({
|
||||
'name': f"statement_{len(bank_statement_vals_list) + 1}",
|
||||
'journal_id': res['journal_id'][0],
|
||||
'line_ids': [Command.set(res['ids'])],
|
||||
})
|
||||
|
||||
return self.env['account.bank.statement'].create(bank_statement_vals_list)
|
||||
|
||||
|
||||
class AccountBankStatementLine(models.Model):
|
||||
"""Populate factory part for account.bank.statements.line."""
|
||||
|
||||
_inherit = "account.bank.statement.line"
|
||||
|
||||
_populate_sizes = {
|
||||
'small': 100,
|
||||
'medium': 10000,
|
||||
'large': 200000,
|
||||
}
|
||||
|
||||
_populate_dependencies = ['account.journal', 'res.company', 'res.partner']
|
||||
|
||||
def _populate_factories(self):
|
||||
@lru_cache()
|
||||
def search_partner_ids(company_id):
|
||||
"""Search all the partners that a company has access to.
|
||||
|
||||
This method is cached, only one search is done per company_id.
|
||||
:param company_id (int): the company to search partners for.
|
||||
:return (list<int>): the ids of partner the company has access to.
|
||||
"""
|
||||
return self.env['res.partner'].search([
|
||||
'|', ('company_id', '=', company_id), ('company_id', '=', False),
|
||||
('id', 'in', self.env.registry.populated_models['res.partner']),
|
||||
]).ids
|
||||
|
||||
def get_partner(random, values, **kwargs):
|
||||
"""Get a partner by selecting inside the list of partner a company has access to.
|
||||
|
||||
There is also a chance of having no partner set.
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return (int): an id of a partner accessible by the company of the statement.
|
||||
"""
|
||||
company_id = self.env['account.journal'].browse(values['journal_id']).company_id.id
|
||||
partner = search_partner_ids(company_id)
|
||||
return random.choices(partner + [False], [1/len(partner)] * len(partner) + [1])[0]
|
||||
|
||||
def get_amount(random, **kwargs):
|
||||
"""Get a random amount between -1000 and 1000.
|
||||
It is impossible to get a null amount. Because it would not be a valid statement line.
|
||||
:param random: seeded random number generator.
|
||||
:return (float): a number between -1000 and 1000.
|
||||
"""
|
||||
return random.uniform(-1000, 1000) or 1
|
||||
|
||||
def get_amount_currency(random, values, **kwargs):
|
||||
"""
|
||||
Get a random amount currency between one tenth of amount and 10 times amount with the same sign
|
||||
if foreign_currency_id is set
|
||||
|
||||
:param random: seeded random number generator.
|
||||
:return (float): a number between amount / 10 and amount * 10.
|
||||
"""
|
||||
return random.uniform(0.1 * values['amount'], 10 * values['amount']) if values['foreign_currency_id'] else 0
|
||||
|
||||
def get_currency(random, values, **kwargs):
|
||||
"""Get a random currency.
|
||||
|
||||
The currency has to be empty if it is the same as the currency of the line's journal's.
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return (int, bool): the id of an active currency or False if it is the same currency as
|
||||
the lines's journal's currency.
|
||||
"""
|
||||
journal = self.env['account.journal'].browse(values['journal_id'])
|
||||
currency = random.choice(self.env['res.currency'].search([('active', '=', True)]).ids)
|
||||
return currency if currency != (journal.currency_id or journal.company_id.currency_id).id else False
|
||||
|
||||
company_ids = self.env['res.company'].search([
|
||||
('chart_template_id', '!=', False),
|
||||
('id', 'in', self.env.registry.populated_models['res.company']),
|
||||
])
|
||||
if not company_ids:
|
||||
return []
|
||||
|
||||
journal_ids = self.env['account.journal'].search([
|
||||
('company_id', 'in', company_ids.ids),
|
||||
('type', 'in', ('cash', 'bank')),
|
||||
]).ids
|
||||
return [
|
||||
('journal_id', populate.iterate(journal_ids)),
|
||||
('partner_id', populate.compute(get_partner)),
|
||||
('date', populate.randdatetime(relative_before=relativedelta(years=-4))),
|
||||
('payment_ref', populate.constant('transaction_{values[date]}_{counter}')),
|
||||
('amount', populate.compute(get_amount)),
|
||||
('foreign_currency_id', populate.compute(get_currency)),
|
||||
('amount_currency', populate.compute(get_amount_currency)),
|
||||
]
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Classes defining the populate factory for Accounting Journals and related models."""
|
||||
import logging
|
||||
|
||||
from odoo import models
|
||||
from odoo.tools import populate
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountJournal(models.Model):
|
||||
"""Populate factory part for account.journal."""
|
||||
|
||||
_inherit = "account.journal"
|
||||
_populate_sizes = {
|
||||
'small': 10,
|
||||
'medium': 30,
|
||||
'large': 100,
|
||||
}
|
||||
|
||||
_populate_dependencies = ['res.company']
|
||||
|
||||
def _populate_factories(self):
|
||||
company_ids = self.env['res.company'].search([
|
||||
('chart_template_id', '!=', False),
|
||||
('id', 'in', self.env.registry.populated_models['res.company']),
|
||||
])
|
||||
if not company_ids:
|
||||
return []
|
||||
return [
|
||||
('company_id', populate.cartesian(company_ids.ids)),
|
||||
('type', populate.cartesian(['sale', 'purchase', 'cash', 'bank', 'general'])),
|
||||
('currency_id', populate.randomize(self.env['res.currency'].search([
|
||||
('active', '=', True),
|
||||
]).ids + [False])),
|
||||
('name', populate.constant("Journal {values[type]} {counter}")),
|
||||
('code', populate.constant("{values[type]:.2}{counter}")),
|
||||
]
|
||||
243
odoo-bringout-oca-ocb-account/account/populate/account_move.py
Normal file
243
odoo-bringout-oca-ocb-account/account/populate/account_move.py
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Classes defining the populate factory for Journal Entries, Invoices and related models."""
|
||||
from odoo import models, fields, Command
|
||||
from odoo.tools import populate
|
||||
|
||||
import logging
|
||||
import math
|
||||
from functools import lru_cache
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
"""Populate factory part for account.move.
|
||||
|
||||
Because of the complicated nature of the interraction of account.move and account.move.line,
|
||||
both models are actualy generated in the same factory.
|
||||
"""
|
||||
|
||||
_inherit = "account.move"
|
||||
|
||||
_populate_sizes = {
|
||||
'small': 1000,
|
||||
'medium': 10000,
|
||||
'large': 500000,
|
||||
}
|
||||
|
||||
_populate_dependencies = ['res.partner', 'account.journal', 'product.product']
|
||||
|
||||
def _populate_factories(self):
|
||||
@lru_cache()
|
||||
def search_accounts(company_id, types=None):
|
||||
"""Search all the accounts of a certain type for a company.
|
||||
|
||||
This method is cached, only one search is done per tuple(company_id, type).
|
||||
:param company_id (int): the company to search accounts for.
|
||||
:param type (str): the type to filter on. If not set, do not filter. Valid values are:
|
||||
payable, receivable, liquidity, other, False.
|
||||
:return (Model<account.account>): the recordset of accounts found.
|
||||
"""
|
||||
domain = [('company_id', '=', company_id), ('account_type', '!=', 'off_balance')]
|
||||
if types:
|
||||
domain += [('account_type', 'in', types)]
|
||||
return self.env['account.account'].search(domain)
|
||||
|
||||
@lru_cache()
|
||||
def search_journals(company_id, journal_type, currency_id):
|
||||
"""Search all the journal of a certain type for a company.
|
||||
|
||||
This method is cached, only one search is done per tuple(company_id, journal_type).
|
||||
:param company_id (int): the company to search journals for.
|
||||
:param journal_type (str): the journal type to filter on.
|
||||
Valid values are sale, purchase, cash, bank and general.
|
||||
:param currency_id (int): the currency to search journals for.
|
||||
:return (list<int>): the ids of the journals of a company and a certain type
|
||||
"""
|
||||
return self.env['account.journal'].search([
|
||||
('company_id', '=', company_id),
|
||||
('currency_id', 'in', (False, currency_id)),
|
||||
('type', '=', journal_type),
|
||||
]).ids
|
||||
|
||||
@lru_cache()
|
||||
def search_products(company_id):
|
||||
"""Search all the products a company has access to.
|
||||
|
||||
This method is cached, only one search is done per company_id.
|
||||
:param company_id (int): the company to search products for.
|
||||
:return (Model<product.product>): all the products te company has access to
|
||||
"""
|
||||
return self.env['product.product'].search([
|
||||
('company_id', 'in', (False, company_id)),
|
||||
('id', 'in', self.env.registry.populated_models['product.product']),
|
||||
])
|
||||
|
||||
@lru_cache()
|
||||
def search_partner_ids(company_id):
|
||||
"""Search all the partners that a company has access to.
|
||||
|
||||
This method is cached, only one search is done per company_id.
|
||||
:param company_id (int): the company to search partners for.
|
||||
:return (list<int>): the ids of partner the company has access to.
|
||||
"""
|
||||
return self.env['res.partner'].search([
|
||||
'|', ('company_id', '=', company_id), ('company_id', '=', False),
|
||||
('id', 'in', self.env.registry.populated_models['res.partner']),
|
||||
]).ids
|
||||
|
||||
def get_invoice_date(values, **kwargs):
|
||||
"""Get the invoice date date.
|
||||
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return (datetime.date, bool): the accounting date if it is an invoice (or similar) document
|
||||
or False otherwise.
|
||||
"""
|
||||
if values['move_type'] in self.get_invoice_types(include_receipts=True):
|
||||
return values['date']
|
||||
return False
|
||||
|
||||
def get_lines(random, values, **kwargs):
|
||||
"""Build the dictionary of account.move.line.
|
||||
|
||||
Generate lines depending on the move_type, company_id and currency_id.
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return list: list of ORM create commands for the field line_ids
|
||||
"""
|
||||
def get_entry_line(label, balance=None):
|
||||
account = random.choice(accounts)
|
||||
currency = account.currency_id != account.company_id.currency_id and account.currency_id or random.choice(currencies)
|
||||
if balance is None:
|
||||
balance = round(random.uniform(-10000, 10000))
|
||||
return Command.create({
|
||||
'name': 'label_%s' % label,
|
||||
'balance': balance,
|
||||
'account_id': account.id,
|
||||
'partner_id': partner_id,
|
||||
'currency_id': currency.id,
|
||||
'amount_currency': account.company_id.currency_id._convert(balance, currency, account.company_id, date),
|
||||
})
|
||||
|
||||
def get_invoice_line():
|
||||
return Command.create({
|
||||
'product_id': random.choice(products).id,
|
||||
'account_id': random.choice(accounts).id,
|
||||
'price_unit': round(random.uniform(0, 10000)),
|
||||
'quantity': round(random.uniform(0, 100)),
|
||||
})
|
||||
|
||||
move_type = values['move_type']
|
||||
date = values['date']
|
||||
company_id = values['company_id']
|
||||
partner_id = values['partner_id']
|
||||
|
||||
# Determine the right sets of accounts depending on the move_type
|
||||
if move_type in self.get_sale_types(include_receipts=True):
|
||||
accounts = search_accounts(company_id, ('income',))
|
||||
elif move_type in self.get_purchase_types(include_receipts=True):
|
||||
accounts = search_accounts(company_id, ('expense',))
|
||||
else:
|
||||
accounts = search_accounts(company_id)
|
||||
|
||||
products = search_products(company_id)
|
||||
|
||||
if move_type == 'entry':
|
||||
# Add a random number of lines (between 1 and 20)
|
||||
lines = [get_entry_line(
|
||||
label=i,
|
||||
) for i in range(random.randint(1, 20))]
|
||||
|
||||
# Add a last line containing the balance.
|
||||
# For invoices, etc., it will be on the receivable/payable account.
|
||||
lines += [get_entry_line(
|
||||
balance=-sum(vals['balance'] for _command, _id, vals in lines),
|
||||
label='balance',
|
||||
)]
|
||||
else:
|
||||
lines = [get_invoice_line() for _i in range(random.randint(1, 20))]
|
||||
|
||||
return lines
|
||||
|
||||
def get_journal(random, values, **kwargs):
|
||||
"""Get a random journal depending on the company and the move_type.
|
||||
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return (int): the id of the journal randomly selected
|
||||
"""
|
||||
move_type = values['move_type']
|
||||
company_id = values['company_id']
|
||||
currency_id = values['company_id']
|
||||
if move_type in self.get_sale_types(include_receipts=True):
|
||||
journal_type = 'sale'
|
||||
elif move_type in self.get_purchase_types(include_receipts=True):
|
||||
journal_type = 'purchase'
|
||||
else:
|
||||
journal_type = 'general'
|
||||
journal = search_journals(company_id, journal_type, currency_id)
|
||||
return random.choice(journal)
|
||||
|
||||
def get_partner(random, values, **kwargs):
|
||||
"""Get a random partner depending on the company and the move_type.
|
||||
|
||||
The first 3/5 of the available partners are used as customer
|
||||
The last 3/5 of the available partners are used as suppliers
|
||||
It means 1/5 is both customer/supplier
|
||||
-> Same proportions as in account.payment
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return (int, bool): the id of the partner randomly selected if it is an invoice document
|
||||
False if it is a Journal Entry.
|
||||
"""
|
||||
move_type = values['move_type']
|
||||
company_id = values['company_id']
|
||||
partner_ids = search_partner_ids(company_id)
|
||||
|
||||
if move_type in self.get_sale_types(include_receipts=True):
|
||||
return random.choice(partner_ids[:math.ceil(len(partner_ids)/5*2)])
|
||||
if move_type in self.get_purchase_types(include_receipts=True):
|
||||
return random.choice(partner_ids[math.floor(len(partner_ids)/5*2):])
|
||||
return False
|
||||
|
||||
company_ids = self.env['res.company'].search([
|
||||
('chart_template_id', '!=', False),
|
||||
('id', 'in', self.env.registry.populated_models['res.company']),
|
||||
])
|
||||
currencies = self.env['res.currency'].search([
|
||||
('active', '=', True),
|
||||
])
|
||||
|
||||
if not company_ids:
|
||||
return []
|
||||
return [
|
||||
('move_type', populate.randomize(
|
||||
['entry', 'in_invoice', 'out_invoice', 'in_refund', 'out_refund', 'in_receipt', 'out_receipt'],
|
||||
[0.2, 0.3, 0.3, 0.07, 0.07, 0.03, 0.03],
|
||||
)),
|
||||
('company_id', populate.randomize(company_ids.ids)),
|
||||
('currency_id', populate.randomize(currencies.ids)),
|
||||
('journal_id', populate.compute(get_journal)),
|
||||
('date', populate.randdatetime(relative_before=relativedelta(years=-4), relative_after=relativedelta(years=1))),
|
||||
('invoice_date', populate.compute(get_invoice_date)),
|
||||
('partner_id', populate.compute(get_partner)),
|
||||
('line_ids', populate.compute(get_lines)),
|
||||
]
|
||||
|
||||
def _populate(self, size):
|
||||
records = super()._populate(size)
|
||||
_logger.info('Posting Journal Entries')
|
||||
to_post = records.filtered(lambda r: r.date < fields.Date.today())
|
||||
to_post.action_post()
|
||||
|
||||
# TODO add some reconciliations. Not done initially because of perfs.
|
||||
# _logger.info('Registering Payments for Invoices and Bills')
|
||||
# random = populate.Random('account.move+register_payment')
|
||||
# for invoice in to_post:
|
||||
# if invoice.is_invoice() and random.uniform(0, 1) < 0.9: # 90% of invoices are at least partialy paid
|
||||
# payment_wizard = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=invoice.ids).create({})
|
||||
# if random.uniform(0, 1) > 0.9: # 90% of paid invoices have the exact amount, others vary a little
|
||||
# payment_wizard.amount *= random.uniform(0.5, 1.5)
|
||||
# payment_wizard._create_payments()
|
||||
return records
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Classes defining the populate factory for Payments and related models."""
|
||||
from odoo import models, fields
|
||||
from odoo.tools import populate
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import logging
|
||||
import math
|
||||
from functools import lru_cache
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountPayment(models.Model):
|
||||
"""Populate factory part for account.payment."""
|
||||
|
||||
_inherit = "account.payment"
|
||||
|
||||
_populate_sizes = {
|
||||
'small': 100,
|
||||
'medium': 5000,
|
||||
'large': 50000,
|
||||
}
|
||||
|
||||
_populate_dependencies = ['res.company', 'res.partner', 'account.journal']
|
||||
|
||||
def _populate_factories(self):
|
||||
@lru_cache()
|
||||
def search_partner_ids(company_id):
|
||||
"""Search all the partners that a company has access to.
|
||||
|
||||
This method is cached, only one search is done per company_id.
|
||||
:param company_id (int): the company to search partners for.
|
||||
:return (list<int>): the ids of partner the company has access to.
|
||||
"""
|
||||
return self.env['res.partner'].search([
|
||||
'|', ('company_id', '=', company_id), ('company_id', '=', False),
|
||||
('id', 'in', self.env.registry.populated_models['res.partner']),
|
||||
]).ids
|
||||
|
||||
@lru_cache()
|
||||
def search_journal_ids(company_id):
|
||||
"""Search all the journal of a certain type for a company.
|
||||
|
||||
This method is cached, only one search is done per company_id.
|
||||
:param company_id (int): the company to search journals for.
|
||||
:return (list<int>): the ids of the bank and cash journals of a company
|
||||
"""
|
||||
return self.env['account.journal'].search([
|
||||
('company_id', '=', company_id),
|
||||
('type', 'in', ('cash', 'bank')),
|
||||
]).ids
|
||||
|
||||
@lru_cache()
|
||||
def search_payment_method_line_ids(payment_type, journal):
|
||||
"""Search all the payment methods of a certain type.
|
||||
|
||||
This method is cached, only one search is done per type.
|
||||
:param payment_type (str): the type of payment method. Valid values are customer and supplier.
|
||||
:param journal (int): the journal of the payment method.
|
||||
:return list<int>: list of ids of payment methods of the selected type
|
||||
"""
|
||||
need_bank_account = self._get_method_codes_needing_bank_account()
|
||||
other_blacklist = ['sdd', 'bacs_dd']
|
||||
return self.env['account.payment.method.line'].search([
|
||||
('journal_id', '=', journal),
|
||||
('payment_method_id.payment_type', '=', payment_type),
|
||||
('code', 'not in', need_bank_account + other_blacklist),
|
||||
]).ids
|
||||
|
||||
def get_partner(random, values, **kwargs):
|
||||
"""Get a random partner depending on the company and the partner_type.
|
||||
|
||||
The first 3/5 of the available partners are used as customer
|
||||
The last 3/5 of the available partners are used as suppliers
|
||||
It means 1/5 is both customer/supplier
|
||||
-> Same proportions as in account.move
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return (int): the id of the partner randomly selected.
|
||||
"""
|
||||
partner_type = values['partner_type']
|
||||
company_id = values['company_id']
|
||||
partner_ids = search_partner_ids(company_id)
|
||||
if partner_type == 'customer':
|
||||
return random.choice(partner_ids[:math.ceil(len(partner_ids)/5*2)])
|
||||
else:
|
||||
return random.choice(partner_ids[math.floor(len(partner_ids)/5*2):])
|
||||
|
||||
def get_journal(random, values, **kwargs):
|
||||
"""Get a random bank or cash journal depending on the company.
|
||||
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return (int): the id of the journal randomly selected
|
||||
"""
|
||||
return random.choice(search_journal_ids(values['company_id']))
|
||||
|
||||
def get_payment_method_line(random, values, **kwargs):
|
||||
"""Get the payment method depending on the payment type.
|
||||
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
"""
|
||||
return random.choice(search_payment_method_line_ids(values['payment_type'], values['journal_id']))
|
||||
|
||||
company_ids = self.env['res.company'].search([
|
||||
('chart_template_id', '!=', False),
|
||||
('id', 'in', self.env.registry.populated_models['res.company']),
|
||||
])
|
||||
if not company_ids:
|
||||
return []
|
||||
return [
|
||||
('company_id', populate.cartesian(company_ids.ids)),
|
||||
('payment_type', populate.cartesian(['inbound', 'outbound'])),
|
||||
('partner_type', populate.cartesian(['customer', 'supplier'])),
|
||||
('journal_id', populate.compute(get_journal)),
|
||||
('payment_method_line_id', populate.compute(get_payment_method_line)),
|
||||
('partner_id', populate.compute(get_partner)),
|
||||
('amount', populate.randfloat(0, 1000)),
|
||||
('date', populate.randdatetime(relative_before=relativedelta(years=-4))),
|
||||
]
|
||||
|
||||
def _populate(self, size):
|
||||
records = super()._populate(size)
|
||||
_logger.info('Validating Payments')
|
||||
records.move_id.filtered(lambda r: r.date < fields.Date.today()).action_post()
|
||||
return records
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Classes defining the populate factory for Bank Statements and related models."""
|
||||
from odoo import models
|
||||
from odoo.tools import populate
|
||||
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountReconcileModel(models.Model):
|
||||
"""Populate factory part for account.reconcile.model."""
|
||||
|
||||
_inherit = "account.reconcile.model"
|
||||
|
||||
_populate_sizes = {
|
||||
'small': 5,
|
||||
'medium': 100,
|
||||
'large': 1000,
|
||||
}
|
||||
|
||||
_populate_dependencies = ['res.company']
|
||||
|
||||
def _populate_factories(self):
|
||||
def get_name(counter, **kwargs):
|
||||
return 'model_%s' % counter
|
||||
|
||||
company_ids = self.env['res.company'].search([
|
||||
('chart_template_id', '!=', False),
|
||||
('id', 'in', self.env.registry.populated_models['res.company']),
|
||||
])
|
||||
if not company_ids:
|
||||
return []
|
||||
return [
|
||||
('company_id', populate.cartesian(company_ids.ids)),
|
||||
('rule_type', populate.cartesian(['writeoff_button', 'writeoff_suggestion'])),
|
||||
# ('auto_reconcile', populate.cartesian([True, False], [0.1, 0.9])),
|
||||
('name', populate.compute(get_name)),
|
||||
]
|
||||
|
||||
|
||||
class AccountReconcileModelLine(models.Model):
|
||||
"""Populate factory part for account.reconcile.model.line."""
|
||||
|
||||
_inherit = "account.reconcile.model.line"
|
||||
|
||||
_populate_sizes = {
|
||||
'small': 10,
|
||||
'medium': 200,
|
||||
'large': 2000,
|
||||
}
|
||||
|
||||
_populate_dependencies = ['account.reconcile.model']
|
||||
|
||||
def _populate_factories(self):
|
||||
def search_account_ids(company_id, type=None, group=None):
|
||||
"""Search all the accounts of a certain type and group for a company.
|
||||
|
||||
This method is cached, only one search is done per tuple(company_id, type, group).
|
||||
:param company_id (int): the company to search accounts for.
|
||||
:param type (str): the type to filter on. If not set, do not filter. Valid values are:
|
||||
payable, receivable, liquidity, other, False.
|
||||
:param group (str): the group to filter on. If not set, do not filter. Valid values are:
|
||||
asset, liability, equity, off_balance, False.
|
||||
:return (Model<account.account>): the recordset of accounts found.
|
||||
"""
|
||||
domain = [('company_id', '=', company_id)]
|
||||
if type:
|
||||
domain += [('account_type', '=', type)]
|
||||
if group:
|
||||
domain += [('internal_group', '=', group)]
|
||||
return self.env['account.account'].search(domain)
|
||||
|
||||
def get_amount(random, values, **kwargs):
|
||||
"""Get an amount dending on the amount_type.
|
||||
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return (int, str):
|
||||
If amount_type is fixed, a random number between 1 and 1000
|
||||
If amount type is percentage, a random number between 1 and 100
|
||||
Else, amount_type is regex, a random regex out of 2
|
||||
"""
|
||||
if values['amount_type'] == 'fixed':
|
||||
return '%s' % random.randint(1, 1000)
|
||||
elif values['amount_type'] == 'percentage':
|
||||
return '%s' % random.randint(1, 100)
|
||||
else:
|
||||
return random.choice([r'^invoice \d+ (\d+)$', r'xd no-(\d+)'])
|
||||
|
||||
def get_account(random, values, **kwargs):
|
||||
"""Get a random account depending on the company.
|
||||
|
||||
:param random: seeded random number generator.
|
||||
:param values (dict): the values already selected for the record.
|
||||
:return (int): the id of the account randomly selected
|
||||
"""
|
||||
company_id = self.env['account.reconcile.model'].browse(values['model_id']).company_id.id
|
||||
return random.choice(search_account_ids(company_id).ids)
|
||||
|
||||
company_ids = self.env['res.company'].search([
|
||||
('chart_template_id', '!=', False),
|
||||
('id', 'in', self.env.registry.populated_models['res.company']),
|
||||
])
|
||||
if not company_ids:
|
||||
return []
|
||||
return [
|
||||
('model_id', populate.cartesian(self.env.registry.populated_models['account.reconcile.model'])),
|
||||
('amount_type', populate.randomize(['fixed', 'percentage', 'regex'])),
|
||||
('amount_string', populate.compute(get_amount)),
|
||||
('account_id', populate.compute(get_account)),
|
||||
]
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Classes extending the populate factory for Companies and related models.
|
||||
|
||||
Only adding specificities of basic accounting applications.
|
||||
"""
|
||||
from odoo import models, _
|
||||
from odoo.tools import populate
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
import logging
|
||||
from functools import lru_cache
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
"""Populate factory part for the accountings applications of res.company."""
|
||||
|
||||
_inherit = "res.company"
|
||||
|
||||
def _populate(self, size):
|
||||
@lru_cache()
|
||||
def search_coa_ids(currency_id):
|
||||
return self.env['account.chart.template'].search([('currency_id', '=', currency_id)])
|
||||
|
||||
records = super()._populate(size)
|
||||
_logger.info('Loading Chart Template')
|
||||
default_chart_templates = self.env['account.chart.template'].search([], limit=1)
|
||||
if not default_chart_templates:
|
||||
# TODO install l10n_generic_coa ?
|
||||
return records
|
||||
random = populate.Random('res.company+chart_template_selector')
|
||||
|
||||
# Load the a chart of accounts matching the currency of the company for the 3 first created companies
|
||||
# We are loading an existing CoA and not populating it because:
|
||||
# * it reflects best real use cases.
|
||||
# * it allows checking reports by localization
|
||||
# * the config is complete with try_loading(), no need to adapt when the model changes
|
||||
# * it is way easier :-)
|
||||
# We are loading only for 3 companies because:
|
||||
# * It takes a few hundreds of a second to create account.move records in batch.
|
||||
# Because we want to have a lot of entries for at least one company (in order to test
|
||||
# reports, functions and widgets performances for instance), we can't afford to do it for
|
||||
# a lot of companies.
|
||||
# * it would be useless to have entries for all the companies, we can already do everything with
|
||||
# entries in only a few (but multiple) companies.
|
||||
# Note that we can still populate some new records on top of the CoA if it makes sense,
|
||||
# like account.journal for instance.
|
||||
for company in records[:3]:
|
||||
chart_templates_cur = search_coa_ids(company.currency_id.id) or default_chart_templates
|
||||
random.choice(chart_templates_cur).with_company(company.id).try_loading()
|
||||
return records
|
||||
Loading…
Add table
Add a link
Reference in a new issue