Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC

This commit is contained in:
CI Publish Bot
2026-11-01 22:54:30 +00:00
commit 26250aa580
2492 changed files with 664277 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
import logging
_logger = logging.getLogger(__name__)
# Стабильный внешний идентификатор профиля «Основной договор».
# По нему на профиль можно ссылаться из данных (в т.ч. демо) через ref,
# не зная реального id записи в БД.
MAIN_PROFILE_XMLID = 'l10n_ru_contract_account.contract_profile_main'
def _find_company_accounting(env, company):
"""Вернуть (journal_sale, receivable, payable, payment_term) для компании.
Счета берём ДЕФОЛТНЫЕ для контрагентов (property_account_receivable_id /
property_account_payable_id) — именно они попадают в строки инвойсов.
Так профиль договора будет согласован со счётом дебиторки инвойса и
проверка invoice_fields_check пройдёт. Любой элемент может быть пустым,
если план счетов ещё не настроен.
"""
journal = env['account.journal'].search(
[('type', '=', 'sale'), ('company_id', '=', company.id)], limit=1)
# Дефолтные счета контрагента в контексте компании.
partner_model = env['res.partner'].with_company(company)
receivable = partner_model.default_get(
['property_account_receivable_id']).get('property_account_receivable_id')
payable = partner_model.default_get(
['property_account_payable_id']).get('property_account_payable_id')
receivable = env['account.account'].browse(receivable) if receivable else \
env['account.account'].search(
[('account_type', '=', 'asset_receivable'),
('company_ids', 'in', company.id)], limit=1)
payable = env['account.account'].browse(payable) if payable else \
env['account.account'].search(
[('account_type', '=', 'liability_payable'),
('company_ids', 'in', company.id)], limit=1)
payment_term = env.ref('account.account_payment_term_immediate',
raise_if_not_found=False)
return journal, receivable, payable, payment_term
def ensure_main_profile(env, company=None):
"""Создать/дозаполнить профиль «Основной договор» и закрепить xmlid.
Возвращает запись профиля или None, если бухгалтерия ещё не настроена
(нет журнала/счетов) — тогда создание откладывается до момента, когда
план счетов будет загружен (напр. pre_init демо-данных).
"""
module, name = MAIN_PROFILE_XMLID.split('.')
profile = env.ref(MAIN_PROFILE_XMLID, raise_if_not_found=False)
if profile and profile.journal_id:
return profile # уже настроен — уважаем существующее
company = company or env.company or env['res.company'].search([], limit=1)
if not company:
return None
journal, receivable, payable, payment_term = _find_company_accounting(
env, company)
if not (journal and receivable and payable and payment_term):
_logger.info(
'l10n_ru_contract_account: профиль «Основной договор» пока не '
'создан — в компании %s не настроен план счетов. Будет создан '
'после настройки бухгалтерии.', company.display_name)
return None
vals = {
'name': 'Основной договор',
'journal_id': journal.id,
'receivable_account_id': receivable.id,
'payable_account_id': payable.id,
'payment_term_id': payment_term.id,
'max_receivable_id': 0.0,
}
if profile:
profile.write(vals)
else:
profile = env['contract.profile'].create(vals)
env['ir.model.data'].create({
'name': name,
'module': module,
'model': 'contract.profile',
'res_id': profile.id,
'noupdate': True,
})
_logger.info(
'l10n_ru_contract_account: профиль «Основной договор» готов '
'(компания %s, журнал %s).', company.display_name, journal.code)
return profile
def post_init_hook(env):
"""При установке модуля пытаемся создать профиль сразу.
В чистой базе журналов ещё нет — тогда профиль создаётся позже
(см. pre_init демо-данных или повторный вызов).
"""
ensure_main_profile(env)