forked from Rudoo/L10n_ru
Российская локализация для v18
This commit is contained in:
parent
e07335deaa
commit
2c894fe74b
14
l10n_ru_act_rev/README.md
Normal file
14
l10n_ru_act_rev/README.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Российская локализация - Акт сверки
|
||||
name: l10n_ru_act_rev
|
||||
|
||||
|
||||
## Описание
|
||||
Добавление печатной формы акт сверки из контактов, с помощью которой можно легко отслеживать дебеторские и кредиторские проводки с клиентами.
|
||||
|
||||
### Для печати:
|
||||
1. Выбираем меню Контакты - карточку конкретного партнера - Действия - "Печать акт сверки";
|
||||
2. В визарде выбираем:
|
||||
2.1. Компанию (для которой нужна сверка с выбранным контактом);
|
||||
2.2. Период сверки;
|
||||
2.3. Цель (один из режимом: все проведенные проводки или все проводки, включая черновики);
|
||||
3. Кнопка "Печать"
|
4
l10n_ru_act_rev/__init__.py
Normal file
4
l10n_ru_act_rev/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from . import models
|
||||
from . import report
|
||||
from . import wizard
|
||||
from . import controllers
|
45
l10n_ru_act_rev/__manifest__.py
Normal file
45
l10n_ru_act_rev/__manifest__.py
Normal file
@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': "Российская локализация - Акт сверки",
|
||||
|
||||
'summary': """
|
||||
Добавление отчета акт сверки""",
|
||||
|
||||
'description': """
|
||||
Добавление формы акт сверки, находящегося в контактах, с помощью которого можно легко отслеживать дебеторские и кредиторские проводки с клиентами.
|
||||
|
||||
Для печати:
|
||||
1. Выбираем меню Контакты - конкретного партнера - Действия - "Печать акт сверки";
|
||||
2. В визарде выбираем:
|
||||
2.1. Компанию (для которой нужна сверка с выбранным контактом);
|
||||
2.2. Период сверки;
|
||||
2.3. Цель (один из режимом: все проведенные проводки или все проводки, включая черновики);
|
||||
3. Кнопка "Печать"
|
||||
|
||||
""",
|
||||
|
||||
'author': "MK.Lab",
|
||||
'website': "https://www.inf-centre.ru/",
|
||||
|
||||
'category': 'Uncategorized',
|
||||
'version': '0.1',
|
||||
|
||||
# any module necessary for this one to work correctly
|
||||
"depends": ["account", "portal", "website", 'contacts', "l10n_ru_doc", 'l10n_ru_contract', 'l10n_ru_base'],
|
||||
"data": [
|
||||
"security/ir.model.access.csv",
|
||||
"wizard/general_ledger_wizard_view.xml",
|
||||
"report/layouts.xml",
|
||||
"report/general_ledger.xml",
|
||||
"views/account_account_views.xml",
|
||||
"views/report_general_ledger.xml",
|
||||
"views/portal_templates.xml",
|
||||
],
|
||||
"installable": True,
|
||||
"application": True,
|
||||
"auto_install": False,
|
||||
# only loaded in demonstration mode
|
||||
'demo': [
|
||||
'demo/demo.xml',
|
||||
],
|
||||
}
|
3
l10n_ru_act_rev/controllers/__init__.py
Normal file
3
l10n_ru_act_rev/controllers/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import controllers
|
98
l10n_ru_act_rev/controllers/controllers.py
Normal file
98
l10n_ru_act_rev/controllers/controllers.py
Normal file
@ -0,0 +1,98 @@
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
from datetime import datetime, date
|
||||
import werkzeug
|
||||
|
||||
|
||||
class ActRevise(http.Controller):
|
||||
|
||||
@http.route(['/my/act_revise/<string:act>'], type='http', auth="public", website=True)
|
||||
def print_report(self):
|
||||
partner = request.env.user.partner_id.parent_id.id
|
||||
partner_name = request.env.user.partner_id.parent_id.name
|
||||
if not partner:
|
||||
partner = request.env.user.partner_id.id
|
||||
partner_name = request.env.user.partner_id.name
|
||||
company = request.env.user.company_id.id
|
||||
# company_name = request.env.user.company_id.name
|
||||
# today = date.today()
|
||||
# d1 = today.strftime("%d.%m.%y")
|
||||
#
|
||||
# new_url=str('AC ' + company +' - ' + partner + ' ' + d1)
|
||||
# if request.httprequest.full_path == '/my/act_revise/a?':
|
||||
# return werkzeug.utils.redirect('/my/act_revise/%s' % new_url)
|
||||
|
||||
wizard_data = {
|
||||
"target_move": "posted",
|
||||
"hide_account_at_0": True,
|
||||
"foreign_currency": True,
|
||||
"company_id": company,
|
||||
"partner_ids": [partner],
|
||||
"show_cost_center": True,
|
||||
"centralize": True
|
||||
}
|
||||
wizard_record = request.env['general.ledger.act_revise.wizard'].sudo().create(wizard_data)
|
||||
|
||||
action_read = request.env.ref('l10n_ru_act_rev.action_general_ledger_wizard').sudo().read()
|
||||
if action_read:
|
||||
action = action_read[0]
|
||||
action['res_id'] = wizard_record.id
|
||||
action['context'] = dict(request.env.context)
|
||||
return request.redirect('/web#action=' + str(action['id']) + '&id=' + str(wizard_record.id) + '&view_type=form')
|
||||
else:
|
||||
return request.make_response("Error: Action not found.",[('Content-Type', 'text/plain')],400)
|
||||
|
||||
# @http.route(['/my/act_revise/<string:act>'], type='http', auth="public", website=True)
|
||||
# def print_report(self):
|
||||
# partner = request.env.user.partner_id.parent_id.id
|
||||
# partner_name = request.env.user.partner_id.parent_id.name
|
||||
# if not partner:
|
||||
# partner = request.env.user.partner_id.id
|
||||
# partner_name = request.env.user.partner_id.name
|
||||
# company = request.env.user.company_id.id
|
||||
# company_name = request.env.user.company_id.name
|
||||
# today = date.today()
|
||||
# d1 = today.strftime("%d.%m.%y")
|
||||
# # new_url = str('Акт Сверки ' + d1 + ' ' + company_name + '_' + partner_name)
|
||||
# # new_url=str('AC ' + company +' - ' + partner + ' ' + d1)
|
||||
# # if request.httprequest.full_path == '/my/act_revise/a?':
|
||||
# # return werkzeug.utils.redirect('/my/act_revise/%s' % new_url)
|
||||
# wizard_data = {"target_move": "posted",
|
||||
# "hide_account_at_0": True,
|
||||
# "foreign_currency": True,
|
||||
# #"show_analytic_tags": True,
|
||||
# "company_id": company,
|
||||
# "partner_ids": [partner],
|
||||
# #"show_partner_details": True,
|
||||
# "show_cost_center": True,
|
||||
# "centralize": True}
|
||||
# t = request.env['general.ledger.act_revise.wizard'].sudo().create(wizard_data)
|
||||
# data = t._prepare_report_general_ledger()
|
||||
# name = t.get_report_filename()
|
||||
# report_name = name.encode('cp1251')
|
||||
# pdf, _ = request.env['ir.actions.report']._render_qweb_pdf(
|
||||
# 'act_revise.action_print_report_general_ledger_qweb', res_ids=t.id, data=data)
|
||||
# pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ]
|
||||
# return request.make_response(pdf, headers=pdfhttpheaders)
|
||||
|
||||
@http.route(['/my/act_revise_contact/<string:act>'], type='http', auth="public", website=True)
|
||||
def print_report_contact(self, date_to, date_from, target_move, company, partner):
|
||||
partner_id = int(partner) or 'default_partner_value'
|
||||
company_id = int(company)
|
||||
wizard_data = {"date_to": date_to,
|
||||
"date_from": date_from,
|
||||
"target_move": target_move,
|
||||
"hide_account_at_0": True,
|
||||
"foreign_currency": True,
|
||||
#"show_analytic_tags": True,
|
||||
"company_id": company_id,
|
||||
"partner_ids": [partner_id],
|
||||
#"show_partner_details": True,
|
||||
"show_cost_center": True,
|
||||
"centralize": True}
|
||||
t = request.env['general.ledger.act_revise.wizard'].sudo().create(wizard_data)
|
||||
data = t._prepare_report_general_ledger()
|
||||
pdf, _ = request.env['ir.actions.report']._render_qweb_pdf(
|
||||
'l10n_ru_act_rev.action_print_report_general_ledger_qweb', res_ids=t.id, data=data)
|
||||
pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ]
|
||||
return request.make_response(pdf, headers=pdfhttpheaders)
|
30
l10n_ru_act_rev/demo/demo.xml
Normal file
30
l10n_ru_act_rev/demo/demo.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<odoo>
|
||||
<data>
|
||||
<!--
|
||||
<record id="object0" model="act_revise.act_revise">
|
||||
<field name="name">Object 0</field>
|
||||
<field name="value">0</field>
|
||||
</record>
|
||||
|
||||
<record id="object1" model="act_revise.act_revise">
|
||||
<field name="name">Object 1</field>
|
||||
<field name="value">10</field>
|
||||
</record>
|
||||
|
||||
<record id="object2" model="act_revise.act_revise">
|
||||
<field name="name">Object 2</field>
|
||||
<field name="value">20</field>
|
||||
</record>
|
||||
|
||||
<record id="object3" model="act_revise.act_revise">
|
||||
<field name="name">Object 3</field>
|
||||
<field name="value">30</field>
|
||||
</record>
|
||||
|
||||
<record id="object4" model="act_revise.act_revise">
|
||||
<field name="name">Object 4</field>
|
||||
<field name="value">40</field>
|
||||
</record>
|
||||
-->
|
||||
</data>
|
||||
</odoo>
|
2
l10n_ru_act_rev/models/__init__.py
Normal file
2
l10n_ru_act_rev/models/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from . import account_account
|
||||
from . import ir_actions_report
|
7
l10n_ru_act_rev/models/account_account.py
Normal file
7
l10n_ru_act_rev/models/account_account.py
Normal file
@ -0,0 +1,7 @@
|
||||
from odoo import fields, models, _
|
||||
|
||||
|
||||
class AccountAccount(models.Model):
|
||||
_inherit = "account.account"
|
||||
|
||||
centralized = fields.Boolean(_("Централизованно"))
|
10
l10n_ru_act_rev/models/ir_actions_report.py
Normal file
10
l10n_ru_act_rev/models/ir_actions_report.py
Normal file
@ -0,0 +1,10 @@
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class IrActionsReport(models.Model):
|
||||
_inherit = "ir.actions.report"
|
||||
|
||||
@api.model
|
||||
def _prepare_account_financial_report_context(self, data):
|
||||
lang = data and data.get("account_financial_report_lang") or ""
|
||||
return dict(self.env.context or {}, lang=lang) if lang else False
|
2
l10n_ru_act_rev/report/__init__.py
Normal file
2
l10n_ru_act_rev/report/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from . import general_ledger
|
||||
|
1060
l10n_ru_act_rev/report/general_ledger.py
Normal file
1060
l10n_ru_act_rev/report/general_ledger.py
Normal file
File diff suppressed because it is too large
Load Diff
286
l10n_ru_act_rev/report/general_ledger.xml
Normal file
286
l10n_ru_act_rev/report/general_ledger.xml
Normal file
@ -0,0 +1,286 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<template id="l10n_ru_act_rev.general_ledger">
|
||||
<t t-call="l10n_ru_act_rev.html_container">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<t t-call="l10n_ru_act_rev.internal_layout">
|
||||
<t t-call="l10n_ru_act_rev.report_general_ledger_base" />
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
<template id="l10n_ru_act_rev.report_general_ledger_base">
|
||||
<t t-set="foreign_currency" t-value="foreign_currency" />
|
||||
<t t-set="filter_partner_ids" t-value="filter_partner_ids" />
|
||||
<div class="page">
|
||||
<style type="text/css">
|
||||
body { background: #ffffff; margin: 0; font-family: Arial; font-size: 10pt; font-style: normal; text-align: center;}
|
||||
tbody, table, tr, td, th { border: none;}
|
||||
tr.R0{ height: 15px; border: border: none; }
|
||||
tr.R0 td.R0t{text-align: center; font-family: Tahoma; font-size: 14pt; font-weight: bold;}
|
||||
tr.R0 td.R0j{text-align: justify }
|
||||
tr.R0 td.R0l{text-align: left}
|
||||
tr.R0 td.R0lb{font-weight: bold; text-align: left}
|
||||
tr.R0 td.R0lbt{font-weight: bold; text-align: left; border-top: #000000 1px solid;}
|
||||
tr.R0 td.R0lbox{text-align: left; border-left: #000000 1px solid; border-top: #000000 1px solid;
|
||||
border-right: #000000 1px solid; border-bottom: #000000 1px solid; vertical-align: middle;}
|
||||
tr.R0 td.R0cbox{text-align: center; border-left: #000000 1px solid; border-top: #000000 1px solid;
|
||||
border-right: #000000 1px solid; border-bottom: #000000 1px solid; vertical-align: middle;}
|
||||
tr.R0 td.R0lbbox{font-weight: bold; text-align: left; border-left: #000000 1px solid; border-top:
|
||||
#000000 1px solid; border-right: #000000 1px solid; border-bottom: #000000 1px solid; vertical-align: middle;}
|
||||
tr.R0 td.R0rbox{text-align: right; border-left: #000000 1px solid; border-top: #000000 1px solid;
|
||||
border-right: #000000 1px solid; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0rbbox{font-weight: bold; text-align: right; border-left: #000000 1px solid; border-top:
|
||||
#000000 1px solid; border-right: #000000 1px solid; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.Rcbox{text-align: center; border-left: #000000 1px solid; border-top: #000000 1px solid;
|
||||
border-right: #000000 1px solid; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0cbbox{font-weight: bold; text-align: center; border-left: #000000 1px solid; border-top:
|
||||
#000000 1px solid; border-right: #000000 1px solid; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0lboxf{background: #FFFFCC;text-align: left; border-left: #000000 1px solid; border-top:
|
||||
#000000 1px solid; border-right: #000000 1px solid; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0lbboxf{background: #FFFFCC;font-weight: bold; text-align: left; border-left: #000000 1px
|
||||
solid; border-top: #000000 1px solid; border-right: #000000 1px solid; border-bottom: #000000 1px
|
||||
solid;}
|
||||
tr.R0 td.R0rboxf{background: #FFFFCC;text-align: right; border-left: #000000 1px solid; border-top:
|
||||
#000000 1px solid; border-right: #000000 1px solid; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0rbboxf{background: #FFFFCC;font-weight: bold; text-align: right; border-left: #000000 1px
|
||||
solid; border-top: #000000 1px solid; border-right: #000000 1px solid; border-bottom: #000000 1px
|
||||
solid;}
|
||||
tr.R0 td.Rcboxf{background: #FFFFCC;text-align: center; border-left: #000000 1px solid; border-top:
|
||||
#000000 1px solid; border-right: #000000 1px solid; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0cbboxf{background: #FFFFCC;font-weight: bold; text-align: center; border-left: #000000 1px
|
||||
solid; border-top: #000000 1px solid; border-right: #000000 1px solid; border-bottom: #000000 1px
|
||||
solid; vertical-align: middle;}
|
||||
tr.R0 td.R0print span img { position: absolute; width: 140px; top: -80px; left: -350px; }
|
||||
tr.R0 td.R0print { overflow: visible; }
|
||||
tr.R0 td.R0print span { position: relative; }
|
||||
tr.R0 td.R0print{ text-align: left; }
|
||||
tr.R0 td.R0fas { font-family: Arial; font-size: 7pt; font-style: normal; text-align: right; border-bottom: #000000 1px solid; }
|
||||
tr.R0 td.R0fas { overflow: visible; }
|
||||
tr.R0 td.R0fas span { position: relative; }
|
||||
tr.R0 td.R0fas span img { position: absolute; width: 100px; top: -25px; left: 200px;}
|
||||
</style>
|
||||
<t t-set="lines" t-value='[]' />
|
||||
<t t-set="total_debit_init_all" t-value='0.0'/>
|
||||
<t t-set="total_credit_init_all" t-value='0.0'/>
|
||||
|
||||
<t t-foreach="general_ledger" t-as="account">
|
||||
<t t-if="'list_grouped' in account">
|
||||
<t t-foreach="account['list_grouped']" t-as="group_item">
|
||||
|
||||
<t
|
||||
t-set="misc_domain"
|
||||
t-value="[('account_id', '=', account['id']),('date', '<', date_from)]"
|
||||
/>
|
||||
<t
|
||||
t-set="misc_grouped_domain"
|
||||
t-value="[('partner_id', '=', group_item['id'])]"
|
||||
t-if="'partners' in account"
|
||||
/>
|
||||
<t t-set="misc_grouped_domain" t-value="[]" t-else="" />
|
||||
<t t-set="debit_domain" t-value="[('debit', '<>', 0)]" />
|
||||
<span
|
||||
t-att-domain="misc_domain+debit_domain+misc_grouped_domain"
|
||||
res-model="account.move.line"
|
||||
>
|
||||
<t t-set="total_debit_init" t-value="group_item['init_bal']['debit']" />
|
||||
<t t-set="total_debit_init_all" t-value='total_debit_init_all+total_debit_init'/>
|
||||
</span>
|
||||
<t t-set="credit_domain" t-value="[('credit', '<>', 0)]" />
|
||||
<span
|
||||
t-att-domain="misc_domain+credit_domain+misc_grouped_domain"
|
||||
res-model="account.move.line"
|
||||
>
|
||||
<t t-set="total_credit_init" t-value="group_item['init_bal']['credit']" />
|
||||
<t t-set="total_credit_init_all" t-value='total_credit_init_all+total_credit_init'/>
|
||||
</span>
|
||||
<t t-set="lines" t-value='lines+group_item["move_lines"]' />
|
||||
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
<t t-set="lines" t-value='o.sorted_lines(lines)'/>
|
||||
<t t-set="total_debit" t-value='0.0' />
|
||||
<t t-set="total_credit" t-value='0.0' />
|
||||
<TABLE CELLSPACING="0">
|
||||
<COL WIDTH="12%"/>
|
||||
<COL WIDTH="14%"/>
|
||||
<COL WIDTH="12%"/>
|
||||
<COL WIDTH="12%"/>
|
||||
<COL WIDTH="12%"/>
|
||||
<COL WIDTH="12%"/>
|
||||
<COL WIDTH="14%"/>
|
||||
<COL WIDTH="12%"/>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8" CLASS="R0t">Акт сверки</td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8">взаимных расчетов за период: <t t-esc="o.get_data_format(date_from) or ''"/> - <t t-esc="o.get_data_format(date_to) or ''"/></td>
|
||||
</tr>
|
||||
<t t-set="pid" t-value="o.partner_ids[0].parent_id or o.partner_ids[0]"/>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8">между: <t t-esc="company_name"/> и <t t-esc="pid.name"/></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8"><t t-if="o.get_contract()">по договору №<t t-esc="o.get_contract().name"/> от <t t-esc="o.get_contract().date_start"/></t></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8" CLASS="R0lb"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8" CLASS="R0lb"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8" CLASS="R0j">Мы, нижеподписавшиеся, <t t-esc="company_name"/> с одной стороны, и <t t-esc="pid.name"/>, с другой стороны, составили данный акт сверки в том, что, состояние взаимных расчетов по данным учета следующее:</td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8" CLASS="R0lb"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="4" CLASS="R0lbox">По данным <t t-esc="company_name"/>, руб</td>
|
||||
<td colspan="4" CLASS="R0lbox">По данным <t t-esc="pid.name"/>, руб</td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td CLASS="R0cbbox">Дата</td>
|
||||
<td CLASS="R0cbbox">Документ</td>
|
||||
<td CLASS="R0cbbox">Дебет</td>
|
||||
<td CLASS="R0cbbox">Кредит</td>
|
||||
<td CLASS="R0cbbox">Дата</td>
|
||||
<td CLASS="R0cbbox">Документ</td>
|
||||
<td CLASS="R0cbbox">Дебет</td>
|
||||
<td CLASS="R0cbbox">Кредит</td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<t
|
||||
t-set="misc_domain"
|
||||
t-value="[('account_id', '=', account['id']),('date', '<', date_from)]"
|
||||
/>
|
||||
<t
|
||||
t-set="misc_grouped_domain"
|
||||
t-value="[('partner_id', '=', group_item['id'])]"
|
||||
t-if="'partners' in account"
|
||||
/>
|
||||
<t t-set="misc_grouped_domain" t-value="[]" t-else="" />
|
||||
<td colspan="2" CLASS="R0lbox">Сальдо начальное</td>
|
||||
<td CLASS="R0cbox"><span t-esc="'%0.2f'%(total_debit_init_all)"/></td>
|
||||
<td CLASS="R0cbox"><span t-esc="'%0.2f'%(total_credit_init_all)"/></td>
|
||||
<td colspan="2" CLASS="R0lbox">Сальдо начальное</td>
|
||||
<td CLASS="R0cbox"></td>
|
||||
<td CLASS="R0cbox"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0" t-foreach="lines" t-as="line">
|
||||
<t t-set="total_debit" t-value="total_debit+line['debit']" />
|
||||
<t t-set="total_credit" t-value="total_credit+line['credit']" />
|
||||
<td CLASS="R0cbox"><t t-esc="o.get_data_format(line['date']) or ''"/></td>
|
||||
<td CLASS="R0lbox"><t t-raw="line['entry']"/></td>
|
||||
<td CLASS="R0cbox"><t t-raw="'%0.2f'%(line['debit'])"/></td>
|
||||
<td CLASS="R0cbox"><t t-raw="'%0.2f'%(line['credit'])"/></td>
|
||||
<td CLASS="R0cbox"></td>
|
||||
<td CLASS="R0lbox"></td>
|
||||
<td CLASS="R0cbox"></td>
|
||||
<td CLASS="R0cbox"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="2" CLASS="R0lbbox">Обороты за период</td>
|
||||
<td CLASS="R0cbbox"><t t-raw="'%0.2f'%(total_debit)"/>
|
||||
</td>
|
||||
<td CLASS="R0cbbox"><t t-raw="'%0.2f'%(total_credit)"/>
|
||||
</td>
|
||||
<td colspan="2" CLASS="R0lbbox">Обороты за период</td>
|
||||
<td CLASS="R0cbbox"></td>
|
||||
<td CLASS="R0cbbox"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="2" CLASS="R0lbbox">Сальдо конечное</td>
|
||||
<td CLASS="R0cbbox"><t t-raw="'%0.2f'%(total_debit_init_all+total_debit)"/></td>
|
||||
<td CLASS="R0cbbox"><t t-raw="'%0.2f'%(total_credit_init_all+total_credit)"/></td>
|
||||
<td colspan="2" CLASS="R0lbbox">Сальдо конечное</td>
|
||||
<td CLASS="R0cbbox"></td>
|
||||
<td CLASS="R0cbbox"></td>
|
||||
</tr>
|
||||
<t t-set="total_balance_fin" t-value='(total_debit_init_all+total_debit)-(total_credit_init_all+total_credit)'/>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8" CLASS="R0lb"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="4" CLASS="R0l">По данным <t t-esc="company_name"/></td>
|
||||
<td colspan="4" CLASS="R0l">По данным <t t-esc="pid.name"/></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="4" CLASS="R0lb">на <t t-esc="o.get_data_format(date_to) or ''"/> задолженность в пользу <t t-if="total_balance_fin>=0"><t t-esc="company_name"/></t><t t-else=""><t t-esc="pid.name"/></t> <t t-esc="'%0.2f'%(abs(total_balance_fin))"/> руб. (<t t-esc="o.rubles(abs(total_balance_fin)) or ''"/>)"
|
||||
</td>
|
||||
<td colspan="4" CLASS="R0lb">на <t t-esc="o.get_data_format(date_to) or ''"/> задолженность в пользу <t t-if="total_balance_fin>=0"><t t-esc="company_name"/></t><t t-else=""><t t-esc="pid.name"/></t> <t t-esc="'%0.2f'%(abs(total_balance_fin))"/> руб. (<t t-esc="o.rubles(abs(total_balance_fin)) or ''"/>)"
|
||||
</td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8" CLASS="R0lb"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="4" CLASS="R0l">От <t t-esc="company_name"/></td>
|
||||
<td colspan="4" CLASS="R0l">От <t t-esc="pid.name"/></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8" CLASS="R0lb"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="4" CLASS="R0lb"><t t-esc="o.company_id.chief_id.function or ''"/></td>
|
||||
<td colspan="4" CLASS="R0lb">Директор</td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="8" CLASS="R0lb"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="2" CLASS="R0fas"><SPAN><t t-raw="o.company_id.print_facsimile and o.img(o.company_id.chief_id.facsimile) or ''"/></SPAN></td>
|
||||
<td colspan="2" CLASS="R0lb"><t t-esc="o.initials(o.company_id.chief_id.name) or ''"/></td>
|
||||
<td colspan="2" CLASS="R0lb"></td>
|
||||
<td colspan="2" CLASS="R0lb"></td>
|
||||
</tr>
|
||||
<tr CLASS="R0">
|
||||
<td colspan="2" CLASS="R0lbt">М.П.</td>
|
||||
<td colspan="2" CLASS="R0print"><SPAN><t t-raw="o.company_id.print_stamp and (o.company_id.print_anywhere or context.get('mark_invoice_as_sent', False)) and o.img(o.company_id.stamp) or ''"/></SPAN></td>
|
||||
<td colspan="2" CLASS="R0lbt">М.П.</td>
|
||||
<td colspan="2" CLASS="R0lb"></td>
|
||||
</tr>
|
||||
</TABLE>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- <report-->
|
||||
<!-- id="action_print_report_general_ledger_qweb"-->
|
||||
<!-- model="general.ledger.report.wizard"-->
|
||||
<!-- string="Акт сверки"-->
|
||||
<!-- report_type="qweb-pdf"-->
|
||||
<!-- menu="False"-->
|
||||
<!-- name="act_revise.general_ledger"-->
|
||||
<!-- file="act_revise.general_ledger"-->
|
||||
<!-- print_report_name=" 'Акт сверки - %s' %s (object.get_report_filename()) or ''"-->
|
||||
<!-- />-->
|
||||
<record id="action_print_report_general_ledger_qweb" model="ir.actions.report">
|
||||
<field name="name">Акт сверки</field>
|
||||
<field name="model">general.ledger.act_revise.wizard</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">l10n_ru_act_rev.general_ledger</field>
|
||||
<field name="report_file">l10n_ru_act_rev.general_ledger</field>
|
||||
<field name="print_report_name">'Акт сверки - %s' % (object.get_report_filename() or '')</field>
|
||||
<field name="binding_model_id" ref="model_general_ledger_act_revise_wizard"/>
|
||||
</record>
|
||||
|
||||
<record id="report_qweb_paperformat" model="report.paperformat">
|
||||
<field name="name">Account financial report qweb paperformat</field>
|
||||
<field name="default" eval="True" />
|
||||
<field name="format">custom</field>
|
||||
<field name="page_height">297</field>
|
||||
<field name="page_width">210</field>
|
||||
<field name="orientation">Landscape</field>
|
||||
<field name="margin_top">12</field>
|
||||
<field name="margin_bottom">8</field>
|
||||
<field name="margin_left">5</field>
|
||||
<field name="margin_right">5</field>
|
||||
<field name="header_line" eval="False" />
|
||||
<field name="header_spacing">10</field>
|
||||
<field name="dpi">110</field>
|
||||
</record>
|
||||
<record id="action_print_report_general_ledger_qweb" model="ir.actions.report">
|
||||
<field name="paperformat_id" ref="report_qweb_paperformat" />
|
||||
</record>
|
||||
</odoo>
|
34
l10n_ru_act_rev/report/layouts.xml
Normal file
34
l10n_ru_act_rev/report/layouts.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<template id="l10n_ru_act_rev.html_container">
|
||||
<t t-set="body_classname" t-value="'container'" />
|
||||
<t t-call="web.report_layout">
|
||||
<t t-out="0" />
|
||||
</t>
|
||||
</template>
|
||||
<template id="l10n_ru_act_rev.internal_layout">
|
||||
<div class="article o_account_financial_reports_page">
|
||||
<t t-out="0" />
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="row">
|
||||
<div class="col-6 custom_footer">
|
||||
<span
|
||||
t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 text-right custom_footer">
|
||||
<ul class="list-inline">
|
||||
<li class="list-inline-item">
|
||||
<span class="page" />
|
||||
</li>
|
||||
<li class="list-inline-item">/</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="topage" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</odoo>
|
3
l10n_ru_act_rev/security/ir.model.access.csv
Normal file
3
l10n_ru_act_rev/security/ir.model.access.csv
Normal file
@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_general_ledger_act_revise_wizard,general.ledger.act_revise.wizard,model_general_ledger_act_revise_wizard,base.group_user,1,1,1,1
|
||||
access_general_ledger_act_revise_wizard_portal,general.ledger.act_revise.wizard.portal,model_general_ledger_act_revise_wizard,base.group_portal,1,1,1,1
|
|
14
l10n_ru_act_rev/views/account_account_views.xml
Normal file
14
l10n_ru_act_rev/views/account_account_views.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="view_account_form" model="ir.ui.view">
|
||||
<field name="name">account.account.form.inherit</field>
|
||||
<field name="inherit_id" ref="account.view_account_form" />
|
||||
<field name="model">account.account</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<field name="deprecated" position="after">
|
||||
<field name="centralized" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
12
l10n_ru_act_rev/views/portal_templates.xml
Normal file
12
l10n_ru_act_rev/views/portal_templates.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="portal_my_home_act_revise" name="Portal My Home : act revise" inherit_id="portal.portal_my_home" priority="40">
|
||||
<xpath expr="//div[hasclass('o_portal_docs')]" position="inside">
|
||||
<a t-attf-href="/my/act_revise/a">
|
||||
<button type="button" class="btn btn-primary btn-md o_website_form_send">Печатать акт сверки</button>
|
||||
</a>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
9
l10n_ru_act_rev/views/report_general_ledger.xml
Normal file
9
l10n_ru_act_rev/views/report_general_ledger.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<template id="report_general_ledger">
|
||||
<div class="o_act_revise_page">
|
||||
<t t-call="l10n_ru_act_rev.report_buttons" />
|
||||
<t t-call="l10n_ru_act_rev.report_general_ledger_base" />
|
||||
</div>
|
||||
</template>
|
||||
</odoo>
|
2
l10n_ru_act_rev/wizard/__init__.py
Normal file
2
l10n_ru_act_rev/wizard/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from . import abstract_wizard
|
||||
from . import general_ledger_wizard
|
38
l10n_ru_act_rev/wizard/abstract_wizard.py
Normal file
38
l10n_ru_act_rev/wizard/abstract_wizard.py
Normal file
@ -0,0 +1,38 @@
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class AbstractWizard(models.AbstractModel):
|
||||
_name = "act_revise.abstract_wizard"
|
||||
_description = "Abstract Wizard"
|
||||
|
||||
def _get_partner_ids_domain(self):
|
||||
return [
|
||||
"&",
|
||||
"|",
|
||||
("company_id", "=", self.company_id.id),
|
||||
("company_id", "=", False),
|
||||
"|",
|
||||
("parent_id", "=", False),
|
||||
("is_company", "=", True),
|
||||
]
|
||||
|
||||
def _default_partners(self):
|
||||
context = self.env.context
|
||||
if context.get("active_ids") and context.get("active_model") == "res.partner":
|
||||
partners = self.env["res.partner"].browse(context["active_ids"])
|
||||
corp_partners = partners.filtered("parent_id")
|
||||
partners -= corp_partners
|
||||
partners |= corp_partners.mapped("commercial_partner_id")
|
||||
return partners.ids
|
||||
|
||||
company_id = fields.Many2one(
|
||||
comodel_name="res.company",
|
||||
default=lambda self: self.env.company.id,
|
||||
required=False,
|
||||
string="Компания",
|
||||
)
|
||||
|
||||
def button_export_pdf(self):
|
||||
self.ensure_one()
|
||||
report_type = "qweb-pdf"
|
||||
return self._export(report_type)
|
897
l10n_ru_act_rev/wizard/general_ledger_wizard.py
Normal file
897
l10n_ru_act_rev/wizard/general_ledger_wizard.py
Normal file
@ -0,0 +1,897 @@
|
||||
import logging
|
||||
import time
|
||||
from ast import literal_eval
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.tools import date_utils,pycompat
|
||||
from pytils import dt,numeral
|
||||
from datetime import datetime, date
|
||||
import re
|
||||
import urllib
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
class GeneralLedgerReportWizard(models.TransientModel):
|
||||
"""General ledger report wizard."""
|
||||
|
||||
_name = "general.ledger.act_revise.wizard"
|
||||
_description = "General Ledger Report Wizard"
|
||||
_inherit = "act_revise.abstract_wizard"
|
||||
|
||||
# date_range_id = fields.Many2one(comodel_name="date.range", string="Date range")
|
||||
date_from = fields.Date(string="Начало даты", required=True, default=lambda self: self._init_date_from())
|
||||
date_to = fields.Date(string="Конец даты", required=True, default=fields.Date.context_today)
|
||||
fy_start_date = fields.Date(compute="_compute_fy_start_date")
|
||||
target_move = fields.Selection(
|
||||
[("posted", "Все проведенные проводки"), ("all", "Все проводки")],
|
||||
string="Цель операции",
|
||||
required=True,
|
||||
default="posted",
|
||||
)
|
||||
account_ids = fields.Many2many(
|
||||
comodel_name="account.account", string=_("Filter accounts")
|
||||
)
|
||||
centralize = fields.Boolean(string=_("Activate centralization"), default=True)
|
||||
hide_account_at_0 = fields.Boolean(
|
||||
string=_("Hide account ending balance at 0"),
|
||||
help=_("Use this filter to hide an account or a partner "
|
||||
"with an ending balance at 0. "
|
||||
"If partners are filtered, "
|
||||
"debits and credits totals will not match the trial balance."),
|
||||
)
|
||||
receivable_accounts_only = fields.Boolean()
|
||||
payable_accounts_only = fields.Boolean()
|
||||
partner_ids = fields.Many2many(
|
||||
comodel_name="res.partner",
|
||||
string=_("Filter partners"),
|
||||
default=lambda self: self._default_partners(),
|
||||
)
|
||||
account_journal_ids = fields.Many2many(
|
||||
comodel_name="account.journal", string=_("Filter journals")
|
||||
)
|
||||
cost_center_ids = fields.Many2many(
|
||||
comodel_name="account.analytic.account", string=_("Filter cost centers")
|
||||
)
|
||||
|
||||
not_only_one_unaffected_earnings_account = fields.Boolean(readonly=True)
|
||||
foreign_currency = fields.Boolean(
|
||||
string=_("Show foreign currency"),
|
||||
help=_("Display foreign currency for move lines, unless "
|
||||
"account currency is not setup through chart of accounts "
|
||||
"will display initial and final balance in that currency."),
|
||||
default=lambda self: self._default_foreign_currency(),
|
||||
)
|
||||
account_code_from = fields.Many2one(
|
||||
comodel_name="account.account",
|
||||
help="Starting account in a range",
|
||||
)
|
||||
account_code_to = fields.Many2one(
|
||||
comodel_name="account.account",
|
||||
help="Ending account in a range",
|
||||
)
|
||||
grouped_by = fields.Selection(
|
||||
selection=[("", "None"), ("partners", "Partners"), ("taxes", "Taxes")],
|
||||
default="partners",
|
||||
)
|
||||
show_cost_center = fields.Boolean(
|
||||
string="Show Analytic Account",
|
||||
default=True,
|
||||
)
|
||||
domain = fields.Char(
|
||||
string="Journal Items Domain",
|
||||
default=[],
|
||||
help="This domain will be used to select specific domain for Journal " "Items",
|
||||
)
|
||||
|
||||
# def _print_report(self, report_type):
|
||||
# self.ensure_one()
|
||||
# data = self._prepare_report_general_ledger()
|
||||
# report = self.env["ir.actions.report"].search(
|
||||
# [("report_name", "=", "act_revise.general_ledger"), ("report_type", "=", report_type)], limit=1, )
|
||||
# if self.partner_ids[0].parent_id:
|
||||
# partner = int(self.partner_ids[0].parent_id.id)
|
||||
# else:
|
||||
# partner = int(self.partner_ids[0].id)
|
||||
# return {
|
||||
# 'type': 'ir.actions.act_url',
|
||||
# 'url': '/my/act_revise_contact/%s?date_to=%s&date_from=%s&target_move=%s&company=%s&partner=%s' % (
|
||||
# urllib.parse.quote(self.get_report_filename()), self.date_to, self.date_from, self.target_move,
|
||||
# self.company_id.id, partner),
|
||||
# 'target': 'new',
|
||||
# }
|
||||
|
||||
def _get_account_move_lines_domain(self):
|
||||
domain = literal_eval(self.domain) if self.domain else []
|
||||
return domain
|
||||
|
||||
@api.onchange("account_code_from", "account_code_to")
|
||||
def on_change_account_range(self):
|
||||
if (
|
||||
self.account_code_from
|
||||
and self.account_code_from.code.isdigit()
|
||||
and self.account_code_to
|
||||
and self.account_code_to.code.isdigit()
|
||||
):
|
||||
start_range = self.account_code_from.code
|
||||
end_range = self.account_code_to.code
|
||||
self.account_ids = self.env["account.account"].search(
|
||||
[("code", ">=", start_range), ("code", "<=", end_range)]
|
||||
)
|
||||
if self.company_id:
|
||||
self.account_ids = self.account_ids.filtered(
|
||||
lambda a: a.company_ids == self.company_id
|
||||
)
|
||||
|
||||
def _init_date_from(self):
|
||||
"""set start date to begin of current year if fiscal year running"""
|
||||
today = fields.Date.context_today(self)
|
||||
company = self.company_id or self.env.company
|
||||
last_fsc_month = company.fiscalyear_last_month
|
||||
last_fsc_day = company.fiscalyear_last_day
|
||||
|
||||
if (
|
||||
today.month < int(last_fsc_month)
|
||||
or today.month == int(last_fsc_month)
|
||||
and today.day <= last_fsc_day
|
||||
):
|
||||
return time.strftime("%Y-01-01")
|
||||
else:
|
||||
return False
|
||||
|
||||
def _default_foreign_currency(self):
|
||||
return self.env.user.has_group("base.group_multi_currency")
|
||||
|
||||
@api.depends("date_from")
|
||||
def _compute_fy_start_date(self):
|
||||
for wiz in self:
|
||||
if wiz.date_from:
|
||||
date_from, date_to = date_utils.get_fiscal_year(
|
||||
wiz.date_from,
|
||||
day=self.company_id.fiscalyear_last_day,
|
||||
month=int(self.company_id.fiscalyear_last_month),
|
||||
)
|
||||
wiz.fy_start_date = date_from
|
||||
else:
|
||||
wiz.fy_start_date = False
|
||||
|
||||
@api.onchange("company_id")
|
||||
def onchange_company_id(self):
|
||||
"""Handle company change."""
|
||||
count = self.env["account.account"].search_count(
|
||||
[
|
||||
("account_type", "=", "equity_unaffected"),
|
||||
("company_ids", "=", self.company_id.id),
|
||||
]
|
||||
)
|
||||
self.not_only_one_unaffected_earnings_account = count != 1
|
||||
# if (
|
||||
# self.company_id
|
||||
# and self.date_range_id.company_id
|
||||
# and self.date_range_id.company_id != self.company_id
|
||||
# ):
|
||||
# self.date_range_id = False
|
||||
if self.company_id and self.account_journal_ids:
|
||||
self.account_journal_ids = self.account_journal_ids.filtered(
|
||||
lambda p: p.company_id == self.company_id or not p.company_id
|
||||
)
|
||||
if self.company_id and self.partner_ids:
|
||||
self.partner_ids = self.partner_ids.filtered(
|
||||
lambda p: p.company_id == self.company_id or not p.company_id
|
||||
)
|
||||
if self.company_id and self.account_ids:
|
||||
if self.receivable_accounts_only or self.payable_accounts_only:
|
||||
self.onchange_type_accounts_only()
|
||||
else:
|
||||
self.account_ids = self.account_ids.filtered(
|
||||
lambda a: a.company_ids == self.company_id
|
||||
)
|
||||
if self.company_id and self.cost_center_ids:
|
||||
self.cost_center_ids = self.cost_center_ids.filtered(
|
||||
lambda c: c.company_id == self.company_id
|
||||
)
|
||||
res = {
|
||||
"domain": {
|
||||
"account_ids": [],
|
||||
"partner_ids": [],
|
||||
"account_journal_ids": [],
|
||||
"cost_center_ids": [],
|
||||
# "date_range_id": [],
|
||||
}
|
||||
}
|
||||
if not self.company_id:
|
||||
return res
|
||||
else:
|
||||
res["domain"]["account_ids"] += [("company_ids", "=", self.company_id.id)]
|
||||
res["domain"]["account_journal_ids"] += [
|
||||
("company_ids", "=", self.company_id.id)
|
||||
]
|
||||
res["domain"]["partner_ids"] += self._get_partner_ids_domain()
|
||||
res["domain"]["cost_center_ids"] += [
|
||||
("company_id", "=", self.company_id.id)
|
||||
]
|
||||
# res["domain"]["date_range_id"] += [
|
||||
# "|",
|
||||
# ("company_id", "=", self.company_id.id),
|
||||
# ("company_id", "=", False),
|
||||
# ]
|
||||
return res
|
||||
|
||||
# @api.onchange("date_range_id")
|
||||
# def onchange_date_range_id(self):
|
||||
# """Handle date range change."""
|
||||
# if self.date_range_id:
|
||||
# self.date_from = self.date_range_id.date_start
|
||||
# self.date_to = self.date_range_id.date_end
|
||||
|
||||
# @api.constrains("company_id", "date_range_id")
|
||||
# def _check_company_id_date_range_id(self):
|
||||
# for rec in self.sudo():
|
||||
# if (
|
||||
# rec.company_id
|
||||
# and rec.date_range_id.company_id
|
||||
# and rec.company_id != rec.date_range_id.company_id
|
||||
# ):
|
||||
# raise ValidationError(
|
||||
# _(
|
||||
# "The Company in the General Ledger Report Wizard and in "
|
||||
# "Date Range must be the same."
|
||||
# )
|
||||
# )
|
||||
|
||||
@api.onchange("receivable_accounts_only", "payable_accounts_only")
|
||||
def onchange_type_accounts_only(self):
|
||||
"""Handle receivable/payable accounts only change."""
|
||||
if self.receivable_accounts_only or self.payable_accounts_only:
|
||||
domain = [("company_ids", "=", self.company_id.id)]
|
||||
if self.receivable_accounts_only and self.payable_accounts_only:
|
||||
domain += [
|
||||
("account_type", "in", ("asset_receivable", "liability_payable"))
|
||||
]
|
||||
elif self.receivable_accounts_only:
|
||||
domain += [("account_type", "=", "asset_receivable")]
|
||||
elif self.payable_accounts_only:
|
||||
domain += [("account_type", "=", "liability_payable")]
|
||||
self.account_ids = self.env["account.account"].search(domain)
|
||||
else:
|
||||
self.account_ids = None
|
||||
|
||||
@api.onchange("partner_ids")
|
||||
def onchange_partner_ids(self):
|
||||
"""Handle partners change."""
|
||||
if self.partner_ids:
|
||||
self.receivable_accounts_only = self.payable_accounts_only = True
|
||||
else:
|
||||
self.receivable_accounts_only = self.payable_accounts_only = False
|
||||
|
||||
@api.depends("company_id")
|
||||
def _compute_unaffected_earnings_account(self):
|
||||
for record in self:
|
||||
record.unaffected_earnings_account = self.env["account.account"].search(
|
||||
[
|
||||
("account_type", "=", "equity_unaffected"),
|
||||
("company_ids", "=", record.company_id.id),
|
||||
]
|
||||
)
|
||||
|
||||
unaffected_earnings_account = fields.Many2one(
|
||||
comodel_name="account.account",
|
||||
compute="_compute_unaffected_earnings_account",
|
||||
store=True,
|
||||
)
|
||||
|
||||
# def _print_report(self, report_type):
|
||||
# self.ensure_one()
|
||||
# data = self._prepare_report_general_ledger()
|
||||
# report_name = "act_revise.general_ledger"
|
||||
# return (
|
||||
# self.env["ir.actions.report"]
|
||||
# .search(
|
||||
# [("report_name", "=", report_name), ("report_type", "=", report_type)],
|
||||
# limit=1,
|
||||
# )
|
||||
# .report_action(self, data=data)
|
||||
# )
|
||||
def _print_report(self, report_type):
|
||||
self.ensure_one()
|
||||
data = self._prepare_report_general_ledger()
|
||||
report = self.env["ir.actions.report"].search(
|
||||
[("report_name", "=", "l10n_ru_act_rev.general_ledger"), ("report_type", "=", report_type)], limit=1, )
|
||||
|
||||
if self.partner_ids[0].parent_id:
|
||||
partner = int(self.partner_ids[0].parent_id.id)
|
||||
else:
|
||||
partner = int(self.partner_ids[0].id)
|
||||
account_data = self.env['account.move.line'].sudo().search([
|
||||
('partner_id', '=', partner),
|
||||
('account_id.account_type', 'in', ('liability_payable', 'asset_receivable')),
|
||||
('account_id.non_trade', '=', False),
|
||||
('date', '<=', self.date_to),
|
||||
('date', '>=', self.date_from)
|
||||
])
|
||||
if self.target_move == 'posted' and not account_data.filtered(lambda p: p.parent_state == 'posted') or not account_data:
|
||||
raise UserError(f'Проводок для формирования акта по введенным условиям не найдено.')
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': '/my/act_revise_contact/%s?date_to=%s&date_from=%s&target_move=%s&company=%s&partner=%s' % (
|
||||
urllib.parse.quote(self.get_report_filename()), self.date_to, self.date_from, self.target_move,
|
||||
self.company_id.id, partner),
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
def _prepare_report_general_ledger(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
"wizard_id": self.id,
|
||||
"date_from": self.date_from,
|
||||
"date_to": self.date_to,
|
||||
"only_posted_moves": self.target_move == "posted",
|
||||
"hide_account_at_0": self.hide_account_at_0,
|
||||
"foreign_currency": self.foreign_currency,
|
||||
"company_id": self.company_id.id,
|
||||
"account_ids": self.account_ids.ids,
|
||||
"partner_ids": self.partner_ids.ids,
|
||||
"grouped_by": self.grouped_by,
|
||||
"cost_center_ids": self.cost_center_ids.ids,
|
||||
"show_cost_center": self.show_cost_center,
|
||||
"journal_ids": self.account_journal_ids.ids,
|
||||
"centralize": self.centralize,
|
||||
"fy_start_date": self.fy_start_date,
|
||||
"unaffected_earnings_account": self.unaffected_earnings_account.id,
|
||||
"account_financial_report_lang": self.env.lang,
|
||||
"domain": self._get_account_move_lines_domain(),
|
||||
}
|
||||
|
||||
def _export(self, report_type):
|
||||
"""Default export is PDF."""
|
||||
return self._print_report(report_type)
|
||||
|
||||
def _get_atr_from_dict(self, obj_id, data, key):
|
||||
try:
|
||||
return data[obj_id][key]
|
||||
except KeyError:
|
||||
return data[str(obj_id)][key]
|
||||
|
||||
def numer(self, name):
|
||||
if name:
|
||||
numeration = re.findall('\d+$', name)
|
||||
if numeration: return numeration[0]
|
||||
return name
|
||||
|
||||
def get_data_format(self, date):
|
||||
if date and date != 'False':
|
||||
return dt.ru_strftime(u'%d.%m.%Y г.', date=datetime.strptime(str(date), "%Y-%m-%d"), inflected=True)
|
||||
return ''
|
||||
|
||||
def initials(self, fio):
|
||||
if fio:
|
||||
return (fio.split()[0] + ' ' + ''.join([fio[0:1] + '.' for fio in fio.split()[1:]])).strip()
|
||||
return ''
|
||||
|
||||
def rubles(self, sum):
|
||||
"Transform sum number in rubles to text"
|
||||
text_rubles = numeral.rubles(int(sum))
|
||||
copeck = round((sum - int(sum)) * 100)
|
||||
text_copeck = numeral.choose_plural(int(copeck), (u"копейка", u"копейки", u"копеек"))
|
||||
return ("%s %02d %s") % (text_rubles, copeck, text_copeck)
|
||||
|
||||
def img(self, img, type='png', width=0, height=0):
|
||||
if width:
|
||||
width = "width='%spx'" % (width)
|
||||
else:
|
||||
width = " "
|
||||
if height:
|
||||
height = "height='%spx'" % (height)
|
||||
else:
|
||||
height = " "
|
||||
toreturn = "<img %s %s src='data:image/%s;base64,%s' />" % (
|
||||
width,
|
||||
height,
|
||||
type,
|
||||
str(pycompat.to_text(img)))
|
||||
return toreturn
|
||||
|
||||
def get_contract(self):
|
||||
partner = int(self.partner_ids[0].id)
|
||||
contract = self.env['partner.contract.customer'].search(
|
||||
[('partner_id', '=', partner), ('state', '=', 'signed')], limit=1)
|
||||
if contract:
|
||||
return contract
|
||||
|
||||
def get_function_partner(self, partner):
|
||||
director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1)
|
||||
if director:
|
||||
if director.function:
|
||||
return director.function or 'отсутствует'
|
||||
|
||||
def get_name_partner(self, partner):
|
||||
director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1)
|
||||
if director:
|
||||
return director.name or 'отсутствует'
|
||||
|
||||
def get_report_filename(self):
|
||||
today = date.today()
|
||||
d1 = today.strftime("%d-%m-%Y")
|
||||
if self.partner_ids[0].parent_id:
|
||||
p = ''.join(self.partner_ids[0].parent_id.name)
|
||||
else:
|
||||
p = ''.join(self.partner_ids[0].name)
|
||||
# return 'Акт Сверки '+ d1 + ' ' + self.company_id.name+'_'+p
|
||||
return str(self.company_id.id) + ' - ' + ' ' + d1
|
||||
|
||||
def sorted_lines(self, list):
|
||||
list = sorted(list, key=lambda k: k.get('date'), reverse=False)
|
||||
return list
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# import time
|
||||
# from ast import literal_eval
|
||||
# from odoo import _, api, fields, models
|
||||
# from odoo.tools import date_utils,pycompat
|
||||
# from pytils import dt,numeral
|
||||
# from datetime import datetime, date
|
||||
# import re
|
||||
# import urllib
|
||||
#
|
||||
# class GeneralLedgerReportWizard(models.TransientModel):
|
||||
# """General ledger report wizard."""
|
||||
#
|
||||
# _name = "general.ledger.act_revise.wizard"
|
||||
# _description = "General Ledger Report Wizard"
|
||||
# _inherit = "act_revise.abstract_wizard"
|
||||
#
|
||||
# # date_range_id = fields.Many2one(comodel_name="date.range", string="Date range")
|
||||
# date_from = fields.Date(string="Начало даты", required=True, default=lambda self: self._init_date_from())
|
||||
# date_to = fields.Date(string="Конец даты", required=True, default=fields.Date.context_today)
|
||||
# fy_start_date = fields.Date(compute="_compute_fy_start_date")
|
||||
# target_move = fields.Selection(
|
||||
# [("posted", "Все проведенные проводки"), ("all", "Все проводки")],
|
||||
# string="Цель операции",
|
||||
# required=True,
|
||||
# default="posted",
|
||||
# )
|
||||
# account_ids = fields.Many2many(
|
||||
# comodel_name="account.account", string=_("Filter accounts")
|
||||
# )
|
||||
# centralize = fields.Boolean(string=_("Activate centralization"), default=True)
|
||||
# hide_account_at_0 = fields.Boolean(
|
||||
# string=_("Hide account ending balance at 0"),
|
||||
# help=_("Use this filter to hide an account or a partner "
|
||||
# "with an ending balance at 0. "
|
||||
# "If partners are filtered, "
|
||||
# "debits and credits totals will not match the trial balance."),
|
||||
# )
|
||||
# receivable_accounts_only = fields.Boolean()
|
||||
# payable_accounts_only = fields.Boolean()
|
||||
# partner_ids = fields.Many2many(
|
||||
# comodel_name="res.partner",
|
||||
# string=_("Filter partners"),
|
||||
# default=lambda self: self._default_partners(),
|
||||
# )
|
||||
# account_journal_ids = fields.Many2many(
|
||||
# comodel_name="account.journal", string=_("Filter journals")
|
||||
# )
|
||||
# cost_center_ids = fields.Many2many(
|
||||
# comodel_name="account.analytic.account", string=_("Filter cost centers")
|
||||
# )
|
||||
#
|
||||
# not_only_one_unaffected_earnings_account = fields.Boolean(readonly=True)
|
||||
# foreign_currency = fields.Boolean(
|
||||
# string=_("Show foreign currency"),
|
||||
# help=_("Display foreign currency for move lines, unless "
|
||||
# "account currency is not setup through chart of accounts "
|
||||
# "will display initial and final balance in that currency."),
|
||||
# default=lambda self: self._default_foreign_currency(),
|
||||
# )
|
||||
# account_code_from = fields.Many2one(
|
||||
# comodel_name="account.account",
|
||||
# help="Starting account in a range",
|
||||
# )
|
||||
# account_code_to = fields.Many2one(
|
||||
# comodel_name="account.account",
|
||||
# help="Ending account in a range",
|
||||
# )
|
||||
# grouped_by = fields.Selection(
|
||||
# selection=[("", "None"), ("partners", "Partners"), ("taxes", "Taxes")],
|
||||
# default="partners",
|
||||
# )
|
||||
# show_cost_center = fields.Boolean(
|
||||
# string="Show Analytic Account",
|
||||
# default=True,
|
||||
# )
|
||||
# domain = fields.Char(
|
||||
# string="Journal Items Domain",
|
||||
# default=[],
|
||||
# help="This domain will be used to select specific domain for Journal " "Items",
|
||||
# )
|
||||
#
|
||||
# # def _print_report(self, report_type):
|
||||
# # self.ensure_one()
|
||||
# # data = self._prepare_report_general_ledger()
|
||||
# # report = self.env["ir.actions.report"].search(
|
||||
# # [("report_name", "=", "act_revise.general_ledger"), ("report_type", "=", report_type)], limit=1, )
|
||||
# # if self.partner_ids[0].parent_id:
|
||||
# # partner = int(self.partner_ids[0].parent_id.id)
|
||||
# # else:
|
||||
# # partner = int(self.partner_ids[0].id)
|
||||
# # return {
|
||||
# # 'type': 'ir.actions.act_url',
|
||||
# # 'url': '/my/act_revise_contact/%s?date_to=%s&date_from=%s&target_move=%s&company=%s&partner=%s' % (
|
||||
# # urllib.parse.quote(self.get_report_filename()), self.date_to, self.date_from, self.target_move,
|
||||
# # self.company_id.id, partner),
|
||||
# # 'target': 'new',
|
||||
# # }
|
||||
#
|
||||
# def _get_account_move_lines_domain(self):
|
||||
# domain = literal_eval(self.domain) if self.domain else []
|
||||
# return domain
|
||||
#
|
||||
# @api.onchange("account_code_from", "account_code_to")
|
||||
# def on_change_account_range(self):
|
||||
# if (
|
||||
# self.account_code_from
|
||||
# and self.account_code_from.code.isdigit()
|
||||
# and self.account_code_to
|
||||
# and self.account_code_to.code.isdigit()
|
||||
# ):
|
||||
# start_range = self.account_code_from.code
|
||||
# end_range = self.account_code_to.code
|
||||
# self.account_ids = self.env["account.account"].search(
|
||||
# [("code", ">=", start_range), ("code", "<=", end_range)]
|
||||
# )
|
||||
# if self.company_id:
|
||||
# self.account_ids = self.account_ids.filtered(
|
||||
# lambda a: a.company_id == self.company_id
|
||||
# )
|
||||
#
|
||||
# def _init_date_from(self):
|
||||
# """set start date to begin of current year if fiscal year running"""
|
||||
# today = fields.Date.context_today(self)
|
||||
# company = self.company_id or self.env.company
|
||||
# last_fsc_month = company.fiscalyear_last_month
|
||||
# last_fsc_day = company.fiscalyear_last_day
|
||||
#
|
||||
# if (
|
||||
# today.month < int(last_fsc_month)
|
||||
# or today.month == int(last_fsc_month)
|
||||
# and today.day <= last_fsc_day
|
||||
# ):
|
||||
# return time.strftime("%Y-01-01")
|
||||
# else:
|
||||
# return False
|
||||
#
|
||||
# def _default_foreign_currency(self):
|
||||
# return self.env.user.has_group("base.group_multi_currency")
|
||||
#
|
||||
# @api.depends("date_from")
|
||||
# def _compute_fy_start_date(self):
|
||||
# for wiz in self:
|
||||
# if wiz.date_from:
|
||||
# date_from, date_to = date_utils.get_fiscal_year(
|
||||
# wiz.date_from,
|
||||
# day=self.company_id.fiscalyear_last_day,
|
||||
# month=int(self.company_id.fiscalyear_last_month),
|
||||
# )
|
||||
# wiz.fy_start_date = date_from
|
||||
# else:
|
||||
# wiz.fy_start_date = False
|
||||
#
|
||||
# @api.onchange("company_id")
|
||||
# def onchange_company_id(self):
|
||||
# """Handle company change."""
|
||||
# count = self.env["account.account"].search_count(
|
||||
# [
|
||||
# ("account_type", "=", "equity_unaffected"),
|
||||
# ("company_id", "=", self.company_id.id),
|
||||
# ]
|
||||
# )
|
||||
# self.not_only_one_unaffected_earnings_account = count != 1
|
||||
# # if (
|
||||
# # self.company_id
|
||||
# # and self.date_range_id.company_id
|
||||
# # and self.date_range_id.company_id != self.company_id
|
||||
# # ):
|
||||
# # self.date_range_id = False
|
||||
# if self.company_id and self.account_journal_ids:
|
||||
# self.account_journal_ids = self.account_journal_ids.filtered(
|
||||
# lambda p: p.company_id == self.company_id or not p.company_id
|
||||
# )
|
||||
# if self.company_id and self.partner_ids:
|
||||
# self.partner_ids = self.partner_ids.filtered(
|
||||
# lambda p: p.company_id == self.company_id or not p.company_id
|
||||
# )
|
||||
# if self.company_id and self.account_ids:
|
||||
# if self.receivable_accounts_only or self.payable_accounts_only:
|
||||
# self.onchange_type_accounts_only()
|
||||
# else:
|
||||
# self.account_ids = self.account_ids.filtered(
|
||||
# lambda a: a.company_id == self.company_id
|
||||
# )
|
||||
# if self.company_id and self.cost_center_ids:
|
||||
# self.cost_center_ids = self.cost_center_ids.filtered(
|
||||
# lambda c: c.company_id == self.company_id
|
||||
# )
|
||||
# res = {
|
||||
# "domain": {
|
||||
# "account_ids": [],
|
||||
# "partner_ids": [],
|
||||
# "account_journal_ids": [],
|
||||
# "cost_center_ids": [],
|
||||
# # "date_range_id": [],
|
||||
# }
|
||||
# }
|
||||
# if not self.company_id:
|
||||
# return res
|
||||
# else:
|
||||
# res["domain"]["account_ids"] += [("company_id", "=", self.company_id.id)]
|
||||
# res["domain"]["account_journal_ids"] += [
|
||||
# ("company_id", "=", self.company_id.id)
|
||||
# ]
|
||||
# res["domain"]["partner_ids"] += self._get_partner_ids_domain()
|
||||
# res["domain"]["cost_center_ids"] += [
|
||||
# ("company_id", "=", self.company_id.id)
|
||||
# ]
|
||||
# # res["domain"]["date_range_id"] += [
|
||||
# # "|",
|
||||
# # ("company_id", "=", self.company_id.id),
|
||||
# # ("company_id", "=", False),
|
||||
# # ]
|
||||
# return res
|
||||
#
|
||||
# # @api.onchange("date_range_id")
|
||||
# # def onchange_date_range_id(self):
|
||||
# # """Handle date range change."""
|
||||
# # if self.date_range_id:
|
||||
# # self.date_from = self.date_range_id.date_start
|
||||
# # self.date_to = self.date_range_id.date_end
|
||||
#
|
||||
# # @api.constrains("company_id", "date_range_id")
|
||||
# # def _check_company_id_date_range_id(self):
|
||||
# # for rec in self.sudo():
|
||||
# # if (
|
||||
# # rec.company_id
|
||||
# # and rec.date_range_id.company_id
|
||||
# # and rec.company_id != rec.date_range_id.company_id
|
||||
# # ):
|
||||
# # raise ValidationError(
|
||||
# # _(
|
||||
# # "The Company in the General Ledger Report Wizard and in "
|
||||
# # "Date Range must be the same."
|
||||
# # )
|
||||
# # )
|
||||
#
|
||||
# @api.onchange("receivable_accounts_only", "payable_accounts_only")
|
||||
# def onchange_type_accounts_only(self):
|
||||
# """Handle receivable/payable accounts only change."""
|
||||
# if self.receivable_accounts_only or self.payable_accounts_only:
|
||||
# domain = [("company_id", "=", self.company_id.id)]
|
||||
# if self.receivable_accounts_only and self.payable_accounts_only:
|
||||
# domain += [
|
||||
# ("account_type", "in", ("asset_receivable", "liability_payable"))
|
||||
# ]
|
||||
# elif self.receivable_accounts_only:
|
||||
# domain += [("account_type", "=", "asset_receivable")]
|
||||
# elif self.payable_accounts_only:
|
||||
# domain += [("account_type", "=", "liability_payable")]
|
||||
# self.account_ids = self.env["account.account"].search(domain)
|
||||
# else:
|
||||
# self.account_ids = None
|
||||
#
|
||||
# @api.onchange("partner_ids")
|
||||
# def onchange_partner_ids(self):
|
||||
# """Handle partners change."""
|
||||
# if self.partner_ids:
|
||||
# self.receivable_accounts_only = self.payable_accounts_only = True
|
||||
# else:
|
||||
# self.receivable_accounts_only = self.payable_accounts_only = False
|
||||
#
|
||||
# @api.depends("company_id")
|
||||
# def _compute_unaffected_earnings_account(self):
|
||||
# for record in self:
|
||||
# record.unaffected_earnings_account = self.env["account.account"].search(
|
||||
# [
|
||||
# ("account_type", "=", "equity_unaffected"),
|
||||
# ("company_id", "=", record.company_id.id),
|
||||
# ]
|
||||
# )
|
||||
#
|
||||
# unaffected_earnings_account = fields.Many2one(
|
||||
# comodel_name="account.account",
|
||||
# compute="_compute_unaffected_earnings_account",
|
||||
# store=True,
|
||||
# )
|
||||
#
|
||||
# # def _print_report(self, report_type):
|
||||
# # self.ensure_one()
|
||||
# # data = self._prepare_report_general_ledger()
|
||||
# # report_name = "act_revise.general_ledger"
|
||||
# # return (
|
||||
# # self.env["ir.actions.report"]
|
||||
# # .search(
|
||||
# # [("report_name", "=", report_name), ("report_type", "=", report_type)],
|
||||
# # limit=1,
|
||||
# # )
|
||||
# # .report_action(self, data=data)
|
||||
# # )
|
||||
# def _print_report(self, report_type):
|
||||
# self.ensure_one()
|
||||
# data = self._prepare_report_general_ledger()
|
||||
# report = self.env["ir.actions.report"].search(
|
||||
# [("report_name", "=", "act_revise.general_ledger"), ("report_type", "=", report_type)], limit=1, )
|
||||
# # report.report_name='Test'
|
||||
# # report.headers.add('Content-Disposition', 'attachment; filename="Test.pdf";')
|
||||
# # pdf, _ = request.env.ref('act_revise.action_print_report_general_ledger_qweb').sudo().render_qweb_pdf(self,data=data)
|
||||
# # pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)),('Content-Disposition', 'attachment; filename="%s";' % report_name),]
|
||||
# # return request.make_response(pdf, headers=pdfhttpheaders)
|
||||
# # return (
|
||||
# # self.env["ir.actions.report"]
|
||||
# # .search(
|
||||
# # [("report_name", "=", "act_revise.general_ledger"), ("report_type", "=", report_type)],
|
||||
# # limit=1,
|
||||
# # )
|
||||
# # report.report_action(self, data=data)
|
||||
# # )
|
||||
# # name='Test'
|
||||
# if self.partner_ids[0].parent_id:
|
||||
# partner = int(self.partner_ids[0].parent_id.id)
|
||||
# else:
|
||||
# partner = int(self.partner_ids[0].id)
|
||||
# account_data = self.env['account.move.line'].sudo().search([
|
||||
# ('partner_id', '=', partner.id),
|
||||
# ('account_id.account_type', 'in', ('liability_payable', 'asset_receivable')),
|
||||
# ('account_id.non_trade', '=', False),
|
||||
# ('date', '<=', self.date_to),
|
||||
# ('date', '>=', self.date_from)
|
||||
# ])
|
||||
# if not account_data:
|
||||
# raise UserError(f'Проводок для формирования акта по введенным условиям не найдено.')
|
||||
# return {
|
||||
# 'type': 'ir.actions.act_url',
|
||||
# 'url': '/my/act_revise_contact/%s?date_to=%s&date_from=%s&target_move=%s&company=%s&partner=%s' % (
|
||||
# urllib.parse.quote(self.get_report_filename()), self.date_to, self.date_from, self.target_move,
|
||||
# self.company_id.id, partner),
|
||||
# 'target': 'new',
|
||||
# }
|
||||
#
|
||||
# def _prepare_report_general_ledger(self):
|
||||
# self.ensure_one()
|
||||
# return {
|
||||
# "wizard_id": self.id,
|
||||
# "date_from": self.date_from,
|
||||
# "date_to": self.date_to,
|
||||
# "only_posted_moves": self.target_move == "posted",
|
||||
# "hide_account_at_0": self.hide_account_at_0,
|
||||
# "foreign_currency": self.foreign_currency,
|
||||
# "company_id": self.company_id.id,
|
||||
# "account_ids": self.account_ids.ids,
|
||||
# "partner_ids": self.partner_ids.ids,
|
||||
# "grouped_by": self.grouped_by,
|
||||
# "cost_center_ids": self.cost_center_ids.ids,
|
||||
# "show_cost_center": self.show_cost_center,
|
||||
# "journal_ids": self.account_journal_ids.ids,
|
||||
# "centralize": self.centralize,
|
||||
# "fy_start_date": self.fy_start_date,
|
||||
# "unaffected_earnings_account": self.unaffected_earnings_account.id,
|
||||
# "account_financial_report_lang": self.env.lang,
|
||||
# "domain": self._get_account_move_lines_domain(),
|
||||
# }
|
||||
#
|
||||
# def _export(self, report_type):
|
||||
# """Default export is PDF."""
|
||||
# return self._print_report(report_type)
|
||||
#
|
||||
# def _get_atr_from_dict(self, obj_id, data, key):
|
||||
# try:
|
||||
# return data[obj_id][key]
|
||||
# except KeyError:
|
||||
# return data[str(obj_id)][key]
|
||||
#
|
||||
# def numer(self, name):
|
||||
# if name:
|
||||
# numeration = re.findall('\d+$', name)
|
||||
# if numeration: return numeration[0]
|
||||
# return name
|
||||
#
|
||||
# def get_data_format(self, date):
|
||||
# if date and date != 'False':
|
||||
# return dt.ru_strftime(u'%d.%m.%Y Рі.', date=datetime.strptime(str(date), "%Y-%m-%d"), inflected=True)
|
||||
# return ''
|
||||
#
|
||||
# def initials(self, fio):
|
||||
# if fio:
|
||||
# return (fio.split()[0] + ' ' + ''.join([fio[0:1] + '.' for fio in fio.split()[1:]])).strip()
|
||||
# return ''
|
||||
#
|
||||
# def rubles(self, sum):
|
||||
# "Transform sum number in rubles to text"
|
||||
# text_rubles = numeral.rubles(int(sum))
|
||||
# copeck = round((sum - int(sum)) * 100)
|
||||
# text_copeck = numeral.choose_plural(int(copeck), (u"копейка", u"копейки", u"копеек"))
|
||||
# return ("%s %02d %s") % (text_rubles, copeck, text_copeck)
|
||||
#
|
||||
# def img(self, img, type='png', width=0, height=0):
|
||||
# if width:
|
||||
# width = "width='%spx'" % (width)
|
||||
# else:
|
||||
# width = " "
|
||||
# if height:
|
||||
# height = "height='%spx'" % (height)
|
||||
# else:
|
||||
# height = " "
|
||||
# toreturn = "<img %s %s src='data:image/%s;base64,%s' />" % (
|
||||
# width,
|
||||
# height,
|
||||
# type,
|
||||
# str(pycompat.to_text(img)))
|
||||
# return toreturn
|
||||
#
|
||||
# def get_contract(self):
|
||||
# partner = int(self.partner_ids[0].id)
|
||||
# contract = self.env['partner.contract.customer'].search(
|
||||
# [('partner_id', '=', partner), ('state', '=', 'signed')], limit=1)
|
||||
# if contract:
|
||||
# return contract
|
||||
#
|
||||
# def get_function_partner(self, partner):
|
||||
# director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1)
|
||||
# if director:
|
||||
# if director.function:
|
||||
# return director.function or 'отсутствует'
|
||||
#
|
||||
# def get_name_partner(self, partner):
|
||||
# director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1)
|
||||
# if director:
|
||||
# return director.name or 'отсутствует'
|
||||
#
|
||||
# def get_report_filename(self):
|
||||
# today = date.today()
|
||||
# d1 = today.strftime("%d-%m-%Y")
|
||||
# if self.partner_ids[0].parent_id:
|
||||
# p = ''.join(self.partner_ids[0].parent_id.name)
|
||||
# else:
|
||||
# p = ''.join(self.partner_ids[0].name)
|
||||
# # return 'Акт Сверки '+ d1 + ' ' + self.company_id.name+'_'+p
|
||||
# return str(self.company_id.id) + ' - ' + ' ' + d1
|
||||
#
|
||||
# def sorted_lines(self, list):
|
||||
# list = sorted(list, key=lambda k: k.get('date'), reverse=False)
|
||||
# return list
|
164
l10n_ru_act_rev/wizard/general_ledger_wizard_view.xml
Normal file
164
l10n_ru_act_rev/wizard/general_ledger_wizard_view.xml
Normal file
@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<!-- GENERAL LEDGER -->
|
||||
<record id="general_ledger_wizard" model="ir.ui.view">
|
||||
<field name="name">Акт сверки</field>
|
||||
<field name="model">general.ledger.act_revise.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group name="main_info">
|
||||
<field
|
||||
name="company_id"
|
||||
options="{'no_create': True}"
|
||||
groups="base.group_multi_company"
|
||||
/>
|
||||
</group>
|
||||
<div invisible= "not_only_one_unaffected_earnings_account==True" >
|
||||
<group name="filters">
|
||||
<group name="date_range">
|
||||
<!-- <field name="date_range_id" />-->
|
||||
<field name="date_from" />
|
||||
<field name="date_to" />
|
||||
<field name="fy_start_date" invisible="1" /><!-- reason: need-->
|
||||
<field name="target_move" widget="radio" />
|
||||
</group>
|
||||
<group name="other_filters" invisible="1"><!-- reason: need-->
|
||||
<field name="grouped_by" />
|
||||
<field name="centralize" />
|
||||
<field name="hide_account_at_0" />
|
||||
<field name="foreign_currency" />
|
||||
<field name="show_cost_center" />
|
||||
</group>
|
||||
</group>
|
||||
<notebook invisible="1"><!-- reason: need-->
|
||||
<page string="Filter accounts">
|
||||
<group name="account_filter" col="4">
|
||||
<label for="account_ids" colspan="4" />
|
||||
<field name="receivable_accounts_only" />
|
||||
<field name="payable_accounts_only" />
|
||||
<label for="account_code_from" string="From Code" />
|
||||
<div>
|
||||
<div class="o_row">
|
||||
<field
|
||||
name="account_code_from"
|
||||
class="oe_inline"
|
||||
options="{'no_create': True}"
|
||||
/>
|
||||
<span class="oe_inline">To</span>
|
||||
<field
|
||||
name="account_code_to"
|
||||
class="oe_inline"
|
||||
options="{'no_create': True}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<field
|
||||
name="account_ids"
|
||||
nolabel="1"
|
||||
widget="many2many_tags"
|
||||
options="{'no_create': True}"
|
||||
colspan="4"
|
||||
/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Filter partners">
|
||||
<field
|
||||
name="partner_ids"
|
||||
nolabel="1"
|
||||
widget="many2many_tags"
|
||||
options="{'no_create': True}"
|
||||
/>
|
||||
</page>
|
||||
<page
|
||||
string="Filter analytic accounts"
|
||||
groups="analytic.group_analytic_accounting"
|
||||
>
|
||||
<field
|
||||
name="cost_center_ids"
|
||||
nolabel="1"
|
||||
widget="many2many_tags"
|
||||
options="{'no_create': True}"
|
||||
/>
|
||||
</page>
|
||||
<page string="Additional Filtering">
|
||||
<style>
|
||||
.o_domain_show_selection_button {display: none}
|
||||
</style>
|
||||
<field
|
||||
name="domain"
|
||||
widget="domain"
|
||||
options="{'model': 'account.move.line', 'in_dialog': True}"
|
||||
context="{'skip_search_count': 1}"
|
||||
/>
|
||||
</page>
|
||||
</notebook>
|
||||
</div>
|
||||
<div invisible= "not_only_one_unaffected_earnings_account==False" >
|
||||
<field name="not_only_one_unaffected_earnings_account" invisible="1"/><!-- reason: need-->
|
||||
<group />
|
||||
<h4>
|
||||
General Ledger can be computed only if selected company have
|
||||
only one unaffected earnings account.
|
||||
</h4>
|
||||
<group />
|
||||
</div>
|
||||
<footer>
|
||||
<div invisible= "not_only_one_unaffected_earnings_account==True">
|
||||
<button
|
||||
name="button_export_pdf"
|
||||
string="Печать"
|
||||
type="object"
|
||||
/>
|
||||
<button string="Отмена" class="oe_link" special="cancel" />
|
||||
</div>
|
||||
<div invisible= "not_only_one_unaffected_earnings_account==False" >
|
||||
<button string="Отмена" class="oe_link" special="cancel" />
|
||||
</div>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!-- <act_window-->
|
||||
<!-- id="action_general_ledger_wizard"-->
|
||||
<!-- name="Акт сверки"-->
|
||||
<!-- res_model="general.ledger.act_revise.wizard"-->
|
||||
<!-- view_mode="form"-->
|
||||
<!-- view_id="general_ledger_wizard"-->
|
||||
<!-- target="new"-->
|
||||
<!-- />-->
|
||||
<!-- <!–Add to res.partner action–>-->
|
||||
<!-- <act_window-->
|
||||
<!-- id="act_action_general_ledger_wizard_partner_relation"-->
|
||||
<!-- name="Печатать акт сверки"-->
|
||||
<!-- res_model="general.ledger.act_revise.wizard"-->
|
||||
<!-- binding_model="res.partner"-->
|
||||
<!-- view_mode="form"-->
|
||||
<!-- context="{-->
|
||||
<!-- 'default_receivable_accounts_only':1,-->
|
||||
<!-- 'default_payable_accounts_only':1,-->
|
||||
<!-- }"-->
|
||||
<!-- groups="account.group_account_manager"-->
|
||||
<!-- target="new"-->
|
||||
<!-- />-->
|
||||
|
||||
<record id="action_general_ledger_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Акт сверки</field>
|
||||
<field name="res_model">general.ledger.act_revise.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="general_ledger_wizard"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<record id="act_action_general_ledger_wizard_partner_relation" model="ir.actions.act_window">
|
||||
<field name="name">Печатать акт сверки</field>
|
||||
<field name="res_model">general.ledger.act_revise.wizard</field>
|
||||
<field name="binding_model_id" ref="base.model_res_partner"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="context">{'default_receivable_accounts_only': 1, 'default_payable_accounts_only': 1}</field>
|
||||
<field name="groups_id" eval="[(6, 0, [ref('account.group_account_manager')])]"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
</odoo>
|
21
l10n_ru_attorney/README.md
Normal file
21
l10n_ru_attorney/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Российская локализация - Доверенность
|
||||
name: l10n_ru_attorney
|
||||
|
||||
## Описание
|
||||
Создание списка доверенностей на получение ТМЦ и их печать.
|
||||
|
||||
###Создание доверенности:
|
||||
1. Меню Покупки - Доверенности - кнопка "Создать";
|
||||
2. На форме указываем:
|
||||
|
||||
2.1. Контрагент - поставщик;
|
||||
|
||||
2.2. Заказ на закупку;
|
||||
|
||||
2.3. Даты действия доверенности ("дата выдачи" и "действительно по").
|
||||
|
||||
|
||||
###Для печати:
|
||||
1. Меню Настройки - Техническое - Отчеты;
|
||||
2. Находим в списке l10n_ru_attorney и добавляем в меню "Печать";
|
||||
3. Открываем созданную запись доверенности - Действие - "Доверенность".
|
3
l10n_ru_attorney/__init__.py
Normal file
3
l10n_ru_attorney/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
42
l10n_ru_attorney/__manifest__.py
Normal file
42
l10n_ru_attorney/__manifest__.py
Normal file
@ -0,0 +1,42 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': "Российская локализация - Доверенность",
|
||||
|
||||
'summary': """
|
||||
Печать доверенности на получение ТМЦ
|
||||
""",
|
||||
|
||||
'description': """
|
||||
Создание списка доверенностей на получение ТМЦ и их печать.
|
||||
|
||||
Создание доверенности:
|
||||
1. Меню Покупки - Доверенности - кнопка "Создать";
|
||||
2. На форме указываем:
|
||||
2.1. Контрагент - поставщик;
|
||||
2.2. Заказ на закупку;
|
||||
2.3. Даты действия доверенности ("дата выдачи" и "действительно по").
|
||||
|
||||
Для печати:
|
||||
1. Меню Настройки - Техническое - Отчеты;
|
||||
2. Находим в списке l10n_ru_attorney и добавляем в меню "Печать";
|
||||
3. Открываем созданную запись доверенности - Действие - "Доверенность".
|
||||
""",
|
||||
|
||||
'author': "MK.Lab",
|
||||
'website': "https://www.inf-centre.ru/",
|
||||
|
||||
'category': 'Uncategorized',
|
||||
'version': '0.1',
|
||||
|
||||
# any module necessary for this one to work correctly
|
||||
'depends': ['base', 'account', 'sale', 'purchase', 'hr', 'l10n_ru_base'],
|
||||
|
||||
# always loaded
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'views/base_consent_views.xml',
|
||||
'views/hr_employee_views.xml',
|
||||
'views/purchase_order_views.xml',
|
||||
'report/consent_report.xml',
|
||||
],
|
||||
}
|
5
l10n_ru_attorney/models/__init__.py
Normal file
5
l10n_ru_attorney/models/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import base_consent
|
||||
from . import hr_employee
|
||||
from . import purchase_order
|
BIN
l10n_ru_attorney/models/__init__.pyc
Normal file
BIN
l10n_ru_attorney/models/__init__.pyc
Normal file
Binary file not shown.
46
l10n_ru_attorney/models/base_consent.py
Normal file
46
l10n_ru_attorney/models/base_consent.py
Normal file
@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
class BaseConsent(models.Model):
|
||||
_name = 'base.consent'
|
||||
_inherit = ['mail.thread', 'utm.mixin']
|
||||
_description = 'Consent'
|
||||
_order = 'date_from desc'
|
||||
|
||||
name = fields.Char(string=_('Номер'))
|
||||
date_from = fields.Date(string=_('Дата выдачи'), default=lambda self: fields.Datetime.now())
|
||||
date_to = fields.Date(string=_('Действительна по'), default=lambda self: datetime.today() + timedelta(days=180))
|
||||
partner_id = fields.Many2one('res.partner', string=_('Контрагент'), required=1)
|
||||
employee_id = fields.Many2one('hr.employee', string=_('Сотрудник'), required=1)
|
||||
purchaseorder_id = fields.Many2one('purchase.order', _('Заказ на закупку'), domain="[('partner_id','=',partner_id)]",
|
||||
required=1)
|
||||
company_id = fields.Many2one('res.company', string=_('Компания'),
|
||||
default=lambda self: self.env['res.company']._company_default_get('base.consent'),
|
||||
required=1)
|
||||
|
||||
@api.model
|
||||
def create(self, val):
|
||||
name = self.env['ir.sequence'].next_by_code('base.consent')
|
||||
if name:
|
||||
if 'name' in val:
|
||||
if val['name'] == False:
|
||||
val.update({
|
||||
'name': name,
|
||||
})
|
||||
|
||||
result = super(BaseConsent, self).create(val)
|
||||
return result
|
||||
|
||||
@api.onchange('purchaseorder_id')
|
||||
def set_partner(self):
|
||||
if self.purchaseorder_id:
|
||||
self.partner_id = self.purchaseorder_id.partner_id
|
||||
|
||||
@api.constrains('purchaseorder_id')
|
||||
def fill_order(self):
|
||||
p_orders = self.env['purchase.order'].sudo().browse(self.purchaseorder_id.id)
|
||||
for order in p_orders:
|
||||
order.consent_id = self.id
|
19
l10n_ru_attorney/models/hr_employee.py
Normal file
19
l10n_ru_attorney/models/hr_employee.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import fields, models, _
|
||||
|
||||
|
||||
class HrEmployee(models.Model):
|
||||
_inherit = 'hr.employee'
|
||||
|
||||
inn = fields.Char(string=_("ИНН"))
|
||||
pass_kem = fields.Char(string=_("Кем выдан паспорт"))
|
||||
pass_date = fields.Date(string=_('Дата выдачи паспорта'))
|
||||
|
||||
class HrEmployeePublic(models.Model):
|
||||
_inherit = 'hr.employee.public'
|
||||
|
||||
inn = fields.Char(related='employee_id.inn', readonly = True)
|
||||
pass_kem = fields.Char(related='employee_id.pass_kem', readonly = True)
|
||||
pass_date = fields.Date(related='employee_id.pass_date', readonly = True)
|
||||
|
9
l10n_ru_attorney/models/purchase_order.py
Normal file
9
l10n_ru_attorney/models/purchase_order.py
Normal file
@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import fields, models, _
|
||||
|
||||
|
||||
class PurchaseOrder(models.Model):
|
||||
_inherit = 'purchase.order'
|
||||
|
||||
consent_id = fields.Many2one('base.consent', string=_('Доверенность'))
|
303
l10n_ru_attorney/report/consent_report.xml
Normal file
303
l10n_ru_attorney/report/consent_report.xml
Normal file
@ -0,0 +1,303 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<report
|
||||
string="Доверенность"
|
||||
id="action_report_consent"
|
||||
model="base.consent"
|
||||
report_type="qweb-pdf"
|
||||
name="l10n_ru_attorney.report_consent"
|
||||
file="l10n_ru_attorney.report_consent"
|
||||
/>
|
||||
|
||||
<record model="ir.actions.report" id="l10n_ru_attorney.action_report_consent">
|
||||
<field name="name">Доверенность</field>
|
||||
<field name="model">base.consent</field>
|
||||
<field name="print_report_name">(u'Доверенность - %s.pdf' % (object.name))</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">l10n_ru_attorney.report_consent</field>
|
||||
</record>
|
||||
|
||||
<record id="paperformat_a4new" model="report.paperformat">
|
||||
<field name="name">A4</field>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="format">A4</field>
|
||||
<field name="page_height">0</field>
|
||||
<field name="page_width">0</field>
|
||||
<field name="orientation">Portrait</field>
|
||||
<field name="margin_top">15</field>
|
||||
<field name="margin_bottom">15</field>
|
||||
<field name="margin_left">7</field>
|
||||
<field name="margin_right">7</field>
|
||||
<field name="header_line" eval="False"/>
|
||||
<field name="header_spacing">10</field>
|
||||
<field name="dpi">90</field>
|
||||
</record>
|
||||
|
||||
<template id="l10n_ru_attorney.report_consent">
|
||||
<t t-call="web.basic_layout">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<div class="page">
|
||||
<style type="text/css">
|
||||
/*----------------Invoice classes-------------------*/
|
||||
body { background: #ffffff; font-family: Arial; font-size: 8pt; font-style: normal; }
|
||||
p { font-family: Arial; font-size: 13px; }
|
||||
.tb-numbers { width: 600px; }
|
||||
.tb-numbers td { padding: 4px 10px; font-family: Arial; }
|
||||
.tb-numbers label {display: inline-block;padding: 4px 0px 0px;line-height: 20px;font-size:
|
||||
12px;font-family: Arial;}
|
||||
.tb-numbers input {width: 100px;}
|
||||
.company-info {width: 100%;margin: 20px auto;}
|
||||
.company-info td {padding: 5px 2px;font-size: 13px;font-family: Arial;}
|
||||
.approver-info {width: 100%;margin: 20px auto;text-align: center;}
|
||||
.approver-info .director {font-weight: bold;}
|
||||
.approver-info .title {font-weight: bold;font-size: 18px;padding-bottom: 20px;}
|
||||
.approver-info .signature {font-size: 11px;padding-top: 40px;}
|
||||
.actDate {float: right;}
|
||||
.actDescription {width: 100%;padding-top: 30px;}
|
||||
.act-info p {font-weight: bold;}
|
||||
.buyer-box {width: 50%;}
|
||||
.buyer-box table {width: 100%;}
|
||||
.buyer-box .tb-info {width: 310px;}
|
||||
.buyer-box .tb-info td {padding: 2px 5px;}
|
||||
.buyer-box .tb-info td.lbl {text-align: right;font-weight: bold;width: 40%;}
|
||||
.tb-invoice {width: 100%;border-collapse: collapse;}
|
||||
.tb-invoice td {padding: 2px 4px;border: 1px solid #ccc;font-size: 11px;text-align:
|
||||
center;font-family: Arial;}
|
||||
.tb-invoice td input {border: 0px;text-align: center;}
|
||||
.tb-invoice .head td {background: #f3f3f3;font-weight: bold;}
|
||||
.deleteRow {color: Red;font-size: 13px;font-weight: bold;cursor: pointer;}
|
||||
.tb-act {width: 100%;border-collapse: collapse;margin-bottom: 15px;clear: both;margin: 20px
|
||||
0px 10px 0px;}
|
||||
.tb-act td {padding: 2px 4px;border: 1px solid #ccc;font-size:
|
||||
13px;text-align:center;font-family: Arial;}
|
||||
.tb-act td input {border: 0px;text-align:center;}
|
||||
.tb-act .head td {background:#f3f3f3;}
|
||||
.tb-act td .deleteActRow {color: Red;font-size :13 px;font-weight:bold;cursor:pointer;}
|
||||
.description {font-size :12 px;text-align :justify;text-indent :1.5 em;white-space
|
||||
:pre-wrap;}
|
||||
.tb-total {width :405 px;margin: 30px 0px 20px auto;}
|
||||
.tb-total td {padding: 2px 5px;font-size :12 px;}
|
||||
.tb-total td.lbl {font-weight:bold;text-align:right;}
|
||||
.tb-total td.val {border :1 px solid #ccc ;min-width :50 px ;}
|
||||
.tb-total td input {padding :1 px ;font-size :11 px ;}
|
||||
.act-link-addrow-container {margin-bottom :30 px ;}
|
||||
.link-addrow, .act-link-addrow {text-decoration:none !important ;border-bottom :1 px dashed
|
||||
#777 ;font-size :13 px ;}
|
||||
.btn-box {margin: 10px 0px;}
|
||||
.signer-box {width: 400px;}
|
||||
.buyer-box .tb-info {width: 400px;}
|
||||
.btn-box a {font-size: 14px;margin-left: 10px;}
|
||||
.podpis-box {clear: both;display: inline-block;font-size: 11px;margin: 20px auto 30px;width:
|
||||
100%;}
|
||||
.tb-podpis {width: 100%;}
|
||||
.podpis-box .box1 {float: left;width: 48%;}
|
||||
|
||||
/*SIGNATURES PLACE BEGIN*/
|
||||
.signatures-box {clear: both;display: inline-block;font-size: 11px;margin: 20px auto
|
||||
30px;width: 100%;}
|
||||
.signatures-box .box1 {float: left;width: 35%;}
|
||||
.signatures-box .box2 {float: right;width: 35%;}
|
||||
.signatures-box .box1 table,
|
||||
.signatures-box .box2 table { width: 100%; }
|
||||
.signatures-box table td { padding: 3px; text-align: center; }
|
||||
|
||||
/*SIGNATURES PLACE END*/
|
||||
.podpis-box .box2 { float: right; width: 48%; }
|
||||
.podpis-box .box1 table,
|
||||
.podpis-box .box2 table { width: 100%; }
|
||||
.podpis-box table td { padding: 3px; text-align: center; }
|
||||
.special-line { border-bottom: 1px solid #000; display: block; line-height: 22px
|
||||
!important;text-align: center; }
|
||||
.w120 { width: 120px; }
|
||||
.w130 { width: 130px; }
|
||||
.note { font-size: 11px !important; }
|
||||
.l { text-align: left !important; }
|
||||
.r { text-align: right !important; }
|
||||
.c { text-align: center !important; }
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<h4 style="text-align:center; margin:10px 5px 5px;">
|
||||
Доверенность №
|
||||
<span t-field="o.name"/>
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<table style="width:55%">
|
||||
<tr>
|
||||
<td>Дата выдачи:</td>
|
||||
<td>
|
||||
<span t-field="o.date_from" t-options="{"widget": "date"}"/>
|
||||
г.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Доверенность действительна по:</td>
|
||||
<td>
|
||||
<span t-field="o.date_from" t-options="{"widget": "date"}"/>
|
||||
г.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="special-line" style="width:100%;margin-top:15px;text-align:center">
|
||||
<b>
|
||||
<span t-field="o.company_id.name"/>, адрес:<span t-field="o.company_id.street"/>, ИНН
|
||||
<span t-field="o.company_id.vat"/>,
|
||||
</b>
|
||||
</div>
|
||||
<div style="margin:0 auto;text-align:center;">наименование предприятия и его адрес</div>
|
||||
<table style="width:100%;margin-top:10px">
|
||||
<tr>
|
||||
<td style="width:30%">
|
||||
Доверенность выдана
|
||||
</td>
|
||||
<td style="width:100%;text-align:center;">
|
||||
<span style="border-bottom:1px solid;display:block;clear:both;text-align:center;">
|
||||
<span t-field="o.employee_id"/>,<span t-field="o.employee_id.job_id.name"/>, ИНН
|
||||
<span t-field="o.employee_id.inn"/>
|
||||
</span>
|
||||
<span style="">
|
||||
должность и Ф.И.О.
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td>Паспорт серия и №
|
||||
|
||||
<span style="padding:0 5px 0 5px;margin-left:12px;margin-right:12px;display:inline-table;"
|
||||
class="special-line">
|
||||
<span t-field="o.employee_id.passport_id"/>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Кем выдан
|
||||
<span style="padding:0 5px 0 5px;margin-left:12px;margin-right:12px;display:inline-table;"
|
||||
class="special-line">
|
||||
<span t-field="o.employee_id.pass_kem"/>
|
||||
</span>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Дата выдачи
|
||||
<span style="padding:0 5px 0 5px;margin-left:12px;margin-right:12px;display:inline-table;"
|
||||
class="special-line">
|
||||
<span t-field="o.employee_id.pass_date"/>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td style="width:25%">
|
||||
На получение от
|
||||
</td>
|
||||
<td style="width:75%;text-align:center;">
|
||||
<span style="border-bottom:1px solid;display:block;clear:both;">
|
||||
<span t-field="o.partner_id"/>
|
||||
</span>
|
||||
<span style="">
|
||||
наименование поставщика
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:25%">
|
||||
Материальных ценностей по
|
||||
</td>
|
||||
<td style="width:75%;text-align:center;">
|
||||
<span style="border-bottom:1px solid;display:block;clear:both;">
|
||||
Заказу на закупку №
|
||||
<span t-field="o.purchaseorder_id.name"/>
|
||||
от
|
||||
<span t-field="o.purchaseorder_id.date_order"
|
||||
t-options="{"widget": "date"}"/>
|
||||
г.
|
||||
</span>
|
||||
<span style="">
|
||||
наименование, номер и дата документа
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<h4 style="text-align:center; margin:15px 5px 15px;">
|
||||
Перечень материальных ценностей,
|
||||
<br/>
|
||||
подлежащих получению
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<table class="tb-invoice">
|
||||
<tr class="head">
|
||||
<td></td>
|
||||
<td style="min-width:200px;">Наименование товаров (работ, услуг)</td>
|
||||
<td>Ед. изм.</td>
|
||||
<td>Количество</td>
|
||||
</tr>
|
||||
<t t-set="num" t-value="1"/>
|
||||
<t t-foreach="o.purchaseorder_id.order_line" t-as="line">
|
||||
<tr class="data-row">
|
||||
<td>
|
||||
<t t-esc="num"/>
|
||||
</td>
|
||||
<td class="l" style="white-space: pre-wrap;">
|
||||
<span t-field="line.name"/>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="line.product_uom"/>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="line.product_qty"/>
|
||||
</td>
|
||||
</tr>
|
||||
<t t-set="num" t-value="num+1"/>
|
||||
</t>
|
||||
</table>
|
||||
|
||||
<div class="clear h100"></div>
|
||||
<div>
|
||||
<p></p>
|
||||
<p>Подпись лица, получившего доверенность ___________________ удостоверяем</p>
|
||||
</div>
|
||||
<div class="podpis-box">
|
||||
<table style="width:50%;">
|
||||
<tr>
|
||||
<td style="width: 13%;">Руководитель предприятия</td>
|
||||
<td style="width: 19%; vertical-align: bottom;">
|
||||
<span class="special-line"></span>
|
||||
<span class="note">(подпись)</span>
|
||||
</td>
|
||||
<td style="width: 16%; vertical-align: bottom;">
|
||||
<span class="special-line"></span>
|
||||
<span class="note">(Ф.И.О)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 13%;">Гл. бухгалтер:</td>
|
||||
<td style="width: 19%; vertical-align: bottom;">
|
||||
<span class="special-line"></span>
|
||||
<span class="note">(подпись)</span>
|
||||
</td>
|
||||
<td style="width: 16%; vertical-align: bottom;">
|
||||
<span class="special-line"></span>
|
||||
<span class="note">(Ф.И.О)</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
2
l10n_ru_attorney/security/ir.model.access.csv
Normal file
2
l10n_ru_attorney/security/ir.model.access.csv
Normal file
@ -0,0 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_base_consent,base.consent,model_base_consent,base.group_user,1,1,1,1
|
|
66
l10n_ru_attorney/views/base_consent_views.xml
Normal file
66
l10n_ru_attorney/views/base_consent_views.xml
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="base_consent_tree" model="ir.ui.view">
|
||||
<field name="name">Consents</field>
|
||||
<field name="model">base.consent</field>
|
||||
<field name="arch" type="xml">
|
||||
<list>
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="base_consent_form" model="ir.ui.view">
|
||||
<field name="name">consent.form</field>
|
||||
<field name="model">base.consent</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header></header>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" placeholder="Для автонумерации оставьте пустым"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="employee_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
<field name="purchaseorder_id"/>
|
||||
<field name="company_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<chatter/>
|
||||
<!-- <div class="oe_chatter">-->
|
||||
<!-- <field name="message_follower_ids" widget="mail_followers"/>-->
|
||||
<!-- <field name="message_ids" widget="mail_thread"/>-->
|
||||
<!-- </div>-->
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="l10n_ru_attorney.action_consent" model="ir.actions.act_window">
|
||||
<field name="name">Доверенности</field>
|
||||
<field name="res_model">base.consent</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="l10n_ru_attorney.menu_1" name="Доверенности" parent="purchase.menu_purchase_root"
|
||||
action="l10n_ru_attorney.action_consent"/>
|
||||
|
||||
<record id="seq_consent" model="ir.sequence">
|
||||
<field name="name">Consents</field>
|
||||
<field name="code">base.consent</field>
|
||||
<field name="prefix">CON</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
19
l10n_ru_attorney/views/hr_employee_views.xml
Normal file
19
l10n_ru_attorney/views/hr_employee_views.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="view_employee_form" model="ir.ui.view">
|
||||
<field name="name">view_employee_form.inherit</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr.view_employee_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='bank_account_id']" position="after">
|
||||
<field name="inn"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='passport_id']" position="after">
|
||||
<field name="pass_kem"/>
|
||||
<field name="pass_date"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
16
l10n_ru_attorney/views/purchase_order_views.xml
Normal file
16
l10n_ru_attorney/views/purchase_order_views.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="purchase_order_form" model="ir.ui.view">
|
||||
<field name="name">purchase.order.form.inherit</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="inherit_id" ref="purchase.purchase_order_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='incoterm_id']" position="after">
|
||||
<field name="consent_id" context="{'default_partner_id':partner_id,'default_purchaseorder_id':id}"
|
||||
domain="[('purchaseorder_id','=',id)]"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
16
l10n_ru_base/README.md
Normal file
16
l10n_ru_base/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Российская локализация - Базовый
|
||||
name: l10n_ru_base
|
||||
|
||||
## Описание
|
||||
Российская локализация: основные отчеты и печатные формы. Это базовый модуль для работы с модулями локализации.
|
||||
|
||||
###Для включения модулей:
|
||||
1. Меню Настройки - в боковом меню "Российская локализация";
|
||||
2. Выбирается нужный блок для подключения дополнительных возможностей по локализации.
|
||||
|
||||
###Перечень модулей локализации:
|
||||
1. Российская локализация - Акт сверки (l10n_ru_act_rev)
|
||||
2. Российская локализация - Доверенность (l10n_ru_attorney)
|
||||
3. Российская локализация - Договоры (l10n_ru_contract)
|
||||
4. Российская локализация - Документы (l10n_ru_doc)
|
||||
5. Российская локализация - УПД в xml-формате (l10n_ru_upd_xml)
|
2
l10n_ru_base/__init__.py
Normal file
2
l10n_ru_base/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from . import models
|
||||
|
28
l10n_ru_base/__manifest__.py
Normal file
28
l10n_ru_base/__manifest__.py
Normal file
@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': "Российская локализация - Базовый>",
|
||||
'summary': """
|
||||
Российская локализация: основные отчеты и печатные формы.
|
||||
""",
|
||||
|
||||
'description': """
|
||||
Российская локализация: основные отчеты и печатные формы.
|
||||
|
||||
Для включения модулей:
|
||||
1. Меню Настройки - в боковом меню "Российская локализация"
|
||||
2. Выбирается нужный блок.
|
||||
""",
|
||||
|
||||
'author': "MK.Lab",
|
||||
'website': "https://www.inf-centre.ru/",
|
||||
|
||||
'version': '18.0.1.0.0',
|
||||
'license': 'LGPL-3',
|
||||
'category': 'Uncategorized',
|
||||
|
||||
'depends': ["account", "portal", "website", 'contacts','base', 'mail', 'sale', 'purchase', 'hr','sale_management', 'sale_stock', 'uom','web'],
|
||||
|
||||
'data': [
|
||||
'views/res_config_settings_views.xml',
|
||||
],
|
||||
}
|
117
l10n_ru_base/i18n/ru_RU.po
Normal file
117
l10n_ru_base/i18n/ru_RU.po
Normal file
@ -0,0 +1,117 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * l10n_ru_base
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-12-17 06:36+0000\n"
|
||||
"PO-Revision-Date: 2024-12-17 06:36+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: l10n_ru_base
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ru_base/models/res_config_settings.py:0
|
||||
#: model:ir.model.fields,field_description:l10n_ru_base.field_res_config_settings__module_l10n_ru_act_rev
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
msgid "Act revise"
|
||||
msgstr "Акт сверки"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ru_base/models/res_config_settings.py:0
|
||||
#: model:ir.model.fields,field_description:l10n_ru_base.field_res_config_settings__module_act_revise
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
#, python-format
|
||||
msgid "Act revise"
|
||||
msgstr "Акт сверки"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model:ir.model.fields,field_description:l10n_ru_base.field_res_config_settings__company_status_rf
|
||||
msgid "Company Status Rf"
|
||||
msgstr "Статус компании"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model:ir.model,name:l10n_ru_base.model_res_config_settings
|
||||
msgid "Config Settings"
|
||||
msgstr "Параметры конфигурации"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ru_base/models/res_config_settings.py:0
|
||||
#: model:ir.model.fields,field_description:l10n_ru_base.field_res_config_settings__module_fehu_base_consent
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
#, python-format
|
||||
msgid "Consent"
|
||||
msgstr "Доверенность"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ru_base/models/res_config_settings.py:0
|
||||
#: model:ir.model.fields,field_description:l10n_ru_base.field_res_config_settings__module_contract
|
||||
#, python-format
|
||||
msgid "Contract"
|
||||
msgstr "Договор"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
msgid "Contracts"
|
||||
msgstr "Договоры"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
msgid "Powers of attorney"
|
||||
msgstr "Доверенность на получение ТМЦ"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ru_base/models/res_config_settings.py:0
|
||||
#: model:ir.model.fields,field_description:l10n_ru_base.field_res_config_settings__module_l10n_ru_doc
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
#, python-format
|
||||
msgid "Print forms"
|
||||
msgstr "Печатные формы"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
msgid "Report act revise"
|
||||
msgstr "Отчет Акт сверки"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
msgid "Report contract"
|
||||
msgstr "Договоры"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
msgid "Report report_xml"
|
||||
msgstr "УПД в формате xml для ЭДО"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ru_base/models/res_config_settings.py:0
|
||||
#: model:ir.model.fields,field_description:l10n_ru_base.field_res_config_settings__module_report_xml
|
||||
#, python-format
|
||||
msgid "Report_xml"
|
||||
msgstr "Универсальный передаточный документ (УПД) в формате xml для ЭДО"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
msgid "Russian Localization"
|
||||
msgstr "Российская локализация"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
msgid "UPD xml"
|
||||
msgstr "УПД в формате xml для ЭДО"
|
||||
|
||||
#. module: l10n_ru_base
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ru_base.res_config_settings_view_form
|
||||
msgid "print_forms"
|
||||
msgstr "Печатные формы документов"
|
4
l10n_ru_base/models/__init__.py
Normal file
4
l10n_ru_base/models/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from . import res_config_settings
|
||||
|
||||
|
||||
|
46
l10n_ru_base/models/res_config_settings.py
Normal file
46
l10n_ru_base/models/res_config_settings.py
Normal file
@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
import logging
|
||||
|
||||
_FIELDS_MODUL = [
|
||||
'module_l10n_ru_act_rev',
|
||||
'module_l10n_ru_contract',
|
||||
'module_l10n_ru_upd_xml',
|
||||
'module_l10n_ru_doc',
|
||||
'module_l10n_ru_attorney'
|
||||
]
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
module_l10n_ru_act_rev = fields.Boolean(_("Act revise"))
|
||||
module_l10n_ru_contract = fields.Boolean(_("Contract"))
|
||||
module_l10n_ru_upd_xml = fields.Boolean(_("Report_xml"))
|
||||
module_l10n_ru_doc = fields.Boolean(_("Print forms"))
|
||||
module_l10n_ru_attorney = fields.Boolean(_("Consent"))
|
||||
|
||||
@api.model
|
||||
def write(self, values):
|
||||
if any(field in values for field in _FIELDS_MODUL):
|
||||
company = self.env.company
|
||||
if company.country_id.code != 'RU':
|
||||
raise UserError("Признак Российской компании не обнаружен!")
|
||||
|
||||
if _FIELDS_MODUL:
|
||||
missing_modules = set()
|
||||
for field in _FIELDS_MODUL:
|
||||
mapped_values = self.mapped(field)
|
||||
if mapped_values and mapped_values[0]:
|
||||
module_name = field[7:]
|
||||
module_installed = self.env['ir.module.module'].search([('name', '=', module_name)], limit=1)
|
||||
if not module_installed:
|
||||
missing_modules.add(module_name)
|
||||
if missing_modules:
|
||||
message = "Обратитесь в тех.поддержку для получения лицензии для следующих модулей:\n" + \
|
||||
"\n".join(missing_modules)
|
||||
raise UserError(message)
|
||||
return super(ResConfigSettings, self).write(values)
|
BIN
l10n_ru_base/static/description/icon.png
Normal file
BIN
l10n_ru_base/static/description/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
42
l10n_ru_base/views/res_config_settings_views.xml
Normal file
42
l10n_ru_base/views/res_config_settings_views.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.russian.localization</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="priority" eval="5"/>
|
||||
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//form" position="inside">
|
||||
<app data-string="Russian Localization" string="Russian Localization" name="base_russian_localization" img="l10n_ru_base/static/description/icon.png">
|
||||
<block title="Act revise" name="act_revise_setting_container">
|
||||
<setting id="act_revise" string="Act revise" help="Report act revise">
|
||||
<field name="module_l10n_ru_act_rev"/>
|
||||
</setting>
|
||||
</block>
|
||||
<block title="Contracts" name="contract_setting_container">
|
||||
<setting id="contract" string="Contracts" help="Report contract">
|
||||
<field name="module_l10n_ru_contract"/>
|
||||
</setting>
|
||||
</block>
|
||||
<block title="UPD xml" name="upd_xml_setting_container">
|
||||
<setting id="report_xml" string="UPD xml" help="Report report_xml">
|
||||
<field name="module_l10n_ru_upd_xml"/>
|
||||
</setting>
|
||||
</block>
|
||||
<block title="Print forms" name="print_forms_setting_container">
|
||||
<setting id="print_forms" string="Print forms" help="print_forms">
|
||||
<field name="module_l10n_ru_doc"/>
|
||||
</setting>
|
||||
</block>
|
||||
<block title="Consent" name="powers_attorney_setting_container">
|
||||
<setting id="powers_attorney" string="Consent" help="Powers of attorney">
|
||||
<field name="module_l10n_ru_attorney"/>
|
||||
</setting>
|
||||
</block>
|
||||
</app>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
30
l10n_ru_contract/README.md
Normal file
30
l10n_ru_contract/README.md
Normal file
@ -0,0 +1,30 @@
|
||||
# Российская локализация - Договоры
|
||||
name: l10n_ru_contract
|
||||
|
||||
|
||||
## Описание
|
||||
Создание договоров с клиентами и поставщиками в системе.
|
||||
Возможность разделения договоров на виды, отслеживание статуса договора. Вы также можете распечатать договор из системы.
|
||||
|
||||
### Создание вида договора клиента(поставщика):
|
||||
1. Меню Продажи (Покупки) - Договоры - Виды договора - кнопка "Создать";
|
||||
2. На форме указываем:
|
||||
|
||||
2.1. Журнал и счета дебетовой и кредиторской задолженности;
|
||||
|
||||
2.2. Присваиваем новое название.
|
||||
|
||||
### Создание договора клиента (поставщика):
|
||||
1. Меню Продажи (Покупки) - Договоры - кнопка "Создать";
|
||||
2. На форме указываем основные и дополнительные условия договора:
|
||||
|
||||
2.1. Контрагент - клиент (поставщик);
|
||||
|
||||
2.2. Тип контрагента;
|
||||
|
||||
2.3. Компанию, от лица которой будет подписан договор;
|
||||
|
||||
2.4. Вид договора.
|
||||
|
||||
### Для печати:
|
||||
1. Открываем созданную запись договора - Действие - "Договор".
|
3
l10n_ru_contract/__init__.py
Normal file
3
l10n_ru_contract/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import models
|
||||
from . import report
|
52
l10n_ru_contract/__manifest__.py
Normal file
52
l10n_ru_contract/__manifest__.py
Normal file
@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': 'Российская локализация - Договоры',
|
||||
'summary': """
|
||||
Создание договоров, их видов и печать
|
||||
""",
|
||||
|
||||
'description': """
|
||||
Создание договоров с клиентами и поставщиками. Возможность разделения на виды договоров, отслеживание статуса договора и его печатью
|
||||
Создание вида договора клиента(поставщика):
|
||||
1. Меню Продажи (Покупки) - Договоры - Виды договора - кнопка "Создать";
|
||||
2. На форме указываем:
|
||||
2.1. Журнал и счета дебетовой и кредиторской задолженности;
|
||||
2.2. Присваиваем новое название.
|
||||
|
||||
Создание договора клиента (поставщика):
|
||||
1. Меню Продажи (Покупки) - Договоры - кнопка "Создать";
|
||||
2. На форме указываем основные и дополнительные условия договора:
|
||||
2.1. Контрагент - клиент (поставщик);
|
||||
2.2. Тип контрагента;
|
||||
2.3. Компанию, от лица которой будет подписан договор;
|
||||
2.4. Вид договора.
|
||||
|
||||
Для печати:
|
||||
1. Открываем созданную запись договора - Действие - "Договор".
|
||||
""",
|
||||
|
||||
'version': '18.0.1.0.0',
|
||||
'sequence': 0,
|
||||
'author': 'MK.Lab',
|
||||
'website': 'https://www.inf-centre.ru/',
|
||||
'external_dependencies': {
|
||||
'python': ['pymorphy2'],
|
||||
},
|
||||
'depends': [
|
||||
'base',
|
||||
'mail',
|
||||
'account', 'sale', 'sale_management', 'purchase', 'l10n_ru_base'
|
||||
],
|
||||
'data': [
|
||||
'data/data.xml',
|
||||
'views/contract_customer_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'report/report_contract.xml',
|
||||
'report/report_contract_order.xml',
|
||||
'report/report_contract_order1.xml',
|
||||
'report/report_contract_invoice.xml',
|
||||
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
}
|
21
l10n_ru_contract/data/data.xml
Normal file
21
l10n_ru_contract/data/data.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="contract_customer_sequence" model="ir.sequence">
|
||||
<field name="name">Договор последовательность клиент</field>
|
||||
<field name="code">partner.contract.customer.sequence</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
<field eval="True" name="use_date_range"/>
|
||||
<field name="padding">5</field>
|
||||
</record>
|
||||
<record id="contract_supplier_sequence" model="ir.sequence">
|
||||
<field name="name">Договор последовательность поставщик</field>
|
||||
<field name="code">partner.contract.supplier.sequence</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
<field eval="True" name="use_date_range"/>
|
||||
<field name="padding">5</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
9
l10n_ru_contract/models/__init__.py
Normal file
9
l10n_ru_contract/models/__init__.py
Normal file
@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_move
|
||||
from . import contract_customer
|
||||
from . import crutch_fields_header
|
||||
from . import dop_field
|
||||
from . import purchase_order
|
||||
from . import sale_make_invoice_advance
|
||||
from . import sale_order
|
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-35.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-35.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-36.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-36.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-37.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-37.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-38.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-38.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/__init__.cpython-39.pyc
Normal file
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-310.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-310.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-311.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-311.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-36.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-36.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-37.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-37.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-38.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-38.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-39.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/dop_field.cpython-39.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/models/__pycache__/report_helper.cpython-36.pyc
Normal file
BIN
l10n_ru_contract/models/__pycache__/report_helper.cpython-36.pyc
Normal file
Binary file not shown.
50
l10n_ru_contract/models/account_move.py
Normal file
50
l10n_ru_contract/models/account_move.py
Normal file
@ -0,0 +1,50 @@
|
||||
from odoo import api, fields, models, exceptions, _
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_inherit = 'account.move'
|
||||
|
||||
mt_contract_id = fields.Many2one('partner.contract.customer', string=_('Номер договора'))
|
||||
sf_number = fields.Char(string=_('Номер с/ф'))
|
||||
osnovanie = fields.Char(string=_('Основание'))
|
||||
sec_partner_id = fields.Many2one('res.partner', string=_('Контрагент'), store=True, compute='_compute_get_pid')
|
||||
stamp = fields.Boolean(string=_('Печать и подпись'), related='mt_contract_id.stamp')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_get_pid(self):
|
||||
for s in self:
|
||||
s.sec_partner_id = s.partner_id.parent_id if s.partner_id.parent_id else s.partner_id
|
||||
|
||||
@api.onchange('mt_contract_id')
|
||||
def set_ons(self):
|
||||
if self.mt_contract_id:
|
||||
self.osnovanie = 'Договор № ' + self.mt_contract_id.name + ' от ' + fields.Datetime.from_string(
|
||||
self.mt_contract_id.date_start).strftime("%d.%m.%Y")
|
||||
|
||||
@api.constrains('state')
|
||||
def invoice_fields_check(self):
|
||||
for s in self:
|
||||
if s.state == 'posted':
|
||||
if s.mt_contract_id:
|
||||
errors_list = []
|
||||
journal_in_contract = s.mt_contract_id.profile_id.journal_id
|
||||
payment_term_in_contract = s.mt_contract_id.profile_id.payment_term_id
|
||||
receivable_in_contract = s.mt_contract_id.profile_id.receivable_account_id
|
||||
|
||||
if journal_in_contract != s.journal_id:
|
||||
errors_list.append(f'Отличается Журнал - [{s.journal_id.name}] '
|
||||
f'и указанный в договоре №{s.mt_contract_id.name} '
|
||||
f'Журнал - [{journal_in_contract.name}]\n\n')
|
||||
|
||||
if payment_term_in_contract != s.invoice_payment_term_id:
|
||||
errors_list.append(f'Отличается поле "Условие оплаты" в инвойсе '
|
||||
f'[Условие оплаты - {s.invoice_payment_term_id.name}] '
|
||||
f'и указанный в договоре №{s.mt_contract_id.name} '
|
||||
f'[Условие оплаты - {payment_term_in_contract.name}]\n\n')
|
||||
|
||||
if receivable_in_contract not in s.line_ids.account_id:
|
||||
errors_list.append(f'Отличается поле "Счет дебиторской задолженности" в инвойсе '
|
||||
f'и указанный в договоре №{s.mt_contract_id.name}')
|
||||
|
||||
if errors_list:
|
||||
raise exceptions.ValidationError(''.join(errors_list))
|
334
l10n_ru_contract/models/contract_customer.py
Normal file
334
l10n_ru_contract/models/contract_customer.py
Normal file
@ -0,0 +1,334 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import api, fields, models, exceptions, tools, _
|
||||
import pymorphy2
|
||||
from datetime import datetime, timedelta
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from .crutch_fields_header import IP_CONTACT_HEADER, ENTITY_CONTRACT_HEADER, INDIVIDUAL_CONTRACT_HEADER
|
||||
|
||||
|
||||
class PartnerContractCustomer(models.Model):
|
||||
_name = 'partner.contract.customer'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin', 'mail.render.mixin']
|
||||
|
||||
def get_dateend(self):
|
||||
if self.date_start:
|
||||
six_months = fields.Datetime.from_string(self.date_start) + relativedelta(months=+11)
|
||||
else:
|
||||
six_months = datetime.today() + relativedelta(months=+11)
|
||||
return fields.Datetime.to_string(six_months)
|
||||
|
||||
name = fields.Char(string=_('Номер'))
|
||||
date_start = fields.Date(string=_('Дата договора'), required=True, default=fields.Datetime.now())
|
||||
partner_id = fields.Many2one('res.partner', string=_('Контрагент'), required=True)
|
||||
sec_partner_id = fields.Many2one('res.partner', string=_('Контрагент как в заказе'))
|
||||
company_id = fields.Many2one('res.company', string=_('Компания'), required=True)
|
||||
name_print = fields.Char(string=_('Имя для печати'), compute='_get_name_print')
|
||||
name_print1 = fields.Char(string=_('Имя для печати, И.П.'), compute='_get_name_printip')
|
||||
date_end = fields.Date(string=_('Дата окончания'), required=True, default=get_dateend)
|
||||
name_dirprint = fields.Char(string=_('Имя нашего директора для печати'))
|
||||
name_dirprint1 = fields.Char(string=_('Имя нашего директора для печати И.П.'))
|
||||
lines = fields.One2many('contract.line', 'contract_id', string=_('Договорные цены'))
|
||||
type = fields.Selection(
|
||||
[('customer', 'С покупателем'),
|
||||
('supplier', 'С поставщиком'),
|
||||
('other', 'Прочие расчеты'),
|
||||
|
||||
],
|
||||
string=_('Тип договора'), default='customer', required=True)
|
||||
saleorder_id = fields.Many2one('sale.order', string=_('Заказ/Сделка'))
|
||||
stamp = fields.Boolean(string=_('Печать и подпись'))
|
||||
signed = fields.Boolean(string=_('Договор подписан'))
|
||||
state = fields.Selection(
|
||||
[('draft', 'Черновик'),
|
||||
('progress', 'На согласовании'),
|
||||
('signed', 'Подписан, действует'),
|
||||
('closed', 'Истёк'),
|
||||
],
|
||||
string=_('Статус'), default='draft', group_expand='_expand_states', index=True
|
||||
)
|
||||
is_template = fields.Boolean(_('Это шаблон'))
|
||||
copy_from = fields.Many2one('partner.contract.customer', string=_('Копировать из этого шаблона'))
|
||||
profile_id = fields.Many2one('contract.profile', string=_('Вид договора'), required=True)
|
||||
credit_limit = fields.Float(string=_('Лимит кредита'))
|
||||
guid_1s = fields.Char(_('Код договора из 1С'))
|
||||
buh_code = fields.Char(_('Код договора из бухгалтерии'))
|
||||
payment_term_id = fields.Many2one('account.payment.term', string=_('Условие оплаты'))
|
||||
manager_id = fields.Many2one('res.users', string=_('Менеджер по продажам'))
|
||||
accountant_id = fields.Many2one('res.users', string=_('Бухгалтер по взаиморасчетам'))
|
||||
time_to_delivery_from = fields.Datetime(_('Время доставки от'))
|
||||
time_to_delivery_to = fields.Datetime(_('Время доставки до'))
|
||||
day_of_delivery = fields.Float(_('Дни доставки'))
|
||||
day_of_otgruzki = fields.Float(_('Дни отгрузки'))
|
||||
|
||||
channel_id = fields.Many2one('saleorder.channel', string=_('Канал продаж'))
|
||||
team_id = fields.Many2one('crm.team', string=_('Команда продаж'))
|
||||
order_days_ids = fields.Many2many(comodel_name='contract.day', relation='orderdays', string=_('Дни доставки'),
|
||||
column1='contract_id', column2='day_id')
|
||||
shipment_days_ids = fields.Many2many(comodel_name='contract.day', relation='shipmentdays', string=_('Дни отгрузки'),
|
||||
column1='contract_id',
|
||||
column2='day_id')
|
||||
# Доработка хедера договора
|
||||
partner_type = fields.Selection(string=_('Тип контрагента'), selection=[
|
||||
('person', 'Физ. лицо'),
|
||||
('company_ip', 'ИП'),
|
||||
('company', 'Юр. лицо')
|
||||
], required=True)
|
||||
contract_header = fields.Html(_('Шапка договора'))
|
||||
|
||||
@api.onchange('partner_type')
|
||||
def generate_contract_header(self):
|
||||
self.ensure_one()
|
||||
self.render_model = 'partner.contract.customer'
|
||||
if self.partner_type == 'company_ip':
|
||||
self.contract_header = IP_CONTACT_HEADER
|
||||
elif self.partner_type == 'person':
|
||||
self.contract_header = INDIVIDUAL_CONTRACT_HEADER
|
||||
else:
|
||||
self.contract_header = ENTITY_CONTRACT_HEADER
|
||||
# # Рендер Jinja выражение типа {{object.field}}
|
||||
result = self._render_template(self.contract_header, self.render_model, res_ids=[self.id])
|
||||
result = tools.html_sanitize(result[self.id])
|
||||
self.contract_header = result
|
||||
|
||||
@api.onchange('sec_partner_id')
|
||||
def set_pid(self):
|
||||
self.partner_id = self.sec_partner_id.parent_id if self.sec_partner_id.parent_id else self.sec_partner_id
|
||||
|
||||
def _expand_states(self, states, domain):
|
||||
return [key for key, val in type(self).state.selection]
|
||||
|
||||
def copy_it(self):
|
||||
if self.copy_from:
|
||||
for line in self.copy_from.lines:
|
||||
line.copy({'contract_id': self.id})
|
||||
|
||||
def _get_name_print(self):
|
||||
morph = pymorphy2.MorphAnalyzer()
|
||||
self.name_print = False
|
||||
director = self.env['res.partner'].search([('parent_id', '=', self.partner_id.id), ('type', '=', 'director')],
|
||||
limit=1)
|
||||
if director:
|
||||
if len(director.name.split(' ')) == 3:
|
||||
lastname_old, firstname_old, middlename_old = director.name.split(' ')
|
||||
|
||||
if lastname_old:
|
||||
lastname_n = morph.parse(lastname_old)[0]
|
||||
if lastname_n.inflect({'gent'}):
|
||||
lastname_n = lastname_n.inflect({'gent'}).word
|
||||
else:
|
||||
lastname_n = lastname_old
|
||||
else:
|
||||
lastname_n = ''
|
||||
|
||||
if firstname_old:
|
||||
firstname_n = morph.parse(firstname_old)[0]
|
||||
firstname_n = firstname_n.inflect({'gent'}).word
|
||||
else:
|
||||
firstname_n = ''
|
||||
|
||||
if middlename_old:
|
||||
middlename_n = morph.parse(middlename_old)[0]
|
||||
middlename_n = middlename_n.inflect({'gent'}).word
|
||||
else:
|
||||
middlename_n = ''
|
||||
|
||||
name_print = lastname_n + ' ' + firstname_n + ' ' + middlename_n
|
||||
|
||||
self.name_print = name_print.title()
|
||||
|
||||
def _get_name_print1(self):
|
||||
# morph = pymorphy2.MorphAnalyzer()
|
||||
director = self.company_id.chief_id.partner_id if self.company_id.chief_id else False
|
||||
# raise exceptions.UserError(str(director))
|
||||
self.name_dirprint = False
|
||||
if director:
|
||||
if len(director.name.split(' ')) == 3:
|
||||
lastname_old, firstname_old, middlename_old = director.name.split(' ')
|
||||
|
||||
if lastname_old:
|
||||
lastname_n = morph.parse(lastname_old)[0]
|
||||
lastname_n = lastname_n.inflect({'gent'}).word
|
||||
else:
|
||||
lastname_n = ''
|
||||
|
||||
if firstname_old:
|
||||
firstname_n = morph.parse(firstname_old)[0]
|
||||
firstname_n = firstname_n.inflect({'gent'}).word
|
||||
else:
|
||||
firstname_n = ''
|
||||
|
||||
if middlename_old:
|
||||
middlename_n = morph.parse(middlename_old)[0]
|
||||
middlename_n = middlename_n.inflect({'gent'}).word
|
||||
else:
|
||||
middlename_n = ''
|
||||
|
||||
name_print = lastname_n + ' ' + firstname_n + ' ' + middlename_n
|
||||
|
||||
self.name_dirprint = name_print.title()
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
res = super(PartnerContractCustomer, self).create(values)
|
||||
|
||||
if values.get('is_template'):
|
||||
return res
|
||||
|
||||
if values.get('type') == 'customer':
|
||||
sequence_code = 'partner.contract.customer.sequence'
|
||||
elif values.get('type') == 'supplier':
|
||||
sequence_code = 'partner.contract.supplier.sequence'
|
||||
else:
|
||||
return res
|
||||
|
||||
name = self.env['ir.sequence'].next_by_code(sequence_code)
|
||||
|
||||
res.update({
|
||||
'name': name,
|
||||
})
|
||||
|
||||
return res
|
||||
|
||||
# @api.model
|
||||
def write(self, values):
|
||||
|
||||
if 'state' in values:
|
||||
if self.state != values['state']:
|
||||
msg = 'Статус: ' + dict(self._fields['state'].selection).get(self.state) + ' -> ' + dict(
|
||||
self._fields['state'].selection).get(values['state'])
|
||||
self.message_post(body=msg)
|
||||
res = super(PartnerContractCustomer, self).write(values)
|
||||
return res
|
||||
|
||||
def _get_name_print1ip(self):
|
||||
self.name_dirprint1 = self.company_id.chief_id.partner_id.name if self.company_id.chief_id else False
|
||||
|
||||
def _get_name_printip(self):
|
||||
self.name_print1 = False
|
||||
director = self.env['res.partner'].search([('parent_id', '=', self.partner_id.id), ('type', '=', 'director')],
|
||||
limit=1)
|
||||
if director:
|
||||
self.name_print1 = director.name
|
||||
|
||||
def print_supp(self):
|
||||
# self.filtered(lambda s: s.state == 'draft').write({'state': 'sent'})
|
||||
return self.env['report'].get_action(self, 'mta_base.action_mtacontractsupp_report')
|
||||
|
||||
def print_contract_cust(self):
|
||||
if self.saleorder_id:
|
||||
return self.saleorder_id.print_contract()
|
||||
else:
|
||||
raise exceptions.UserError(_(
|
||||
'Вы не можете напечатать договор с Клиентом, потому что нет связи с Заказом. Нужно зайти в Заказ и привязать этот договор.'))
|
||||
|
||||
def contract_action_confirm(self):
|
||||
if self.state == 'draft':
|
||||
self.state = 'progress'
|
||||
elif self.state == 'progress':
|
||||
self.state = 'signed'
|
||||
|
||||
def contract_in_draft(self):
|
||||
self.state = 'draft'
|
||||
|
||||
@api.onchange('name')
|
||||
def set_comp_and_partn(self):
|
||||
context = self._context
|
||||
order_id = context.get('sale_order_id')
|
||||
if order_id:
|
||||
sale_order = self.env['sale.order'].browse(order_id)
|
||||
|
||||
self.company_id = sale_order.company_id
|
||||
self.partner_id = sale_order.partner_id
|
||||
|
||||
@api.onchange('profile_id')
|
||||
def set_payment(self):
|
||||
if self.profile_id.payment_term_id:
|
||||
self.payment_term_id = self.profile_id.payment_term_id
|
||||
|
||||
# @api.constrains('name')
|
||||
def check_name(self):
|
||||
obj = self.search([('name', '=', self.name), ('id', '!=', self.id), ('state', '!=', 'closed')])
|
||||
if obj:
|
||||
raise exceptions.ValidationError(_('Договор с таким номером уже существует'))
|
||||
|
||||
"""
|
||||
@api.constrains('profile_id')
|
||||
def check_profile_id(self):
|
||||
contracts = self.search([('partner_id', '=', self.partner_id.id), ('id', '!=', self.id)])
|
||||
if contracts:
|
||||
profiles_in_contracts = contracts.profile_id
|
||||
# raise exceptions.ValidationError(profiles_in_contracts.ids)
|
||||
if profiles_in_contracts:
|
||||
ads = self.env['contract.allowed.profiles'].search(
|
||||
[('allowed_profiles', 'in', profiles_in_contracts.ids)])
|
||||
if ads:
|
||||
raise exceptions.ValidationError((self.profile_id.name, ads.name))
|
||||
# raise exceptions.ValidationError(contracts)
|
||||
"""
|
||||
|
||||
|
||||
class Partner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
contract_count = fields.Integer(string=_('Договоры'), compute='get_count_contract')
|
||||
pol = fields.Selection(string=_("Пол"), selection=[('m', 'Муж.'), ('j', 'Жен'), ], required=False)
|
||||
type = fields.Selection(selection_add=[('director', 'Директор')])
|
||||
|
||||
def get_count_contract(self):
|
||||
contract = self.env['partner.contract.customer']
|
||||
self.contract_count = contract.search_count([('partner_id', '=', self.id)])
|
||||
|
||||
def action_view_contract(self):
|
||||
action = self.env.ref('contract.contract_customer_action').read()[0]
|
||||
|
||||
action['domain'] = [('partner_id', '=', self.id)]
|
||||
|
||||
return action
|
||||
|
||||
|
||||
class ContractLine(models.Model):
|
||||
_name = 'contract.line'
|
||||
contract_id = fields.Many2one('partner.contract.customer', string='Order Reference', required=True,
|
||||
ondelete='cascade', index=True, copy=False)
|
||||
_order = "sequence desc"
|
||||
# name = fields.Text(string='Название для договора')
|
||||
# price_unit = fields.Float('Цена', default=0.0)
|
||||
# product_uom = fields.Many2one('uom.uom', string='Единица измерения')
|
||||
# product_id = fields.Many2one('product.product', string='Услуга', domain=[('sale_ok', '=', True)], change_default=True, ondelete='restrict')
|
||||
sequence = fields.Integer('Порядок')
|
||||
name = fields.Char('Номер пункта')
|
||||
punct = fields.Html('Текст пункта')
|
||||
|
||||
@api.onchange('product_id')
|
||||
def set_name(self):
|
||||
self.name = self.product_id.name
|
||||
|
||||
|
||||
class AllowedProfiles(models.Model):
|
||||
_name = 'contract.allowed.profiles'
|
||||
name = fields.Char(string=_('Одновременно включены следующие виды договоров:'))
|
||||
allowed_profiles = fields.Many2many('contract.profile', string=_('Виды договоров'), required=True)
|
||||
|
||||
@api.onchange('allowed_profiles')
|
||||
def set_name(self):
|
||||
self.name = ''
|
||||
for profile in self.allowed_profiles:
|
||||
self.name += profile.name + ' + '
|
||||
if self.name:
|
||||
if self.name[-2] == '+':
|
||||
self.name = self.name[:-2]
|
||||
|
||||
|
||||
class ContractProfile(models.Model):
|
||||
_name = 'contract.profile'
|
||||
name = fields.Char(string=_('Вид договора'), required=True)
|
||||
payable_account_id = fields.Many2one('account.account', string=_('Счет кредиторской задолженности'), required=True)
|
||||
receivable_account_id = fields.Many2one('account.account', string=_('Счет дебиторской задолженности'), required=True)
|
||||
max_receivable_id = fields.Float(string=_('Максимальная деб. задолженность'), required=True)
|
||||
payment_term_id = fields.Many2one('account.payment.term', string=_('Условие оплаты'), required=True)
|
||||
journal_id = fields.Many2one('account.journal', string=_('Журнал'), required=True)
|
||||
|
||||
|
||||
class ContractDay(models.Model):
|
||||
_name = 'contract.day'
|
||||
name = fields.Char(_('День'))
|
33
l10n_ru_contract/models/crutch_fields_header.py
Normal file
33
l10n_ru_contract/models/crutch_fields_header.py
Normal file
@ -0,0 +1,33 @@
|
||||
ENTITY_CONTRACT_HEADER = """
|
||||
<b>{{object.company_id.partner_id.name}}</b>,
|
||||
именуемое в дальнейшем <b>«Поставщик»</b>, в лице
|
||||
{{(object.company_id.chief_id.partner_id.function or '').lower()}}
|
||||
{{(object.name_dirprint1 or '').title()}},
|
||||
действующего на основании ОГРНИП № {{object.company_id.company_registry or ''}}, с одной стороны, и <b>{{object.partner_id.name or ''}}</b>,
|
||||
именуемое в дальнейшем <b>«Покупатель»</b>, в лице
|
||||
{{(object.get_function_partner1(object.partner_id.id) or '').lower()}}
|
||||
{{(object.name_print1 or '').title()}}, действующего на основании устава общества, с другой стороны, вместе именуемые в дальнейшем <b>«Стороны»</b> заключили
|
||||
настоящий Договор о нижеследующем:
|
||||
"""
|
||||
IP_CONTACT_HEADER = """
|
||||
<b>{{object.company_id.partner_id.name}}</b>,
|
||||
именуемое в дальнейшем <b>«Поставщик»</b>, в лице
|
||||
{{(object.company_id.chief_id.partner_id.function or '').lower()}}
|
||||
{{(object.name_dirprint1 or '').title()}},
|
||||
действующего на основании ОГРНИП № {{object.company_id.company_registry or ''}}, с одной стороны, и <b>{{object.partner_id.name or ''}}</b>,
|
||||
именуемое в дальнейшем <b>«Покупатель»</b>, в лице
|
||||
{{(object.get_function_partner1(object.partner_id.id) or '').lower()}}
|
||||
{{(object.name_print1 or '').title()}}, действующего на основании ОГРНИП №{{object.partner_id.ogrn or ''}},
|
||||
с другой стороны, вместе именуемые в дальнейшем <b>«Стороны»</b> заключили
|
||||
настоящий Договор о нижеследующем:
|
||||
"""
|
||||
|
||||
INDIVIDUAL_CONTRACT_HEADER = """
|
||||
<b>{{object.company_id.partner_id.name}}</b>,
|
||||
именуемое в дальнейшем <b>«Поставщик»</b>, в лице
|
||||
{{(object.company_id.chief_id.partner_id.function or '').lower()}}
|
||||
{{(object.name_dirprint1 or '').title()}},
|
||||
действующего на основании ОГРНИП № {{object.company_id.company_registry or ''}}, с одной стороны, и <b>{{object.partner_id.name or ''}}</b>,
|
||||
именуемое в дальнейшем <b>«Покупатель»</b>, вместе именуемые в дальнейшем <b>«Стороны»</b> заключили
|
||||
настоящий Договор о нижеследующем:
|
||||
"""
|
353
l10n_ru_contract/models/dop_field.py
Normal file
353
l10n_ru_contract/models/dop_field.py
Normal file
@ -0,0 +1,353 @@
|
||||
from odoo import api, fields, models, exceptions
|
||||
from datetime import datetime
|
||||
import re
|
||||
import pymorphy2
|
||||
from odoo.tools import pycompat
|
||||
|
||||
FRACTIONS = (
|
||||
(u"десятая", u"десятых", u"десятых"),
|
||||
(u"сотая", u"сотых", u"сотых"),
|
||||
(u"тысячная", u"тысячных", u"тысячных"),
|
||||
(u"десятитысячная", u"десятитысячных", u"десятитысячных"),
|
||||
(u"стотысячная", u"стотысячных", u"стотысячных"),
|
||||
(u"миллионная", u"милллионных", u"милллионных"),
|
||||
(u"десятимиллионная", u"десятимилллионных", u"десятимиллионных"),
|
||||
(u"стомиллионная", u"стомилллионных", u"стомиллионных"),
|
||||
(u"миллиардная", u"миллиардных", u"миллиардных"),
|
||||
)
|
||||
|
||||
ONES = {
|
||||
0: (u"", u"", u""),
|
||||
1: (u"один", u"одна", u"одно"),
|
||||
2: (u"два", u"две", u"два"),
|
||||
3: (u"три", u"три", u"три"),
|
||||
4: (u"четыре", u"четыре", u"четыре"),
|
||||
5: (u"пять", u"пять", u"пять"),
|
||||
6: (u"шесть", u"шесть", u"шесть"),
|
||||
7: (u"семь", u"семь", u"семь"),
|
||||
8: (u"восемь", u"восемь", u"восемь"),
|
||||
9: (u"девять", u"девять", u"девять"),
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: u"",
|
||||
10: u"десять",
|
||||
11: u"одиннадцать",
|
||||
12: u"двенадцать",
|
||||
13: u"тринадцать",
|
||||
14: u"четырнадцать",
|
||||
15: u"пятнадцать",
|
||||
16: u"шестнадцать",
|
||||
17: u"семнадцать",
|
||||
18: u"восемнадцать",
|
||||
19: u"девятнадцать",
|
||||
2: u"двадцать",
|
||||
3: u"тридцать",
|
||||
4: u"сорок",
|
||||
5: u"пятьдесят",
|
||||
6: u"шестьдесят",
|
||||
7: u"семьдесят",
|
||||
8: u"восемьдесят",
|
||||
9: u"девяносто",
|
||||
}
|
||||
|
||||
HUNDREDS = {
|
||||
0: u"",
|
||||
1: u"сто",
|
||||
2: u"двести",
|
||||
3: u"триста",
|
||||
4: u"четыреста",
|
||||
5: u"пятьсот",
|
||||
6: u"шестьсот",
|
||||
7: u"семьсот",
|
||||
8: u"восемьсот",
|
||||
9: u"девятьсот",
|
||||
}
|
||||
|
||||
MALE = 1
|
||||
FEMALE = 2
|
||||
|
||||
import operator
|
||||
import sys
|
||||
import types
|
||||
|
||||
PY2 = sys.version_info[0] == 2
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
string_types = str,
|
||||
integer_types = int,
|
||||
class_types = type,
|
||||
text_type = str
|
||||
binary_type = bytes
|
||||
|
||||
MAXSIZE = sys.maxsize
|
||||
else:
|
||||
string_types = basestring,
|
||||
integer_types = (int, long)
|
||||
class_types = (type, types.ClassType)
|
||||
text_type = unicode
|
||||
binary_type = str
|
||||
|
||||
|
||||
class Partner_Bank(models.Model):
|
||||
_inherit = 'res.partner.bank'
|
||||
bank_corr_acc = fields.Char('Кор.счет')
|
||||
|
||||
|
||||
# class Bank(models.Model):
|
||||
# _inherit = 'res.bank'
|
||||
|
||||
# corr_acc = fields.Char('Corresponding account', size=64)
|
||||
|
||||
# class Users(models.Model):
|
||||
# _inherit = 'res.users'
|
||||
|
||||
# facsimile = fields.Binary("Facsimile")
|
||||
|
||||
class Company(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
inn = fields.Char(related='partner_id.inn', readonly=False)
|
||||
kpp = fields.Char(related='partner_id.kpp', readonly=False)
|
||||
okpo = fields.Char(related='partner_id.okpo', readonly=False)
|
||||
chief_id = fields.Many2one('res.users', 'Имя директора')
|
||||
stamp = fields.Binary("Stamp")
|
||||
|
||||
|
||||
class Partner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
ogrn = fields.Char('ОГРН')
|
||||
okpo = fields.Char('ОКПО')
|
||||
inn = fields.Char('ИНН')
|
||||
kpp = fields.Char('KPP')
|
||||
passport = fields.Char('Паспорт')
|
||||
|
||||
|
||||
class Report_contract_customer(models.Model):
|
||||
_inherit = 'partner.contract.customer'
|
||||
|
||||
def img(self, img, type='png', width=0, height=0):
|
||||
if width:
|
||||
width = "width='%spx'" % (width)
|
||||
else:
|
||||
width = " "
|
||||
if height:
|
||||
height = "height='%spx'" % (height)
|
||||
else:
|
||||
height = " "
|
||||
toreturn = "<img %s %s src='data:image/%s;base64,%s' />" % (
|
||||
width,
|
||||
height,
|
||||
type,
|
||||
str(pycompat.to_text(img)))
|
||||
return toreturn
|
||||
|
||||
def numer(self, name):
|
||||
if name:
|
||||
numeration = re.findall('\d+$', name)
|
||||
if numeration: return numeration[0]
|
||||
return ''
|
||||
|
||||
def ru_date(self, date):
|
||||
if date and date != 'False':
|
||||
return dt.ru_strftime(u'"%d" %B %Y года', date=datetime.strptime(str(date), "%Y-%m-%d"), inflected=True)
|
||||
return ''
|
||||
|
||||
def ru_date2(self, date):
|
||||
if date and date != 'False':
|
||||
return dt.ru_strftime(u'%d %B %Y г.', date=datetime.strptime(str(date), "%Y-%m-%d %H:%M:%S"),
|
||||
inflected=True)
|
||||
return ''
|
||||
|
||||
def in_words(self, number):
|
||||
return numeral.in_words(number)
|
||||
|
||||
def rubles(self, sum):
|
||||
"Transform sum number in rubles to text"
|
||||
text_rubles = self.numeral_rubles(int(sum))
|
||||
copeck = round((sum - int(sum)) * 100)
|
||||
text_copeck = self.numeral_choose_plural(int(copeck), (u"копейка", u"копейки", u"копеек"))
|
||||
return ("%s %02d %s") % (text_rubles, copeck, text_copeck)
|
||||
|
||||
def numeral_rubles(self, amount, zero_for_kopeck=False):
|
||||
self.check_positive(amount)
|
||||
pts = []
|
||||
amount = round(amount, 2)
|
||||
pts.append(self.sum_string(int(amount), 1, (u"рубль", u"рубля", u"рублей")))
|
||||
remainder = self._get_float_remainder(amount, 2)
|
||||
iremainder = int(remainder)
|
||||
|
||||
if iremainder != 0 or zero_for_kopeck:
|
||||
if iremainder < 10 and len(remainder) == 1:
|
||||
iremainder *= 10
|
||||
pts.append(self.sum_string(iremainder, 2,
|
||||
(u"копейка", u"копейки", u"копеек")))
|
||||
return u" ".join(pts)
|
||||
|
||||
def _get_float_remainder(self, fvalue, signs=9):
|
||||
self.check_positive(fvalue)
|
||||
if isinstance(fvalue, integer_types):
|
||||
return "0"
|
||||
if isinstance(fvalue, Decimal) and fvalue.as_tuple()[2] == 0:
|
||||
return "0"
|
||||
|
||||
def sum_string(self, amount, gender, items=None):
|
||||
if isinstance(items, text_type):
|
||||
items = split_values(items)
|
||||
if items is None:
|
||||
items = (u"", u"", u"")
|
||||
try:
|
||||
one_item, two_items, five_items = items
|
||||
except ValueError:
|
||||
raise ValueError("Items must be 3-element sequence")
|
||||
self.check_positive(amount)
|
||||
if amount == 0:
|
||||
return u"ноль %s" % five_items
|
||||
into = u''
|
||||
tmp_val = amount
|
||||
into, tmp_val = self._sum_string_fn(into, tmp_val, gender, items)
|
||||
into, tmp_val = self._sum_string_fn(into, tmp_val, FEMALE,
|
||||
(u"тысяча", u"тысячи", u"тысяч"))
|
||||
into, tmp_val = self._sum_string_fn(into, tmp_val, MALE,
|
||||
(u"миллион", u"миллиона", u"миллионов"))
|
||||
into, tmp_val = self._sum_string_fn(into, tmp_val, MALE,
|
||||
(u"миллиард", u"миллиарда", u"миллиардов"))
|
||||
if tmp_val == 0:
|
||||
return into
|
||||
else:
|
||||
raise ValueError("Cannot operand with numbers bigger than 10**11")
|
||||
|
||||
def _sum_string_fn(self, into, tmp_val, gender, items=None):
|
||||
if items is None:
|
||||
items = (u"", u"", u"")
|
||||
one_item, two_items, five_items = items
|
||||
self.check_positive(tmp_val)
|
||||
if tmp_val == 0:
|
||||
return into, tmp_val
|
||||
words = []
|
||||
rest = tmp_val % 1000
|
||||
tmp_val = tmp_val // 1000
|
||||
if rest == 0:
|
||||
if into == u"":
|
||||
into = u"%s " % five_items
|
||||
return into, tmp_val
|
||||
end_word = five_items
|
||||
words.append(HUNDREDS[rest // 100])
|
||||
rest = rest % 100
|
||||
rest1 = rest // 10
|
||||
tens = rest1 == 1 and TENS[rest] or TENS[rest1]
|
||||
words.append(tens)
|
||||
if rest1 < 1 or rest1 > 1:
|
||||
amount = rest % 10
|
||||
end_word = self.numeral_choose_plural(amount, items)
|
||||
words.append(ONES[amount][gender - 1])
|
||||
words.append(end_word)
|
||||
words.append(into)
|
||||
words = filter(lambda x: len(x) > 0, words)
|
||||
return u" ".join(words).strip(), tmp_val
|
||||
|
||||
def check_positive(self, value, strict=False):
|
||||
if not strict and value < 0:
|
||||
raise ValueError("Value must be positive or zero, not %s" % str(value))
|
||||
if strict and value <= 0:
|
||||
raise ValueError("Value must be positive, not %s" % str(value))
|
||||
|
||||
def numeral_choose_plural(self, amount, variants):
|
||||
if isinstance(variants, text_type):
|
||||
variants = split_values(variants)
|
||||
self.check_length(variants, 3)
|
||||
amount = abs(amount)
|
||||
if amount % 10 == 1 and amount % 100 != 11:
|
||||
variant = 0
|
||||
elif amount % 10 >= 2 and amount % 10 <= 4 and \
|
||||
(amount % 100 < 10 or amount % 100 >= 20):
|
||||
variant = 1
|
||||
else:
|
||||
variant = 2
|
||||
return variants[variant]
|
||||
|
||||
def check_length(self, value, length):
|
||||
_length = len(value)
|
||||
if _length != length:
|
||||
raise ValueError("length must be %d, not %d" % \
|
||||
(length, _length))
|
||||
|
||||
def initials(self, fio):
|
||||
if fio:
|
||||
return (fio.split()[0] + ' ' + ''.join([fio[0:1] + '.' for fio in fio.split()[1:]])).strip()
|
||||
return ''
|
||||
|
||||
def address(self, partner):
|
||||
repr = []
|
||||
if partner.zip: repr.append(partner.zip)
|
||||
if partner.city: repr.append(partner.city)
|
||||
if partner.street: repr.append(partner.street)
|
||||
if partner.street2: repr.append(partner.street2)
|
||||
return ', '.join(repr)
|
||||
|
||||
def address_delivery(self, partner):
|
||||
if partner:
|
||||
addr = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'delivery')], limit=1)
|
||||
repr = []
|
||||
if addr:
|
||||
if addr.zip: repr.append(addr.zip)
|
||||
if addr.city: repr.append(addr.city)
|
||||
if addr.street: repr.append(addr.street)
|
||||
if addr.street2: repr.append(addr.street2)
|
||||
return ', '.join(repr)
|
||||
|
||||
def get_function_print(self, function):
|
||||
morph = pymorphy2.MorphAnalyzer()
|
||||
if function:
|
||||
f = morph.parse(function)[0]
|
||||
f = f.inflect({'gent'}).word
|
||||
return f.title()
|
||||
|
||||
def get_function_partnerip(self, partner):
|
||||
director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1)
|
||||
if director:
|
||||
if director.function:
|
||||
return director.function
|
||||
|
||||
def get_function_partner(self, partner):
|
||||
res = []
|
||||
morph = pymorphy2.MorphAnalyzer()
|
||||
if partner:
|
||||
director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1)
|
||||
if director:
|
||||
if director.function:
|
||||
list_f = str(director.function).split(' ')
|
||||
for func in list_f:
|
||||
f = morph.parse(func)[0]
|
||||
f = f.inflect({'gent'}).word
|
||||
res.append(f)
|
||||
return ' '.join(res)
|
||||
|
||||
def get_function_partner1(self, partner):
|
||||
if partner:
|
||||
director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1)
|
||||
if director:
|
||||
if director.function:
|
||||
return director.function
|
||||
|
||||
def get_date_text(self, date):
|
||||
month_list = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября',
|
||||
'ноября', 'декабря']
|
||||
if date:
|
||||
date_list = str(date).split('-')
|
||||
if date_list[0] and date_list[1] and date_list[2]:
|
||||
return ('"' + date_list[2] + '" ' + month_list[int(date_list[1]) - 1] + ' ' + date_list[0] + ' г.')
|
||||
|
||||
def get_bank(self, partner):
|
||||
repr = []
|
||||
bank = None
|
||||
if partner.bank_ids:
|
||||
bank = partner.bank_ids[0]
|
||||
elif partner.parent_id.bank_ids:
|
||||
bank = partner.parent_id.bank_ids[0]
|
||||
if bank and bank.bank_name: repr.append(bank.bank_name)
|
||||
if bank and bank.acc_number: repr.append(u"Р/счет " + bank.acc_number)
|
||||
if bank and bank.bank_bic: repr.append(u"БИК " + bank.bank_bic)
|
||||
if bank and bank.bank_corr_acc: repr.append(u"к/с " + bank.bank_corr_acc)
|
||||
return '<br/>'.join(repr)
|
13
l10n_ru_contract/models/purchase_order.py
Normal file
13
l10n_ru_contract/models/purchase_order.py
Normal file
@ -0,0 +1,13 @@
|
||||
from odoo import api, fields, models, exceptions, _
|
||||
|
||||
|
||||
class PurchaseOrder(models.Model):
|
||||
_inherit = 'purchase.order'
|
||||
|
||||
mt_contract_id = fields.Many2one('partner.contract.customer', string=_('Номер договора'))
|
||||
sec_partner_id = fields.Many2one('res.partner', string=_('Контрагент'), store=True, compute='_compute_get_pid')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_get_pid(self):
|
||||
for s in self:
|
||||
s.sec_partner_id = s.partner_id.parent_id if s.partner_id.parent_id else s.partner_id
|
18
l10n_ru_contract/models/sale_make_invoice_advance.py
Normal file
18
l10n_ru_contract/models/sale_make_invoice_advance.py
Normal file
@ -0,0 +1,18 @@
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class ContractCreateInvoice(models.TransientModel):
|
||||
_inherit = 'sale.advance.payment.inv'
|
||||
|
||||
# # при выбора счета "Авансовый платеж"
|
||||
# @api.model
|
||||
# def _create_invoice(self, order, so_line, amount):
|
||||
# res = super(ContractCreateInvoice, self)._create_invoice(order, so_line, amount)
|
||||
# if order.mt_contract_id:
|
||||
# res.write({'mt_contract_id': order.mt_contract_id,
|
||||
# 'journal_id': order.mt_contract_id.profile_id.journal_id, })
|
||||
# return res
|
||||
def _prepare_invoice_values(self, order, name, amount):
|
||||
invoice_vals = super(ContractCreateInvoice, self)._prepare_invoice_values(order, name, amount)
|
||||
invoice_vals['mt_contract_id'] = order.mt_contract_id.id
|
||||
return invoice_vals
|
62
l10n_ru_contract/models/sale_order.py
Normal file
62
l10n_ru_contract/models/sale_order.py
Normal file
@ -0,0 +1,62 @@
|
||||
from odoo import api, fields, models, exceptions, _
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = 'sale.order'
|
||||
|
||||
mt_contract_id = fields.Many2one('partner.contract.customer', string=_('Номер договора'))
|
||||
sec_partner_id = fields.Many2one('res.partner', string=_('Контрагент'), store=True, compute='_compute_get_pid')
|
||||
stamp = fields.Boolean(string=_('Печать и подпись'), related='mt_contract_id.stamp')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_get_pid(self):
|
||||
for s in self:
|
||||
s.sec_partner_id = s.partner_id.parent_id if s.partner_id.parent_id else s.partner_id
|
||||
|
||||
@api.onchange('mt_contract_id')
|
||||
def set_ons(self):
|
||||
if self.mt_contract_id:
|
||||
self.payment_term_id = self.mt_contract_id.payment_term_id
|
||||
|
||||
@api.constrains('state')
|
||||
def late_payment_check(self):
|
||||
if self.mt_contract_id:
|
||||
if self.state == 'sale':
|
||||
late_invoices_count = 0
|
||||
max_receivable = self.mt_contract_id.profile_id.max_receivable_id # макс. деб. задолженность в договоре
|
||||
# ищу просроченные инвойсы контрагента указанного в заказе со стейтом "Подтверждено"
|
||||
invoices_obj = self.env['account.move'].search([('partner_id', '=', self.partner_id.id),
|
||||
('state', '=', 'posted'),
|
||||
('invoice_date_due', '<', datetime.now().date())])
|
||||
|
||||
for invoice in invoices_obj:
|
||||
late_invoices_count += invoice.amount_residual # складываю деб. задолженность по просроченным инвойсам
|
||||
|
||||
if late_invoices_count > max_receivable:
|
||||
raise exceptions.ValidationError(
|
||||
f'Нельзя подтвердить заказ, так как у контрагента {self.sec_partner_id.name} нарушено '
|
||||
f'условие по дебиторской задолженности.\n\n'
|
||||
f'Контрагент {self.sec_partner_id.name} должен {late_invoices_count}руб.\n'
|
||||
f'Максимальная дебиторская задолженность указанная в '
|
||||
f'договоре №{self.mt_contract_id.name} - {max_receivable}руб.\n\n'
|
||||
f'Проверьте следующие неоплаченные счета контрагента:\n'
|
||||
f'{", ".join([invoice.name for invoice in invoices_obj])}')
|
||||
|
||||
# # при выбора счета "Обычный счет"
|
||||
# @api.model
|
||||
# def _create_invoices(self, grouped=False, final=False, date=None):
|
||||
# res = super(SaleOrder, self)._create_invoices(grouped, final, date)
|
||||
# if self.mt_contract_id:
|
||||
# res.write({'mt_contract_id': self.mt_contract_id,
|
||||
# 'journal_id': self.mt_contract_id.profile_id.journal_id})
|
||||
# return res
|
||||
def _get_invoice_grouping_keys(self):
|
||||
res = super(SaleOrder, self)._get_invoice_grouping_keys()
|
||||
res.append('mt_contract_id')
|
||||
return res #['company_id', 'partner_id', 'currency_id', 'mt_contractid']
|
||||
|
||||
def _prepare_invoice(self):
|
||||
invoice_vals = super(SaleOrder, self)._prepare_invoice()
|
||||
invoice_vals['mt_contract_id'] = self.mt_contract_id.id
|
||||
return invoice_vals
|
4
l10n_ru_contract/report/__init__.py
Normal file
4
l10n_ru_contract/report/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import report_contract
|
||||
from . import report_contract_order
|
||||
from . import report_contract_invoice
|
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-35.pyc
Normal file
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-35.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-36.pyc
Normal file
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-36.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-37.pyc
Normal file
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-37.pyc
Normal file
Binary file not shown.
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-38.pyc
Normal file
BIN
l10n_ru_contract/report/__pycache__/__init__.cpython-38.pyc
Normal file
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.
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.
Binary file not shown.
BIN
l10n_ru_contract/report/__pycache__/report_helper.cpython-36.pyc
Normal file
BIN
l10n_ru_contract/report/__pycache__/report_helper.cpython-36.pyc
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user