Public release from ruodoo-project: 19.0 - 2026-05-31 21:19:12 UTC

This commit is contained in:
CI Publish Bot
2026-05-31 21:19:21 +00:00
commit aa4214c195
1213 changed files with 183945 additions and 0 deletions

View File

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

View File

@ -0,0 +1,19 @@
{
'name': 'Account Bank Statement 1C Import',
'category': 'Accounting',
'version': '19.0.0.1',
'author': 'MK.Lab',
'website': 'https://inf-centre.ru/',
'depends': [
'account',
'l10n_ru_doc',
],
'data': [
'security/ir.model.access.csv',
'wizard/invoice_import_wizard.xml',
'views/account_journal_wizard_action.xml',
'views/account_journal_dashboard_inherit.xml',
'views/account_journal_settings.xml',
],
'installable': True,
}

View File

@ -0,0 +1,160 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_bank_statement_1c_import
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 17.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-18 22:00+0000\n"
"PO-Revision-Date: 2024-03-18 22:00+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_bank_statement_1c_import
#: model:ir.model,name:account_bank_statement_1c_import.model_account_bank_statement
msgid "Bank Statement"
msgstr "Банковская выписка"
#. module: account_bank_statement_1c_import
#: model_terms:ir.ui.view,arch_db:account_bank_statement_1c_import.view_invoice_import_wizard_form
msgid "Cancel"
msgstr "Отменить"
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_invoice_import_wizard__create_uid
msgid "Created by"
msgstr ""
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_invoice_import_wizard__create_date
msgid "Created on"
msgstr ""
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_account_bank_statement__date_from
msgid "Date From"
msgstr ""
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_invoice_import_wizard__display_name
msgid "Display Name"
msgstr ""
#. module: account_bank_statement_1c_import
#. odoo-python
#: code:addons/account_bank_statement_1c_import/wizard/invoice_import_wizard.py:0
#, python-format
msgid "Error Import: %s"
msgstr ""
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_invoice_import_wizard__file
msgid "File"
msgstr "Файл"
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_invoice_import_wizard__file_name
msgid "File Name"
msgstr ""
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_invoice_import_wizard__id
msgid "ID"
msgstr ""
#. module: account_bank_statement_1c_import
#: model_terms:ir.ui.view,arch_db:account_bank_statement_1c_import.view_invoice_import_wizard_form
msgid "Import"
msgstr "Импортировать"
#. module: account_bank_statement_1c_import
#: model:ir.actions.act_window,name:account_bank_statement_1c_import.action_invoice_import_wizard
#: model:ir.model,name:account_bank_statement_1c_import.model_invoice_import_wizard
#: model:ir.ui.menu,name:account_bank_statement_1c_import.menu_invoice_import
#: model_terms:ir.ui.view,arch_db:account_bank_statement_1c_import.account_journal_dashboard_inherit
#: model_terms:ir.ui.view,arch_db:account_bank_statement_1c_import.view_invoice_import_wizard_form
msgid "Import Invoice"
msgstr "Импортировать выписку"
#. module: account_bank_statement_1c_import
#: model:ir.actions.server,name:account_bank_statement_1c_import.action_import_invoice_wizard
msgid "Import Invoice Wizard"
msgstr "Импорт выписки"
#. module: account_bank_statement_1c_import
#: model:ir.model,name:account_bank_statement_1c_import.model_account_journal
msgid "Journal"
msgstr "Журнал"
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_invoice_import_wizard__write_uid
msgid "Last Updated by"
msgstr ""
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_invoice_import_wizard__write_date
msgid "Last Updated on"
msgstr ""
#. module: account_bank_statement_1c_import
#. odoo-python
#: code:addons/account_bank_statement_1c_import/wizard/invoice_import_wizard.py:0
#, python-format
msgid "Only TXT files are allowed."
msgstr "Разрешены только файлы TXT"
#. module: account_bank_statement_1c_import
#. odoo-python
#: code:addons/account_bank_statement_1c_import/wizard/invoice_import_wizard.py:0
#, python-format
msgid "Please upload the file."
msgstr "Пожалуйста, загрузите файл"
#. module: account_bank_statement_1c_import
#. odoo-python
#: code:addons/account_bank_statement_1c_import/wizard/invoice_import_wizard.py:0
#, python-format
msgid "Statement not found for journal {} on date {}."
msgstr "Не найдено выписки по журналу {} и дате {}"
#. module: account_bank_statement_1c_import
#. odoo-python
#: code:addons/account_bank_statement_1c_import/wizard/invoice_import_wizard.py:0
#, python-format
msgid "Suitable journal not found."
msgstr ""
"Подходящий журнал не найден. Проверьте стоит ли галочка 'Использовать в "
"банковской выписке' в журнале"
#. module: account_bank_statement_1c_import
#: model:ir.model.fields,field_description:account_bank_statement_1c_import.field_account_journal__use_in_bank_statement
msgid "Use in Bank Statement"
msgstr "Использовать в банковской выписке"
#. module: account_bank_statement_1c_import
#. odoo-python
#: code:addons/account_bank_statement_1c_import/wizard/invoice_import_wizard.py:0
#, python-format
msgid "inn your company not found."
msgstr ""
"ИНН вашей компании не найден в файле. Пожалуйста, проверьте корректность "
"файла."
#. module: account_bank_statement_1c_import
#. odoo-python
#: code:addons/account_bank_statement_1c_import/wizard/invoice_import_wizard.py:0
#, python-format
msgid "Выписка успешно импортирована."
msgstr ""
#. module: account_bank_statement_1c_import
#. odoo-python
#: code:addons/account_bank_statement_1c_import/wizard/invoice_import_wizard.py:0
#, python-format
msgid "Импорт завершен"
msgstr ""

View File

@ -0,0 +1,2 @@
from . import account_journal
from . import account_bank_statement

View File

@ -0,0 +1,6 @@
from odoo import models, fields
class AccountBankStatement(models.Model):
_inherit = 'account.bank.statement'
date_from = fields.Date(string="Date From")

View File

@ -0,0 +1,6 @@
from odoo import models, fields
class AccountJournal(models.Model):
_inherit = 'account.journal'
use_in_bank_statement = fields.Boolean(string="Use in Bank Statement")

View File

@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_invoice_import_wizard,access_invoice_import_wizard,model_invoice_import_wizard,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_invoice_import_wizard access_invoice_import_wizard model_invoice_import_wizard base.group_user 1 1 1 1

View File

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

View File

@ -0,0 +1,293 @@
"""
Tests for Parser_1C (account_bank_statement_1c_import).
Validates: Requirements 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.9
"""
import base64
from odoo.exceptions import UserError
from odoo.tests.common import TransactionCase
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
COMPANY_INN = "7700000001"
COMPANY_KPP = "770001001"
PARTNER_INN = "7700000002"
PARTNER_KPP = "770001002"
VALID_TXT_TEMPLATE = """\
1CClientBankExchange
ВерсияФормата=1.03
Кодировка=Windows
Отправитель=Бухгалтерия предприятия
ДатаСоздания=01.01.2024
ВремяСоздания=12:00:00
ДатаНачала=01.01.2024
ДатаКонца=31.01.2024
РасчСчет=40702810000000000001
СекцияРасчСчет
ДатаНачала=01.01.2024
ДатаКонца=31.01.2024
РасчСчет=40702810000000000001
НачальныйОстаток=10000.00
ВсегоПоступило=5000.00
ВсегоСписано=3000.00
КонечныйОстаток=12000.00
КонецРасчСчет
{transactions}КонецФайла
"""
TRANSACTION_PAYER = """\
СекцияДокумент=Платежное поручение
Номер=1
Дата=15.01.2024
Сумма=1000.00
ПлательщикСчет=40702810000000000001
ДатаСписано=15.01.2024
ПлательщикИНН={company_inn}
ПлательщикКПП={company_kpp}
Плательщик=ООО Наша Компания
Плательщик1=ООО Наша Компания
ПлательщикРасчСчет=40702810000000000001
ПлательщикБанк1=Банк Плательщика
ПлательщикБИК=044525001
ПлательщикКорсчет=30101810400000000001
ПолучательСчет=40702810000000000002
ПолучательИНН={partner_inn}
ПолучательКПП={partner_kpp}
Получатель=ООО Контрагент
Получатель1=ООО Контрагент
ПолучательРасчСчет=40702810000000000002
ПолучательБанк1=Банк Получателя
ПолучательБИК=044525002
ПолучательКорсчет=30101810400000000002
НазначениеПлатежа=Оплата по договору №1
КонецДокумента
"""
TRANSACTION_RECIPIENT = """\
СекцияДокумент=Платежное поручение
Номер=2
Дата=16.01.2024
Сумма=2000.00
ПлательщикСчет=40702810000000000002
ДатаПоступило=16.01.2024
ПлательщикИНН={partner_inn}
ПлательщикКПП={partner_kpp}
Плательщик=ООО Контрагент
Плательщик1=ООО Контрагент
ПлательщикРасчСчет=40702810000000000002
ПлательщикБанк1=Банк Плательщика
ПлательщикБИК=044525002
ПлательщикКорсчет=30101810400000000002
ПолучательСчет=40702810000000000001
ПолучательИНН={company_inn}
ПолучательКПП={company_kpp}
Получатель=ООО Наша Компания
Получатель1=ООО Наша Компания
ПолучательРасчСчет=40702810000000000001
ПолучательБанк1=Банк Получателя
ПолучательБИК=044525001
ПолучательКорсчет=30101810400000000001
НазначениеПлатежа=Поступление по договору №2
КонецДокумента
"""
TRANSACTION_UNKNOWN_INN = """\
СекцияДокумент=Платежное поручение
Номер=3
Дата=17.01.2024
Сумма=500.00
ПлательщикСчет=40702810000000000003
ДатаСписано=17.01.2024
ПлательщикИНН=9999999999
ПлательщикКПП=999999999
Плательщик=ООО Чужая Компания
Плательщик1=ООО Чужая Компания
ПлательщикРасчСчет=40702810000000000003
ПлательщикБанк1=Чужой Банк
ПлательщикБИК=044525003
ПлательщикКорсчет=30101810400000000003
ПолучательСчет=40702810000000000004
ПолучательИНН=8888888888
ПолучательКПП=888888888
Получатель=ООО Другая Компания
Получатель1=ООО Другая Компания
ПолучательРасчСчет=40702810000000000004
ПолучательБанк1=Другой Банк
ПолучательБИК=044525004
ПолучательКорсчет=30101810400000000004
НазначениеПлатежа=Транзакция без нашей компании
КонецДокумента
"""
def _encode(text):
"""Encode text to base64 as cp1251 (as the wizard expects)."""
return base64.b64encode(text.encode('cp1251'))
def _make_txt(transactions=""):
return VALID_TXT_TEMPLATE.format(transactions=transactions)
def _payer_tx():
return TRANSACTION_PAYER.format(
company_inn=COMPANY_INN, company_kpp=COMPANY_KPP,
partner_inn=PARTNER_INN, partner_kpp=PARTNER_KPP,
)
def _recipient_tx():
return TRANSACTION_RECIPIENT.format(
company_inn=COMPANY_INN, company_kpp=COMPANY_KPP,
partner_inn=PARTNER_INN, partner_kpp=PARTNER_KPP,
)
def _unknown_inn_tx():
return TRANSACTION_UNKNOWN_INN
# ---------------------------------------------------------------------------
# Fixtures / setUp helpers
# ---------------------------------------------------------------------------
class _Base(TransactionCase):
"""Common setUp: company VAT, bank journal with use_in_bank_statement."""
def setUp(self):
super().setUp()
# Set company VAT so the parser can match INN
self.env.company.write({'vat': COMPANY_INN})
# Create (or find) a bank journal with use_in_bank_statement=True
self.journal = self.env['account.journal'].search(
[('type', '=', 'bank'), ('use_in_bank_statement', '=', True)],
limit=1,
)
if not self.journal:
self.journal = self.env['account.journal'].create({
'name': 'Test Bank Journal',
'type': 'bank',
'code': 'TBNK',
'use_in_bank_statement': True,
})
def _wizard(self, file_content_bytes, file_name='statement.txt'):
"""Create an InvoiceImportWizard record."""
return self.env['invoice.import.wizard'].create({
'file': base64.b64encode(file_content_bytes),
'file_name': file_name,
})
# ---------------------------------------------------------------------------
# TestParser1CBasic
# ---------------------------------------------------------------------------
class TestParser1CBasic(_Base):
"""Validates: Requirements 2.1, 2.2, 2.3"""
def test_valid_txt_parses_without_exception(self):
"""Req 2.1 — correct TXT file is parsed without exceptions."""
content = _make_txt().encode('cp1251')
wizard = self._wizard(content, 'statement.txt')
# action_import_invoice should not raise
wizard.action_import_invoice()
def test_wrong_extension_raises_user_error(self):
"""Req 2.2 — non-.txt extension raises UserError."""
content = _make_txt().encode('cp1251')
wizard = self._wizard(content, 'statement.csv')
with self.assertRaises(UserError):
wizard.action_import_invoice()
def test_no_file_raises_user_error(self):
"""Req 2.3 — missing file raises UserError."""
wizard = self.env['invoice.import.wizard'].create({
'file': False,
'file_name': 'statement.txt',
})
with self.assertRaises(UserError):
wizard.action_import_invoice()
# ---------------------------------------------------------------------------
# TestParser1CLines
# ---------------------------------------------------------------------------
class TestParser1CLines(_Base):
"""Validates: Requirements 2.4, 2.5, 2.6"""
def _import_and_get_lines(self, transactions_text):
content = _make_txt(transactions_text).encode('cp1251')
wizard = self._wizard(content, 'statement.txt')
wizard.action_import_invoice()
return self.env['account.bank.statement.line'].search([], order='id desc')
def test_company_as_payer_creates_negative_amount(self):
"""Req 2.4 — company INN as payer → negative amount line."""
lines = self._import_and_get_lines(_payer_tx())
payer_lines = lines.filtered(lambda l: l.payment_ref == '1')
self.assertTrue(payer_lines, "Expected a statement line with payment_ref='1'")
self.assertLess(payer_lines[0].amount, 0, "Amount should be negative when company is payer")
def test_company_as_recipient_creates_positive_amount(self):
"""Req 2.5 — company INN as recipient → positive amount line."""
lines = self._import_and_get_lines(_recipient_tx())
recipient_lines = lines.filtered(lambda l: l.payment_ref == '2')
self.assertTrue(recipient_lines, "Expected a statement line with payment_ref='2'")
self.assertGreater(recipient_lines[0].amount, 0, "Amount should be positive when company is recipient")
def test_duplicate_line_is_skipped(self):
"""Req 2.6 — importing the same transaction twice does not create a duplicate."""
tx = _payer_tx()
content = _make_txt(tx).encode('cp1251')
# First import
self._wizard(content, 'statement.txt').action_import_invoice()
count_after_first = self.env['account.bank.statement.line'].search_count(
[('payment_ref', '=', '1')]
)
# Second import of the same file
self._wizard(content, 'statement.txt').action_import_invoice()
count_after_second = self.env['account.bank.statement.line'].search_count(
[('payment_ref', '=', '1')]
)
self.assertEqual(count_after_first, count_after_second,
"Duplicate transaction should be skipped on second import")
# ---------------------------------------------------------------------------
# TestParser1CPartner
# ---------------------------------------------------------------------------
class TestParser1CPartner(_Base):
"""Validates: Requirements 2.7, 2.9"""
def test_unknown_inn_kpp_creates_new_partner(self):
"""Req 2.7 — unknown INN/KPP → new partner of type 'company' is created."""
# Ensure partner does not exist
self.env['res.partner'].search([('vat', '=', PARTNER_INN)]).unlink()
content = _make_txt(_payer_tx()).encode('cp1251')
self._wizard(content, 'statement.txt').action_import_invoice()
partner = self.env['res.partner'].search([('vat', '=', PARTNER_INN)], limit=1)
self.assertTrue(partner, "A new partner should have been created")
self.assertEqual(partner.company_type, 'company',
"New partner should have company_type='company'")
def test_unknown_company_inn_in_transaction_raises_user_error(self):
"""Req 2.9 — company INN not found as payer or recipient → UserError."""
content = _make_txt(_unknown_inn_tx()).encode('cp1251')
wizard = self._wizard(content, 'statement.txt')
with self.assertRaises(UserError):
wizard.action_import_invoice()

View File

@ -0,0 +1,16 @@
<odoo>
<record id="account_journal_dashboard_inherit" model="ir.ui.view">
<field name="name">account.dashboard.inherit</field>
<field name="model">account.journal</field>
<field name="inherit_id" ref="account.account_journal_dashboard_kanban_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='bank_cash_buttons']" position="inside">
<button type="action"
name="%(account_bank_statement_1c_import.action_import_invoice_wizard)d"
class="btn btn-primary">
Импортировать выписку
</button>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,14 @@
<odoo>
<data>
<record id="view_account_journal_form_inherit" model="ir.ui.view">
<field name="name">account.journal.form.inherit</field>
<field name="model">account.journal</field>
<field name="inherit_id" ref="account.view_account_journal_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='type']" position="after">
<field name="use_in_bank_statement"/>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,17 @@
<odoo>
<record id="account_bank_statement_1c_import.action_import_invoice_wizard" model="ir.actions.server">
<field name="name">Import Invoice Wizard</field>
<field name="model_id" ref="model_invoice_import_wizard"/>
<field name="binding_model_id" ref="account.model_account_journal"/>
<field name="state">code</field>
<field name="code">
action = {
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'invoice.import.wizard',
'target': 'new',
'name': 'Import Invoice'
}
</field>
</record>
</odoo>

View File

@ -0,0 +1,7 @@
<odoo>
<menuitem id="menu_invoice_import"
name="Import Invoice"
action="action_invoice_import_wizard"
parent="account.menu_finance"
sequence="5"/>
</odoo>

View File

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

View File

@ -0,0 +1,202 @@
from odoo import models, fields, _
from odoo.exceptions import UserError
import base64
import dateutil.parser
# import logging
# _logger = logging.getLogger(__name__)
class InvoiceImportWizard(models.TransientModel):
_name = 'invoice.import.wizard'
_description = 'Import Invoice'
file = fields.Binary(string='File', required=True)
file_name = fields.Char(string='File Name')
def action_import_invoice(self):
# _logger.info("Начало импорта файла выписки")
if not self.file:
# _logger.error("Файл не загружен")
raise UserError(_("Please upload the file."))
if not self.file_name.endswith('.txt'):
# _logger.error("Неподдерживаемый формат файла: %s", self.file_name)
raise UserError(_("Only TXT files are allowed."))
file_content = base64.b64decode(self.file).decode('cp1251')
journal = self.env['account.journal'].search([('type', '=', 'bank'), ('use_in_bank_statement', '=', True)],
limit=1)
if not journal:
raise UserError(_("Suitable journal not found."))
try:
sections = file_content.split('СекцияДокумент')
invoice_sections = sections[0]
transaction_sections = sections[1:]
invoices = invoice_sections.split('СекцияРасчСчет')[1:]
for invoice in invoices:
statement_data = self.parse_statement_data(invoice)
existing_statement = self.env['account.bank.statement'].search([
('date_from', '=', dateutil.parser.parse(statement_data.get('ДатаНачала', '').strip(), dayfirst=True).date()),
('name', '=', statement_data.get('РасчСчет', '').strip()),
], limit=1)
if not existing_statement:
statement = self.create_statement(journal, statement_data)
# _logger.info("Выписка создана успешно: %s", statement.name)
self.create_statement_lines(journal, transaction_sections)
except Exception as e:
# _logger.error("Ошибка при импорте файла: %s", e)
raise UserError(_("Error Import: %s" % str(e)))
message_title = _("Импорт завершен")
message_content = _("Выписка успешно импортирована.")
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': message_title,
'message': message_content,
},
}
def parse_statement_data(self, section):
lines = section.strip().split('\n')
statement_data = {}
for line in lines:
if '=' in line:
key, value = line.split('=', 1)
statement_data[key] = value
return statement_data
def create_statement(self, journal, statement_data):
statement_vals = {
'journal_id': journal.id,
'name': statement_data.get('РасчСчет', '').strip(),
'balance_start': float(statement_data.get('НачальныйОстаток', '0.0').strip()),
'balance_end_real': float(statement_data.get('КонечныйОстаток', '0.0').strip()),
'date_from': dateutil.parser.parse(statement_data.get('ДатаНачала', '').strip(), dayfirst=True).date(),
}
return self.env['account.bank.statement'].sudo().create(statement_vals)
def create_statement_lines(self, journal, sections):
for section in sections:
if section.strip():
lines = section.strip().split('\n')
transaction = self.parse_transaction_data(lines)
if transaction:
# _logger.info("<==================================>")
# _logger.info("Создание строки выписки для транзакции №%s", transaction.get('Номер').strip())
self.create_line(journal, transaction)
# _logger.info("Строка выписки для транзакции №%s создана успешно", transaction.get('Номер').strip())
def parse_transaction_data(self, lines):
transaction = {}
for line in lines:
if '=' in line:
key, value = line.split('=', 1)
transaction[key] = value
return transaction
def create_line(self, journal, transaction):
my_company_inn = journal.company_id.vat
transaction_date = dateutil.parser.parse(transaction.get('Дата', '').strip(), dayfirst=True).date()
statement = self.env['account.bank.statement'].search([
('date_from', '=', transaction_date),
], limit=1)
if not statement:
raise UserError(_("Statement not found for journal {} on date {}.").format(journal.name, transaction_date))
amount = float(transaction.get('Сумма', '0.0').strip())
if transaction.get('ПлательщикИНН').strip() == my_company_inn:
amount = -amount
partner_inn = transaction.get('ПолучательИНН').strip()
partner_kpp = transaction.get('ПолучательКПП').strip()
partner_name = transaction.get('Получатель').strip()
partner_account = transaction.get('ПолучательСчет').strip()
bank_bik = transaction.get('ПолучательБИК').strip()
bank_account = transaction.get('ПолучательКорсчет').strip()
bank_name = transaction.get('ПолучательБанк1').strip()
elif transaction.get('ПолучательИНН').strip() == my_company_inn:
# Если наша компания - получатель, значит это доход
partner_inn = transaction.get('ПлательщикИНН').strip()
partner_kpp = transaction.get('ПлательщикКПП').strip()
partner_name = transaction.get('Плательщик').strip()
partner_account = transaction.get('ПлательщикСчет').strip()
bank_bik = transaction.get('ПлательщикБИК').strip()
bank_account = transaction.get('ПлательщикКорсчет').strip()
bank_name = transaction.get('ПлательщикБанк1').strip()
else:
error_message = "ИНН вашей компании не найден в транзакции. Запись не создана."
error_message += "Журнал: {}, Дата транзакции: {}. ".format(journal.name, transaction_date)
error_message += "Плательщик: {}, ИНН плательщика: {}. ".format(transaction.get('Плательщик1', 'не указан').strip(),
transaction.get('ПлательщикИНН',
'не указан').strip())
error_message += "Получатель: {}, ИНН получателя: {}. ".format(transaction.get('Получатель1', 'не указан').strip(),
transaction.get('ПолучательИНН',
'не указан').strip())
raise UserError(_(f"{error_message}"))
existing_line = self.env['account.bank.statement.line'].search([
('date', '=', transaction_date),
('amount', '=', amount),
('narration', '=', transaction.get('НазначениеПлатежа', '').strip()),
('payment_ref', '=', transaction.get('Номер').strip()),
], limit=1)
if existing_line:
# _logger.info("Строка выписки уже существует: %s", existing_line.id)
return None
partner = self.env['res.partner'].search([('vat', '=', partner_inn), ('kpp', '=', partner_kpp)], limit=1)
if not partner:
# _logger.info("Создание нового партнера: ИНН %s, КПП %s", partner_inn, partner_kpp)
partner = self.env['res.partner'].create({
'name': partner_name,
'vat': partner_inn,
'kpp': partner_kpp,
'company_type': 'company',
})
bank = self.env['res.bank'].search([('bic', '=', bank_bik), ('corr_acc', '=', bank_account)], limit=1)
if not bank:
# _logger.info("Создание нового банка: БИК %s", bank_bik)
bank = self.env['res.bank'].create({
'name': bank_name,
'bic': bank_bik,
'corr_acc': bank_account,
})
partner_bank_account = self.env['res.partner.bank'].search(
[('acc_number', '=', partner_account), ('partner_id', '=', partner.id)], limit=1)
if not partner_bank_account:
# _logger.info("Создание нового банковского счета для партнера %s", partner.name)
partner_bank_account = self.env['res.partner.bank'].create({
'acc_number': partner_account,
'bank_id': bank.id,
'partner_id': partner.id,
})
line_vals = {
'journal_id': journal.id,
'partner_bank_id': partner_bank_account.id,
'partner_id': partner.id,
'statement_id': statement.id,
'company_id': journal.company_id.id,
'date': transaction_date,
'amount': amount,
'narration': transaction.get('НазначениеПлатежа', '').strip(),
'payment_ref': transaction.get('Номер').strip(),
}
self.env['account.bank.statement.line'].sudo().create(line_vals)

View File

@ -0,0 +1,25 @@
<odoo>
<record id="view_invoice_import_wizard_form" model="ir.ui.view">
<field name="name">invoice.import.wizard.form</field>
<field name="model">invoice.import.wizard</field>
<field name="arch" type="xml">
<form string="Import Invoice">
<group>
<field name="file" filename="file_name"/>
<field name="file_name" invisible="1"/>
</group>
<footer>
<button string="Import" name="action_import_invoice" type="object" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_invoice_import_wizard" model="ir.actions.act_window">
<field name="name">Import Invoice</field>
<field name="res_model">invoice.import.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>