Public release from ruodoo-project: 19.0 - 2026-05-10 21:19:01 UTC
This commit is contained in:
2
l10n_ru_contract_sale/__init__.py
Normal file
2
l10n_ru_contract_sale/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from . import models
|
||||
from . import report
|
||||
27
l10n_ru_contract_sale/__manifest__.py
Normal file
27
l10n_ru_contract_sale/__manifest__.py
Normal file
@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': 'Российская локализация - Договоры Продажи',
|
||||
'summary': """
|
||||
Создание договоров, их видов и печать
|
||||
""",
|
||||
|
||||
'description': """
|
||||
Создание договоров с клиентами и поставщиками. Адаптация под модуль продаж.
|
||||
""",
|
||||
|
||||
'version': '19.0.1.0.0',
|
||||
'sequence': 0,
|
||||
'author': 'MK.Lab',
|
||||
'website': 'https://www.inf-centre.ru/',
|
||||
'depends': ['l10n_ru_contract_account','sale', 'sale_management'],
|
||||
'data': [
|
||||
'views/contract_customer_account_views.xml',
|
||||
'views/sale_order_views.xml',
|
||||
'report/report_contract_order.xml',
|
||||
'report/report_contract_order1.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'demo': [
|
||||
'demo/demo.xml',
|
||||
],
|
||||
}
|
||||
21
l10n_ru_contract_sale/demo/demo.xml
Normal file
21
l10n_ru_contract_sale/demo/demo.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- sale.order с привязкой к договору -->
|
||||
<record id="demo_sale_order_001" model="sale.order">
|
||||
<field name="partner_id" ref="l10n_ru_contract.demo_partner_buyer"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="mt_contract_id" ref="l10n_ru_contract.demo_contract_customer_001"/>
|
||||
<field name="date_order">2026-02-01 10:00:00</field>
|
||||
</record>
|
||||
|
||||
<record id="demo_sale_order_line_001" model="sale.order.line">
|
||||
<field name="order_id" ref="demo_sale_order_001"/>
|
||||
<field name="product_id" ref="product.product_product_4"/>
|
||||
<field name="product_uom_qty">5.0</field>
|
||||
<field name="price_unit">15000.0</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
3
l10n_ru_contract_sale/models/__init__.py
Normal file
3
l10n_ru_contract_sale/models/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
from . import sale_make_invoice_advance
|
||||
from . import sale_order
|
||||
from . import partner_contract_customer
|
||||
17
l10n_ru_contract_sale/models/partner_contract_customer.py
Normal file
17
l10n_ru_contract_sale/models/partner_contract_customer.py
Normal file
@ -0,0 +1,17 @@
|
||||
from odoo import api, fields, models, exceptions, _
|
||||
|
||||
class PartnerContractCustomer(models.Model):
|
||||
_inherit = "partner.contract.customer"
|
||||
|
||||
sale_order_id = fields.Many2one(
|
||||
"sale.order",
|
||||
string=_("Заказ/Сделка"),
|
||||
)
|
||||
manager_id = fields.Many2one(
|
||||
"res.users",
|
||||
string=_("Менеджер по продажам"),
|
||||
)
|
||||
team_id = fields.Many2one(
|
||||
"crm.team",
|
||||
string=_("Команда продаж"),
|
||||
)
|
||||
11
l10n_ru_contract_sale/models/sale_make_invoice_advance.py
Normal file
11
l10n_ru_contract_sale/models/sale_make_invoice_advance.py
Normal file
@ -0,0 +1,11 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ContractCreateInvoice(models.TransientModel):
|
||||
_inherit = 'sale.advance.payment.inv'
|
||||
|
||||
def _prepare_invoice_values(self, order, so_lines, accounts):
|
||||
invoice_vals = super()._prepare_invoice_values(order, so_lines, accounts)
|
||||
if order.mt_contract_id:
|
||||
invoice_vals['mt_contract_id'] = order.mt_contract_id.id
|
||||
return invoice_vals
|
||||
57
l10n_ru_contract_sale/models/sale_order.py
Normal file
57
l10n_ru_contract_sale/models/sale_order.py
Normal file
@ -0,0 +1,57 @@
|
||||
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):
|
||||
for s in self:
|
||||
if s.mt_contract_id:
|
||||
s.payment_term_id = s.mt_contract_id.payment_term_id
|
||||
|
||||
@api.constrains('state')
|
||||
def late_payment_check(self):
|
||||
for s in self:
|
||||
if s.mt_contract_id:
|
||||
if s.state == 'sale':
|
||||
late_invoices_count = 0
|
||||
max_receivable = s.mt_contract_id.profile_id.max_receivable_id
|
||||
|
||||
invoices_obj = self.env['account.move'].search([('partner_id', '=', s.partner_id.id),
|
||||
('state', '=', 'posted'),
|
||||
('payment_state', 'not in', ['paid', 'reversed']),
|
||||
('move_type', 'in', ['out_invoice']),
|
||||
('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'Нельзя подтвердить заказ, так как у контрагента {s.sec_partner_id.name} нарушено '
|
||||
f'условие по дебиторской задолженности.\n\n'
|
||||
f'Контрагент {s.sec_partner_id.name} должен {late_invoices_count}руб.\n'
|
||||
f'Максимальная дебиторская задолженность указанная в '
|
||||
f'договоре №{s.mt_contract_id.name} - {max_receivable}руб.\n\n'
|
||||
f'Проверьте следующие неоплаченные счета контрагента:\n'
|
||||
f'{", ".join([invoice.name for invoice in invoices_obj])}')
|
||||
|
||||
|
||||
def _prepare_invoice(self):
|
||||
invoice_vals = super(SaleOrder, self)._prepare_invoice()
|
||||
for s in self:
|
||||
if s.mt_contract_id:
|
||||
invoice_vals['mt_contract_id'] = s.mt_contract_id.id
|
||||
invoice_vals['osnovanie'] = 'Договор № ' + s.mt_contract_id.name + ' от ' + fields.Datetime.from_string(
|
||||
s.mt_contract_id.date_start).strftime("%d.%m.%Y")
|
||||
return invoice_vals
|
||||
2
l10n_ru_contract_sale/report/__init__.py
Normal file
2
l10n_ru_contract_sale/report/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from . import report_contract_order
|
||||
|
||||
18
l10n_ru_contract_sale/report/report_contract_order.py
Normal file
18
l10n_ru_contract_sale/report/report_contract_order.py
Normal file
@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class ContractCustomerReportOrder(models.AbstractModel):
|
||||
_name = 'contract.customer.report_order'
|
||||
|
||||
|
||||
def get_report_values(self, docids, data=None):
|
||||
docs = self.env['sale.order'].browse(docids)
|
||||
return {
|
||||
'doc_ids': docs.ids,
|
||||
'doc_model': 'sale.order',
|
||||
'docs': docs,
|
||||
}
|
||||
|
||||
|
||||
|
||||
594
l10n_ru_contract_sale/report/report_contract_order.xml
Normal file
594
l10n_ru_contract_sale/report/report_contract_order.xml
Normal file
@ -0,0 +1,594 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<template id="report_contract_customer_order">
|
||||
<t t-call="web.basic_layout">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<t t-if="o and 'company_id' in o">
|
||||
<t t-set="company" t-value="o.company_id"/>
|
||||
</t>
|
||||
<t t-if="not o or not 'company_id' in o">
|
||||
<t t-set="company" t-value="res_company"/>
|
||||
</t>
|
||||
<t t-set="context" t-value="o._context"/>
|
||||
<div class="header">
|
||||
<STYLE TYPE="text/css">
|
||||
body {background: #ffffff; margin: 0; font-family: Times new roman; font-size: 12pt; font-style:
|
||||
normal;}
|
||||
tr.R0{height: 15px;}
|
||||
tr.R0 td.R0C0{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium; font-weight: bold;}
|
||||
tr.R0 td.R0C1{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
right; vertical-align: medium; font-weight: bold;}
|
||||
</STYLE>
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%">
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C0"><t t-esc="o.mt_contract_id.company_id.name or ''"/></td>
|
||||
<td class="R0C1">Договор <t t-esc="o.mt_contract_id.name or ''"/> от <t
|
||||
t-esc="o.mt_contract_id.date_start or ''"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="page">
|
||||
<STYLE TYPE="text/css">
|
||||
body {background: #ffffff; margin: 0; font-family: Times new roman; font-size: 12pt; font-style:
|
||||
normal;}
|
||||
tr.R0{height: 15px;}
|
||||
tr.R0 td.R0C0{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: center; vertical-align: medium;}
|
||||
tr.R0 td.R0C1{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium;}
|
||||
tr.R0 td.R0C2{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
right; vertical-align: medium;}
|
||||
tr.R0 td.R0C3{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
justify; vertical-align: medium; margin: 40px;}
|
||||
tr.R0 td.R0C4{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
center; vertical-align: medium; font-weight: bold;}
|
||||
tr.R0 td.R0C5{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
start; vertical-align: medium;}
|
||||
p.R0C4{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align: center;
|
||||
vertical-align: medium; font-weight: bold;}
|
||||
div.R0C5{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
justify; vertical-align: medium;}
|
||||
tr.R0 td.R0C6rtl{ font-family: Times new roman; font-size: 11pt; font-style: normal;
|
||||
font-weight: bold; text-align: left; vertical-align: medium; border-left: #000000 1px solid;
|
||||
border-top: #000000 1px solid; border-right: #000000 1px solid;}
|
||||
tr.R0 td.R0C6rl{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-left: #000000 1px solid; border-right:
|
||||
#000000 1px solid}
|
||||
tr.R0 td.R0C6r{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-right: #000000 1px solid}
|
||||
tr.R0 td.R0C6l{ font-family: Times new roman; font-size: 11pt; font-style: normal;
|
||||
text-align: left; vertical-align: medium; border-left: #000000 1px solid;}
|
||||
tr.R0 td.R0C6b{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C6t{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-top: #000000 1px solid;}
|
||||
tr.R0 td.R0C6rbl{ font-family: Times new roman; font-size: 11pt; font-style: normal;
|
||||
font-weight: bold; text-align: left; vertical-align: medium; border-left: #000000 1px solid;
|
||||
border-right: #000000 1px solid; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C7rtl{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium; border-left: #000000 1px solid; border-top: #000000 1px solid;
|
||||
border-right: #000000 1px solid;}
|
||||
tr.R0 td.R0C7rl{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium; border-left: #000000 1px solid; border-right: #000000 1px solid;}
|
||||
tr.R0 td.R0C7rbl{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium; border-left: #000000 1px solid; border-right: #000000 1px solid;
|
||||
border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C6tI{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C6tI { overflow: visible; }
|
||||
tr.R0 td.R0C6tI span { position: relative; }
|
||||
tr.R0 td.R0C6tI span img { position: absolute; width: 100px; top: -30px; left: 80px; }
|
||||
tr.R0 td.R0C6tS { overflow: visible; }
|
||||
tr.R0 td.R0C6tS span { position: relative; }
|
||||
tr.R0 td.R0C6tS span img { position: absolute; width: 140px; top: -40px; left: -200px; }
|
||||
tr.R0 td.R0C8{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
right; vertical-align: medium; font-weight: bold;}
|
||||
tr.R0 td.R0C9box{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
center; vertical-align: medium; border-left: #000000 1px solid; border-right: #000000 1px solid;
|
||||
border-bottom: #000000 1px solid; border-top: #000000 1px solid;}
|
||||
</STYLE>
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%;">
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="2">Договор № <t t-esc="o.mt_contract_id.name or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="2">на поставку продукции</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C1"></td>
|
||||
<td class="R0C2"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C1"><t t-esc="o.mt_contract_id.company_id.partner_id.city or ''"/></td>
|
||||
<td class="R0C2"><t
|
||||
t-esc="o.mt_contract_id.get_date_text(o.mt_contract_id.date_start) or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C1"></td>
|
||||
<td class="R0C2"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C3" colspan="2">
|
||||
<span>
|
||||
<t t-raw="o.mt_contract_id.contract_header or ''"/>
|
||||
</span>
|
||||
</td>
|
||||
<tr class="R0">
|
||||
<td class="R0C1"></td>
|
||||
<td class="R0C2"></td>
|
||||
</tr>
|
||||
</tr>
|
||||
<!--t t-foreach="o.mt_contract_id.lines.sorted(key=lambda r: r.sequence, reverse=False)" t-as="line">
|
||||
<tr class="R0">
|
||||
<td class="R0C4" colspan="2"><t t-esc="line.name"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C5" colspan="2"><t t-raw="line.punct"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C5" colspan="2"></td>
|
||||
</tr>
|
||||
</t-->
|
||||
<!--tr class="R0">
|
||||
<td class="R0C4" colspan="2">Реквизиты и подписи сторон.</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C1"></td>
|
||||
<td class="R0C2"></td>
|
||||
</tr-->
|
||||
</tbody>
|
||||
</table>
|
||||
<t t-foreach="o.mt_contract_id.lines_ids.sorted(key=lambda r: r.sequence, reverse=False)" t-as="line">
|
||||
<p class="R0C4"><t t-esc="line.name or ''"/></p>
|
||||
<div class="R0C5"><span><t t-raw="line.punct or ''"/></span></div>
|
||||
</t>
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%; page-break-inside: avoid;">
|
||||
<COL WIDTH="5%"/>
|
||||
<COL WIDTH="30%"/>
|
||||
<COL WIDTH="15%"/>
|
||||
<COL WIDTH="5%"/>
|
||||
<COL WIDTH="30%"/>
|
||||
<COL WIDTH="15%"/>
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C4" colspan="6">Реквизиты и подписи сторон.</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C1" colspan="6"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rtl" colspan="3">Поставщик:</td>
|
||||
<td class="R0C6rtl" colspan="3">Покупатель:</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"><t t-esc="o.mt_contract_id.company_id.name or ''"/></td>
|
||||
<td class="R0C6rl" colspan="3"><t t-esc="o.mt_contract_id.partner_id.name or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="3">ИНН
|
||||
<t t-esc="o.mt_contract_id.company_id.inn or ''"/>
|
||||
</td>
|
||||
<td class="R0C7rl" colspan="3">ИНН <t
|
||||
t-esc="o.mt_contract_id.partner_id.inn or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="2">ОГРН
|
||||
<t t-esc="o.company_id.company_registry or ''"/>
|
||||
</td>
|
||||
<td class="R0C6r" rowspan="2">
|
||||
<t t-esc="o.mt_contract_id.director_name_company or ''"/>
|
||||
</td>
|
||||
<t t-if="o.mt_contract_id.partner_type in ['company', 'company_ip']">
|
||||
<td class="R0C7rl" colspan="3">ОГРН
|
||||
<t t-esc="o.partner_id.ogrn or ''"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<td class="R0C7rl" colspan="3">Паспорт
|
||||
<t t-esc="o.partner_id.passport or ''"/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="3">КПП
|
||||
<t t-esc="o.mt_contract_id.company_id.kpp or ''"/>
|
||||
</td>
|
||||
<t t-if="o.mt_contract_id.partner_type == 'company'">
|
||||
<td class="R0C7rl" colspan="3">КПП
|
||||
<t t-esc="o.partner_id.kpp or ''"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<td class="R0C7rl" colspan="3"></td>
|
||||
</t>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3">Юридический адрес:
|
||||
</td>
|
||||
<td class="R0C6rl" colspan="3">Юридический адрес:
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="3">
|
||||
<t t-esc="o.mt_contract_id.address(o.company_id) or ''"/>
|
||||
</td>
|
||||
<td class="R0C7rl" colspan="3">
|
||||
<t t-esc="o.mt_contract_id.address(o.partner_id) or ''"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l"></td>
|
||||
<td class="R0C6tI">
|
||||
<SPAN>
|
||||
<t t-raw="o.stamp and o.mt_contract_id.img(o.company_id.chief_id.facsimile) or ''"/>
|
||||
</SPAN>
|
||||
</td>
|
||||
<td class="R0C6tS">
|
||||
<SPAN>
|
||||
<t t-raw="o.stamp and o.mt_contract_id.img(o.company_id.stamp) or ''"/>
|
||||
</SPAN>
|
||||
</td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6l"></td>
|
||||
<td class="R0C6b"></td>
|
||||
<td class="R0C6r">
|
||||
<t t-esc="''"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rbl" colspan="3"></td>
|
||||
<td class="R0C6rbl" colspan="3"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="page-break-before:always;"></p>
|
||||
<!--p style="page-break-after:always"></p>
|
||||
<div style="page-break-after: auto;"><span style="display: none;"> </span></div>
|
||||
<p style="page-break-inside: avoid">
|
||||
<div style="page-break-inside: auto"></div-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%">
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C8" colspan="8">Приложение<br/>к договору № <t
|
||||
t-esc="o.mt_contract_id.name"/><br/>на поставку продукции<br/>от <t
|
||||
t-esc="o.mt_contract_id.get_date_text(o.mt_contract_id.date_start) or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8">Спецификация № 1</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C1" colspan="4"><t
|
||||
t-esc="o.mt_contract_id.company_id.partner_id.city or ''"/></td>
|
||||
<td class="R0C2" colspan="4"><t
|
||||
t-esc="o.mt_contract_id.get_date_text(o.mt_contract_id.date_start) or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C3" colspan="8">
|
||||
<span>
|
||||
<t t-raw="o.mt_contract_id.contract_header or ''"/>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C5" colspan="8">1. По договору на поставку продукции <t
|
||||
t-esc="o.mt_contract_id.name or ''"/> от <t
|
||||
t-esc="o.mt_contract_id.get_date_text(o.mt_contract_id.date_start) or ''"/>.
|
||||
Поставщик обязуется поставить, а Покупатель оплатить в полном объеме следующее:</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C9box">Номенклатура</td>
|
||||
<!-- <td class="R0C9box">*ГОСТ</td>-->
|
||||
<td class="R0C9box">Ед.изм.</td>
|
||||
<td class="R0C9box">Кол-во</td>
|
||||
<td class="R0C9box">Цена/руб.<br/>без НДС</td>
|
||||
<td class="R0C9box">Стоимость/руб.<br/>без НДС</td>
|
||||
<!-- <td class="R0C9box">НДС</td>-->
|
||||
<!-- <td class="R0C9box">Стоимость/руб.<br/>c НДС</td>-->
|
||||
</tr>
|
||||
<t t-set="order_line" t-value="o.order_line.filtered(lambda s: 'аванс' not in s.name.lower() and 'депозит' not in s.name.lower())"/>
|
||||
<t t-set="quantity" t-value="sum([line.product_uom_qty for line in order_line])"/>
|
||||
<t t-set="sum_full"
|
||||
t-value="sum([line.product_uom_qty*line.price_unit for line in order_line])"/>
|
||||
<t t-set="sum_nds"
|
||||
t-value="sum([line.product_uom_qty*line.price_unit*1.2 for line in order_line])"/>
|
||||
<tr class="R0" t-foreach="order_line" t-as="line">
|
||||
<td class="R0C9box"><t t-esc="line.product_id.name or ''"/></td>
|
||||
<!-- <td class="R0C9box"><!–ГОСТ–></td>-->
|
||||
<td class="R0C9box"><t t-esc="line.product_id.uom_id.name or ''"/></td>
|
||||
<td class="R0C9box"><t t-esc="line.product_uom_qty or ''"/></td>
|
||||
<td class="R0C9box"><t t-esc="line.price_unit or ''"/></td>
|
||||
<td class="R0C9box"><t t-esc="line.price_unit*line.product_uom_qty or ''"/></td>
|
||||
<!-- <td class="R0C9box">20%</td>-->
|
||||
<!-- <td class="R0C9box"><t t-esc="line.price_unit*line.product_uom_qty*1.2 or ''"/></td>-->
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td></td>
|
||||
<!-- <td></td>-->
|
||||
<td>ИТОГО</td>
|
||||
<td class="R0C9box"><t t-esc="quantity or ''"/></td>
|
||||
<td class="R0C9box">x</td>
|
||||
<td class="R0C9box"><t t-esc="sum_full or ''"/></td>
|
||||
<!-- <td class="R0C9box">x</td>-->
|
||||
<!-- <td class="R0C9box"><t t-esc="sum_nds or ''"/></td>-->
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C5" colspan="9">Итого: <t t-esc="sum_full or ''"/> рублей (<t
|
||||
t-esc="o.mt_contract_id.rubles(sum_full) or ''"/>). В стоимость продукции входит
|
||||
стоимость
|
||||
тары и стоимость транспортных расходов, связанных с доставкой продукции до станции
|
||||
назначения.<br/>
|
||||
2. Базис поставки (пункт назначения) по отгрузочным реквизитам:<br/>
|
||||
<t t-esc="o.mt_contract_id.address_delivery(o.mt_contract_id.partner_id.id) or ''"/><br/>
|
||||
Грузополучатель: <t t-esc="o.mt_contract_id.partner_id.name or ''"/>, код <t
|
||||
t-esc="o.mt_contract_id.partner_id.id or ''"/>, ОКПО <t
|
||||
t-esc="o.mt_contract_id.partner_id.okpo or ''"/>.<br/>
|
||||
3. Условия оплаты: <t t-esc="o.payment_term_id.name or ''"/> согласно выставленному
|
||||
счету
|
||||
Поставщика.<br/>
|
||||
4. Срок отгрузки: <t
|
||||
t-esc="o.mt_contract_id.get_date_text(o.mt_contract_id.date_end) or ''"/>
|
||||
<br/>
|
||||
5. Срок действия настоящей спецификации ограничен и равен сроку отгрузки по
|
||||
условиям данной спецификации.
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%; page-break-inside: avoid;">
|
||||
<COL WIDTH="5%"/>
|
||||
<COL WIDTH="30%"/>
|
||||
<COL WIDTH="15%"/>
|
||||
<COL WIDTH="5%"/>
|
||||
<COL WIDTH="30%"/>
|
||||
<COL WIDTH="15%"/>
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C4" colspan="6">Реквизиты и подписи сторон.</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C1" colspan="6"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rtl" colspan="3">Поставщик:</td>
|
||||
<td class="R0C6rtl" colspan="3">Покупатель:</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"><t t-esc="o.mt_contract_id.company_id.name or ''"/></td>
|
||||
<td class="R0C6rl" colspan="3"><t t-esc="o.mt_contract_id.partner_id.name or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="3">ИНН
|
||||
<t t-esc="o.mt_contract_id.company_id.inn or ''"/>
|
||||
</td>
|
||||
<td class="R0C7rl" colspan="3">ИНН <t
|
||||
t-esc="o.mt_contract_id.partner_id.inn or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="2">ОГРН
|
||||
<t t-esc="o.company_id.company_registry or ''"/>
|
||||
</td>
|
||||
<td class="R0C6r" rowspan="2">
|
||||
<t t-esc="o.mt_contract_id.director_name_company or ''"/>
|
||||
</td>
|
||||
<t t-if="o.mt_contract_id.partner_type in ['company', 'company_ip']">
|
||||
<td class="R0C7rl" colspan="3">ОГРН
|
||||
<t t-esc="o.partner_id.ogrn or ''"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<td class="R0C7rl" colspan="3">Паспорт
|
||||
<t t-esc="o.partner_id.passport or ''"/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="3">КПП
|
||||
<t t-esc="o.mt_contract_id.company_id.kpp or ''"/>
|
||||
</td>
|
||||
<t t-if="o.mt_contract_id.partner_type == 'company'">
|
||||
<td class="R0C7rl" colspan="3">КПП
|
||||
<t t-esc="o.partner_id.kpp or ''"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<td class="R0C7rl" colspan="3"></td>
|
||||
</t>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3">Юридический адрес:
|
||||
</td>
|
||||
<td class="R0C6rl" colspan="3">Юридический адрес:
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="3">
|
||||
<t t-esc="o.mt_contract_id.address(o.company_id) or ''"/>
|
||||
</td>
|
||||
<td class="R0C7rl" colspan="3">
|
||||
<t t-esc="o.mt_contract_id.address(o.partner_id) or ''"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l"></td>
|
||||
<td class="R0C6tI">
|
||||
<SPAN>
|
||||
<t t-raw="o.stamp and o.mt_contract_id.img(o.company_id.chief_id.facsimile) or ''"/>
|
||||
</SPAN>
|
||||
</td>
|
||||
<td class="R0C6tS">
|
||||
<SPAN>
|
||||
<t t-raw="o.stamp and o.mt_contract_id.img(o.company_id.stamp) or ''"/>
|
||||
</SPAN>
|
||||
</td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6l"></td>
|
||||
<td class="R0C6b"></td>
|
||||
<td class="R0C6r">
|
||||
<t t-esc="''"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rbl" colspan="3"></td>
|
||||
<td class="R0C6rbl" colspan="3"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<STYLE TYPE="text/css">
|
||||
body {background: #ffffff; margin: 0; font-family: Times new roman; font-size: 12pt; font-style:
|
||||
normal;}
|
||||
tr.R0{height: 30px;}
|
||||
tr.R0 td.R0C0{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: bottom;}
|
||||
tr.R0 td.R0C1{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: right; vertical-align: bottom;}
|
||||
tr.R0 td.R0C6tI{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: top; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C6tI { overflow: visible; }
|
||||
tr.R0 td.R0C6tI span { position: relative; }
|
||||
tr.R0 td.R0C6tI span img { position: absolute; width: 100px; top: -5px; left: 5px;}
|
||||
</STYLE>
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%">
|
||||
<COL WIDTH="20%"/>
|
||||
<COL WIDTH="20%"/>
|
||||
<COL WIDTH="20%"/>
|
||||
<COL WIDTH="20%"/>
|
||||
<COL WIDTH="20%"/>
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C0">Подпись Исполнителя</td>
|
||||
<td class="R0C6tI">
|
||||
<SPAN>
|
||||
<t
|
||||
t-raw="o.stamp and o.mt_contract_id.img(company.chief_id.facsimile) or ''"/>
|
||||
</SPAN>
|
||||
</td>
|
||||
<td class="R0C0"></td>
|
||||
<td class="R0C1">Подпись Заказчика</td>
|
||||
<td class="R0C6tI"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col-xs-3 pull-right">
|
||||
<small style="font-size:18px;">
|
||||
<span>Страница</span>
|
||||
<span class="page"/>
|
||||
из
|
||||
<span class="topage"/>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<record id="paperformat_a4" 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">30</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>
|
||||
|
||||
<record id="action_report_contract_customer_order" model="ir.actions.report">
|
||||
<field name="name">Договор со спецификацией</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">l10n_ru_contract_sale.report_contract_customer_order</field>
|
||||
<field name="report_file">l10n_ru_contract_sale.report_contract_customer_order</field>
|
||||
<field name="print_report_name">'Договор со спецификацией - %s' % (object.name)</field>
|
||||
<field name="binding_model_id" ref="sale.model_sale_order" />
|
||||
<field name="paperformat_id" ref="paperformat_a4" />
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
</odoo>
|
||||
406
l10n_ru_contract_sale/report/report_contract_order1.xml
Normal file
406
l10n_ru_contract_sale/report/report_contract_order1.xml
Normal file
@ -0,0 +1,406 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<template id="report_contract_customer_order1">
|
||||
<t t-call="web.basic_layout">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<t t-if="o and 'company_id' in o">
|
||||
<t t-set="company" t-value="o.company_id"/>
|
||||
</t>
|
||||
<t t-if="not o or not 'company_id' in o">
|
||||
<t t-set="company" t-value="res_company"/>
|
||||
</t>
|
||||
<t t-set="context" t-value="o._context"/>
|
||||
<div class="header">
|
||||
<STYLE TYPE="text/css">
|
||||
body {background: #ffffff; margin: 0; font-family: Times new roman; font-size: 12pt; font-style:
|
||||
normal;}
|
||||
tr.R0{height: 15px;}
|
||||
tr.R0 td.R0C0{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium; font-weight: bold;}
|
||||
tr.R0 td.R0C1{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
right; vertical-align: medium; font-weight: bold;}
|
||||
</STYLE>
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%">
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C0"><t t-esc="o.mt_contract_id.company_id.name or ''"/></td>
|
||||
<td class="R0C1">Договор <t t-esc="o.mt_contract_id.name or ''"/> от <t
|
||||
t-esc="o.mt_contract_id.date_start or ''"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="page">
|
||||
<STYLE TYPE="text/css">
|
||||
body {background: #ffffff; margin: 0; font-family: Times new roman; font-size: 12pt; font-style:
|
||||
normal;}
|
||||
tr.R0{height: 15px;}
|
||||
tr.R0 td.R0C0{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: center; vertical-align: medium;}
|
||||
tr.R0 td.R0C1{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium;}
|
||||
tr.R0 td.R0C2{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
right; vertical-align: medium;}
|
||||
tr.R0 td.R0C3{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
justify; vertical-align: medium; margin: 40px;}
|
||||
tr.R0 td.R0C4{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
center; vertical-align: medium; font-weight: bold;}
|
||||
tr.R0 td.R0C5{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
start; vertical-align: medium;}
|
||||
p.R0C4{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align: center;
|
||||
vertical-align: medium; font-weight: bold;}
|
||||
div.R0C5{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
justify; vertical-align: medium;}
|
||||
tr.R0 td.R0C6rtl{ font-family: Times new roman; font-size: 11pt; font-style: normal;
|
||||
font-weight: bold; text-align: left; vertical-align: medium; border-left: #000000 1px solid;
|
||||
border-top: #000000 1px solid; border-right: #000000 1px solid;}
|
||||
tr.R0 td.R0C6rl{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-left: #000000 1px solid; border-right:
|
||||
#000000 1px solid}
|
||||
tr.R0 td.R0C6r{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-right: #000000 1px solid}
|
||||
tr.R0 td.R0C6l{ font-family: Times new roman; font-size: 11pt; font-style: normal;
|
||||
text-align: left; vertical-align: medium; border-left: #000000 1px solid;}
|
||||
tr.R0 td.R0C6b{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C6t{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-top: #000000 1px solid;}
|
||||
tr.R0 td.R0C6rbl{ font-family: Times new roman; font-size: 11pt; font-style: normal;
|
||||
font-weight: bold; text-align: left; vertical-align: medium; border-left: #000000 1px solid;
|
||||
border-right: #000000 1px solid; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C7rtl{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium; border-left: #000000 1px solid; border-top: #000000 1px solid;
|
||||
border-right: #000000 1px solid;}
|
||||
tr.R0 td.R0C7rl{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium; border-left: #000000 1px solid; border-right: #000000 1px solid;}
|
||||
tr.R0 td.R0C7rbl{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
left; vertical-align: medium; border-left: #000000 1px solid; border-right: #000000 1px solid;
|
||||
border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C6tI{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: medium; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C6tI { overflow: visible; }
|
||||
tr.R0 td.R0C6tI span { position: relative; }
|
||||
tr.R0 td.R0C6tI span img { position: absolute; width: 100px; top: -30px; left: 80px; }
|
||||
tr.R0 td.R0C6tS { overflow: visible; }
|
||||
tr.R0 td.R0C6tS span { position: relative; }
|
||||
tr.R0 td.R0C6tS span img { position: absolute; width: 140px; top: -40px; left: -200px; }
|
||||
tr.R0 td.R0C8{ font-family: Times new roman; font-size: 11pt; font-style: normal; text-align:
|
||||
right; vertical-align: medium; font-weight: bold;}
|
||||
tr.R0 td.R0C9box{ font-family: Times new roman; font-size: 12pt; font-style: normal; text-align:
|
||||
center; vertical-align: medium; border-left: #000000 1px solid; border-right: #000000 1px solid;
|
||||
border-bottom: #000000 1px solid; border-top: #000000 1px solid;}
|
||||
</STYLE>
|
||||
|
||||
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%">
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C8" colspan="8">Приложение<br/>к договору № <t
|
||||
t-esc="o.mt_contract_id.name"/><br/>на поставку продукции<br/>от <t
|
||||
t-esc="o.mt_contract_id.get_date_text(o.mt_contract_id.date_start) or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8">Спецификация № 1</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C1" colspan="4"><t
|
||||
t-esc="o.mt_contract_id.company_id.partner_id.city or ''"/></td>
|
||||
<td class="R0C2" colspan="4"><t
|
||||
t-esc="o.mt_contract_id.get_date_text(o.mt_contract_id.date_start) or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C3" colspan="8">
|
||||
<span>
|
||||
<t t-raw="o.mt_contract_id.contract_header or ''"/>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C5" colspan="8">1. По договору на поставку продукции <t
|
||||
t-esc="o.mt_contract_id.name or ''"/> от <t
|
||||
t-esc="o.mt_contract_id.get_date_text(o.mt_contract_id.date_start) or ''"/>.
|
||||
Поставщик обязуется поставить, а Покупатель оплатить в полном объеме следующее:</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C9box">Номенклатура</td>
|
||||
<!-- <td class="R0C9box">*ГОСТ</td>-->
|
||||
<td class="R0C9box">Ед.изм.</td>
|
||||
<td class="R0C9box">Кол-во</td>
|
||||
<td class="R0C9box">Цена/руб.<br/>без НДС</td>
|
||||
<td class="R0C9box">Стоимость/руб.<br/>без НДС</td>
|
||||
<!-- <td class="R0C9box">НДС</td>-->
|
||||
<!-- <td class="R0C9box">Стоимость/руб.<br/>c НДС</td>-->
|
||||
</tr>
|
||||
<t t-set="order_line" t-value="o.order_line.filtered(lambda s: 'аванс' not in s.name.lower() and 'депозит' not in s.name.lower())"/>
|
||||
<t t-set="quantity" t-value="sum([line.product_uom_qty for line in order_line])"/>
|
||||
<t t-set="sum_full"
|
||||
t-value="sum([line.product_uom_qty*line.price_unit for line in order_line])"/>
|
||||
<t t-set="sum_nds"
|
||||
t-value="sum([line.product_uom_qty*line.price_unit*1.2 for line in order_line])"/>
|
||||
<tr class="R0" t-foreach="order_line" t-as="line">
|
||||
<td class="R0C9box"><t t-esc="line.product_id.name or ''"/></td>
|
||||
<!-- <td class="R0C9box"><!–ГОСТ–></td>-->
|
||||
<td class="R0C9box"><t t-esc="line.product_id.uom_id.name or ''"/></td>
|
||||
<td class="R0C9box"><t t-esc="line.product_uom_qty or ''"/></td>
|
||||
<td class="R0C9box"><t t-esc="line.price_unit or ''"/></td>
|
||||
<td class="R0C9box"><t t-esc="line.price_unit*line.product_uom_qty or ''"/></td>
|
||||
<!-- <td class="R0C9box">20%</td>-->
|
||||
<!-- <td class="R0C9box"><t t-esc="line.price_unit*line.product_uom_qty*1.2 or ''"/></td>-->
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td></td>
|
||||
<!-- <td></td>-->
|
||||
<td>ИТОГО</td>
|
||||
<td class="R0C9box"><t t-esc="quantity or ''"/></td>
|
||||
<td class="R0C9box">x</td>
|
||||
<td class="R0C9box"><t t-esc="sum_full or ''"/></td>
|
||||
<!-- <td class="R0C9box">x</td>-->
|
||||
<!-- <td class="R0C9box"><t t-esc="sum_nds or ''"/></td>-->
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C5" colspan="8">Итого: <t t-esc="sum_full or ''"/> рублей (<t
|
||||
t-esc="o.mt_contract_id.rubles(sum_full) or ''"/>). В стоимость продукции входит стоимость
|
||||
тары и стоимость транспортных расходов, связанных с доставкой продукции до станции
|
||||
назначения.<br/>
|
||||
2. Базис поставки (пункт назначения) по отгрузочным реквизитам:<br/>
|
||||
<t t-esc="o.mt_contract_id.address_delivery(o.mt_contract_id.partner_id.id) or ''"/><br/>
|
||||
Грузополучатель: <t t-esc="o.mt_contract_id.partner_id.name or ''"/>, код <t
|
||||
t-esc="o.mt_contract_id.partner_id.id or ''"/>, ОКПО <t
|
||||
t-esc="o.mt_contract_id.partner_id.okpo or ''"/>.<br/>
|
||||
3. Условия оплаты: <t t-esc="o.payment_term_id.name or ''"/> согласно выставленному счету
|
||||
Поставщика.<br/>
|
||||
4. Срок отгрузки: <t
|
||||
t-esc="o.mt_contract_id.get_date_text(o.mt_contract_id.date_end) or ''"/><br/>
|
||||
5. Срок действия настоящей спецификации ограничен и равен сроку отгрузки по условиям
|
||||
данной спецификации.
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C0" colspan="8"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%; page-break-inside: avoid;">
|
||||
<COL WIDTH="5%"/>
|
||||
<COL WIDTH="30%"/>
|
||||
<COL WIDTH="15%"/>
|
||||
<COL WIDTH="5%"/>
|
||||
<COL WIDTH="30%"/>
|
||||
<COL WIDTH="15%"/>
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C4" colspan="6">Реквизиты и подписи сторон.</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C1" colspan="6"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rtl" colspan="3">Поставщик:</td>
|
||||
<td class="R0C6rtl" colspan="3">Покупатель:</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"><t t-esc="o.mt_contract_id.company_id.name or ''"/></td>
|
||||
<td class="R0C6rl" colspan="3"><t t-esc="o.mt_contract_id.partner_id.name or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="3">ИНН
|
||||
<t t-esc="o.mt_contract_id.company_id.inn or ''"/>
|
||||
</td>
|
||||
<td class="R0C7rl" colspan="3">ИНН <t
|
||||
t-esc="o.mt_contract_id.partner_id.inn or ''"/></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="2">ОГРН
|
||||
<t t-esc="o.company_id.company_registry or ''"/>
|
||||
</td>
|
||||
<td class="R0C6r" rowspan="2">
|
||||
<t t-esc="o.mt_contract_id.director_name_company or ''"/>
|
||||
</td>
|
||||
<t t-if="o.mt_contract_id.partner_type in ['company', 'company_ip']">
|
||||
<td class="R0C7rl" colspan="3">ОГРН
|
||||
<t t-esc="o.partner_id.ogrn or ''"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<td class="R0C7rl" colspan="3">Паспорт
|
||||
<t t-esc="o.partner_id.passport or ''"/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="3">КПП
|
||||
<t t-esc="o.mt_contract_id.company_id.kpp or ''"/>
|
||||
</td>
|
||||
<t t-if="o.mt_contract_id.partner_type == 'company'">
|
||||
<td class="R0C7rl" colspan="3">КПП
|
||||
<t t-esc="o.partner_id.kpp or ''"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<td class="R0C7rl" colspan="3"></td>
|
||||
</t>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3">Юридический адрес:
|
||||
</td>
|
||||
<td class="R0C6rl" colspan="3">Юридический адрес:
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l" colspan="3">
|
||||
<t t-esc="o.mt_contract_id.address(o.company_id) or ''"/>
|
||||
</td>
|
||||
<td class="R0C7rl" colspan="3">
|
||||
<t t-esc="o.mt_contract_id.address(o.partner_id) or ''"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6l"></td>
|
||||
<td class="R0C6tI">
|
||||
<SPAN>
|
||||
<t t-raw="o.stamp and o.mt_contract_id.img(o.company_id.chief_id.facsimile) or ''"/>
|
||||
</SPAN>
|
||||
</td>
|
||||
<td class="R0C6tS">
|
||||
<SPAN>
|
||||
<t t-raw="o.stamp and o.mt_contract_id.img(o.company_id.stamp) or ''"/>
|
||||
</SPAN>
|
||||
</td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6l"></td>
|
||||
<td class="R0C6b"></td>
|
||||
<td class="R0C6r">
|
||||
<t t-esc="''"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
<td class="R0C6rl" colspan="3"></td>
|
||||
</tr>
|
||||
<tr class="R0">
|
||||
<td class="R0C6rbl" colspan="3"></td>
|
||||
<td class="R0C6rbl" colspan="3"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<STYLE TYPE="text/css">
|
||||
body {background: #ffffff; margin: 0; font-family: Times new roman; font-size: 12pt; font-style:
|
||||
normal;}
|
||||
tr.R0{height: 30px;}
|
||||
tr.R0 td.R0C0{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: bottom;}
|
||||
tr.R0 td.R0C1{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: right; vertical-align: bottom;}
|
||||
tr.R0 td.R0C6tI{ font-family: Times new roman; font-size: 11pt; font-style: normal; font-weight:
|
||||
bold; text-align: left; vertical-align: top; border-bottom: #000000 1px solid;}
|
||||
tr.R0 td.R0C6tI { overflow: visible; }
|
||||
tr.R0 td.R0C6tI span { position: relative; }
|
||||
tr.R0 td.R0C6tI span img { position: absolute; width: 100px; top: -5px; left: 5px;}
|
||||
</STYLE>
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="width:100%">
|
||||
<COL WIDTH="20%"/>
|
||||
<COL WIDTH="20%"/>
|
||||
<COL WIDTH="20%"/>
|
||||
<COL WIDTH="20%"/>
|
||||
<COL WIDTH="20%"/>
|
||||
<tbody>
|
||||
<tr class="R0">
|
||||
<td class="R0C0">Подпись Исполнителя</td>
|
||||
<td class="R0C6tI">
|
||||
<SPAN>
|
||||
<t
|
||||
t-raw="o.stamp and o.mt_contract_id.img(company.chief_id.facsimile) or ''"/>
|
||||
</SPAN>
|
||||
</td>
|
||||
<td class="R0C0"></td>
|
||||
<td class="R0C1">Подпись Заказчика</td>
|
||||
<td class="R0C6tI"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col-xs-3 pull-right">
|
||||
<small style="font-size:18px;">
|
||||
<span>Страница</span>
|
||||
<span class="page"/>
|
||||
из
|
||||
<span class="topage"/>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<record id="paperformat_a4" 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">30</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>
|
||||
|
||||
<record id="action_report_contract_customer_order1" model="ir.actions.report">
|
||||
<field name="name">Спецификация</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">l10n_ru_contract_sale.report_contract_customer_order1</field>
|
||||
<field name="report_file">l10n_ru_contract_sale.report_contract_customer_order1</field>
|
||||
<field name="print_report_name">'Спецификация - %s' % (object.name)</field>
|
||||
<field name="binding_model_id" ref="sale.model_sale_order" />
|
||||
<field name="paperformat_id" ref="paperformat_a4" />
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
</odoo>
|
||||
1
l10n_ru_contract_sale/tests/__init__.py
Normal file
1
l10n_ru_contract_sale/tests/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import test_contract_sale
|
||||
250
l10n_ru_contract_sale/tests/test_contract_sale.py
Normal file
250
l10n_ru_contract_sale/tests/test_contract_sale.py
Normal file
@ -0,0 +1,250 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tests for l10n_ru_contract_sale — overdue debt check on sale order confirmation
|
||||
and invoice preparation with contract fields.
|
||||
|
||||
Validates: Requirements 16.1, 16.2, 16.3
|
||||
"""
|
||||
from datetime import date, timedelta
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _get_or_create_accounts(env):
|
||||
"""Return a receivable and income account for the current company."""
|
||||
receivable = env['account.account'].search([
|
||||
('account_type', '=', 'asset_receivable'),
|
||||
('company_ids', 'in', env.company.id),
|
||||
], limit=1)
|
||||
payable = env['account.account'].search([
|
||||
('account_type', '=', 'liability_payable'),
|
||||
('company_ids', 'in', env.company.id),
|
||||
], limit=1)
|
||||
income = env['account.account'].search([
|
||||
('account_type', '=', 'income'),
|
||||
('company_ids', 'in', env.company.id),
|
||||
], limit=1)
|
||||
return receivable, payable, income
|
||||
|
||||
|
||||
def _get_or_create_journal(env):
|
||||
"""Return or create a sales journal."""
|
||||
journal = env['account.journal'].search([
|
||||
('type', '=', 'sale'),
|
||||
('company_id', '=', env.company.id),
|
||||
], limit=1)
|
||||
if not journal:
|
||||
journal = env['account.journal'].create({
|
||||
'name': 'Test Sales Journal CS',
|
||||
'type': 'sale',
|
||||
'code': 'TSCS',
|
||||
'company_id': env.company.id,
|
||||
})
|
||||
return journal
|
||||
|
||||
|
||||
def _get_or_create_payment_term(env):
|
||||
"""Return or create a payment term."""
|
||||
term = env['account.payment.term'].search([], limit=1)
|
||||
if not term:
|
||||
term = env['account.payment.term'].create({'name': 'Immediate CS'})
|
||||
return term
|
||||
|
||||
|
||||
def _make_profile(env, journal, payment_term, receivable, payable, max_receivable=10000.0):
|
||||
"""Create a contract.profile."""
|
||||
return env['contract.profile'].create({
|
||||
'name': 'Test Profile CS',
|
||||
'journal_id': journal.id,
|
||||
'payment_term_id': payment_term.id,
|
||||
'receivable_account_id': receivable.id,
|
||||
'payable_account_id': payable.id,
|
||||
'max_receivable_id': max_receivable,
|
||||
})
|
||||
|
||||
|
||||
def _make_partner(env):
|
||||
"""Create a company partner."""
|
||||
return env['res.partner'].create({
|
||||
'name': 'Test Partner CS',
|
||||
'is_company': True,
|
||||
})
|
||||
|
||||
|
||||
def _make_contract(env, partner, profile):
|
||||
"""Create a minimal partner.contract.customer."""
|
||||
return env['partner.contract.customer'].create({
|
||||
'date_start': '2024-01-01',
|
||||
'date_end': '2024-12-31',
|
||||
'type': 'customer',
|
||||
'profile_id': profile.id,
|
||||
'partner_id': partner.id,
|
||||
'partner_type': 'company',
|
||||
'company_id': env.company.id,
|
||||
})
|
||||
|
||||
|
||||
def _make_product(env):
|
||||
"""Return or create a storable product."""
|
||||
product = env['product.product'].search([
|
||||
('type', '=', 'service'),
|
||||
], limit=1)
|
||||
if not product:
|
||||
product = env['product.product'].create({
|
||||
'name': 'Test Product CS',
|
||||
'type': 'service',
|
||||
})
|
||||
return product
|
||||
|
||||
|
||||
def _make_sale_order(env, partner, contract, product):
|
||||
"""Create a confirmed-ready sale order linked to a contract."""
|
||||
order = env['sale.order'].create({
|
||||
'partner_id': partner.id,
|
||||
'mt_contract_id': contract.id,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': 1.0,
|
||||
'price_unit': 500.0,
|
||||
})],
|
||||
})
|
||||
return order
|
||||
|
||||
|
||||
def _make_overdue_invoice(env, partner, journal, income_account, amount, days_overdue=10):
|
||||
"""Create a posted out_invoice that is overdue and unpaid."""
|
||||
due_date = date.today() - timedelta(days=days_overdue)
|
||||
invoice = env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': partner.id,
|
||||
'journal_id': journal.id,
|
||||
'invoice_date': due_date,
|
||||
'invoice_date_due': due_date,
|
||||
'invoice_line_ids': [(0, 0, {
|
||||
'name': 'Overdue line',
|
||||
'quantity': 1.0,
|
||||
'price_unit': amount,
|
||||
'account_id': income_account.id,
|
||||
})],
|
||||
})
|
||||
invoice.action_post()
|
||||
return invoice
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# TestContractSaleOrder
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestContractSaleOrder(TransactionCase):
|
||||
"""
|
||||
Tests for sale order confirmation with overdue debt check and
|
||||
invoice preparation with contract fields.
|
||||
|
||||
Validates: Requirements 16.1, 16.2, 16.3
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.receivable, self.payable, self.income = _get_or_create_accounts(self.env)
|
||||
self.journal = _get_or_create_journal(self.env)
|
||||
self.payment_term = _get_or_create_payment_term(self.env)
|
||||
self.partner = _make_partner(self.env)
|
||||
self.product = _make_product(self.env)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Requirement 16.1 — overdue debt > max_receivable raises ValidationError
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_confirm_with_overdue_debt_raises(self):
|
||||
"""
|
||||
Req 16.1 — confirming a sale order when the partner has overdue debt
|
||||
exceeding max_receivable raises ValidationError.
|
||||
"""
|
||||
profile = _make_profile(
|
||||
self.env, self.journal, self.payment_term,
|
||||
self.receivable, self.payable,
|
||||
max_receivable=100.0,
|
||||
)
|
||||
contract = _make_contract(self.env, self.partner, profile)
|
||||
|
||||
# Create an overdue posted invoice with amount > max_receivable
|
||||
_make_overdue_invoice(
|
||||
self.env, self.partner, self.journal, self.income,
|
||||
amount=500.0, # 500 > 100 (max_receivable)
|
||||
)
|
||||
|
||||
order = _make_sale_order(self.env, self.partner, contract, self.product)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
order.action_confirm()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Requirement 16.2 — debt within limit confirms without errors
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_confirm_within_debt_limit_ok(self):
|
||||
"""
|
||||
Req 16.2 — confirming a sale order when overdue debt is within
|
||||
max_receivable succeeds without errors.
|
||||
"""
|
||||
profile = _make_profile(
|
||||
self.env, self.journal, self.payment_term,
|
||||
self.receivable, self.payable,
|
||||
max_receivable=10000.0,
|
||||
)
|
||||
contract = _make_contract(self.env, self.partner, profile)
|
||||
|
||||
# Create an overdue invoice with amount well below max_receivable
|
||||
_make_overdue_invoice(
|
||||
self.env, self.partner, self.journal, self.income,
|
||||
amount=50.0, # 50 < 10000 (max_receivable)
|
||||
)
|
||||
|
||||
order = _make_sale_order(self.env, self.partner, contract, self.product)
|
||||
|
||||
# Should not raise
|
||||
order.action_confirm()
|
||||
self.assertEqual(order.state, 'sale',
|
||||
"Order should be confirmed (state='sale') when debt is within limit")
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Requirement 16.3 — _prepare_invoice copies mt_contract_id and osnovanie
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_prepare_invoice_copies_contract(self):
|
||||
"""
|
||||
Req 16.3 — _prepare_invoice transfers mt_contract_id and osnovanie
|
||||
from the sale order's contract to the invoice values dict.
|
||||
"""
|
||||
profile = _make_profile(
|
||||
self.env, self.journal, self.payment_term,
|
||||
self.receivable, self.payable,
|
||||
max_receivable=10000.0,
|
||||
)
|
||||
contract = _make_contract(self.env, self.partner, profile)
|
||||
order = _make_sale_order(self.env, self.partner, contract, self.product)
|
||||
order.action_confirm()
|
||||
|
||||
invoice_vals = order._prepare_invoice()
|
||||
|
||||
self.assertEqual(
|
||||
invoice_vals.get('mt_contract_id'), contract.id,
|
||||
"_prepare_invoice should copy mt_contract_id from the contract",
|
||||
)
|
||||
self.assertIn(
|
||||
'osnovanie', invoice_vals,
|
||||
"_prepare_invoice should set 'osnovanie' in invoice values",
|
||||
)
|
||||
self.assertTrue(
|
||||
invoice_vals['osnovanie'],
|
||||
"'osnovanie' should be a non-empty string",
|
||||
)
|
||||
self.assertIn(
|
||||
contract.name, invoice_vals['osnovanie'],
|
||||
"'osnovanie' should contain the contract name",
|
||||
)
|
||||
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="contract_customer_form_sale" model="ir.ui.view">
|
||||
<field name="name">partner.contract.customer.form.sale</field>
|
||||
<field name="model">partner.contract.customer</field>
|
||||
<field name="inherit_id" ref="l10n_ru_contract.contract_customer_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//notebook" position="inside">
|
||||
<page string="Продажи" name="sales">
|
||||
<group>
|
||||
<group>
|
||||
<field name="sale_order_id" readonly="state!='draft'"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="manager_id"/>
|
||||
<field name="team_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="contract_customer_action2" model="ir.actions.act_window">
|
||||
<field name="name">Договоры</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">partner.contract.customer</field>
|
||||
<field name="view_mode">kanban,list,form</field>
|
||||
<field name="domain">[('type', '=', 'customer')]</field>
|
||||
<field name="help" type="html">
|
||||
|
||||
<p class="oe_view_nocontent_create">
|
||||
Нет созданных контрактов
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Договоры" id="l10n_ru_contract.main" parent="sale.sale_menu_root"/>
|
||||
<menuitem name="Договоры" id="l10n_ru_contract.contracts" parent="l10n_ru_contract.main"
|
||||
action="l10n_ru_contract_sale.contract_customer_action2"/>
|
||||
|
||||
<menuitem name="Настройка" id="l10n_ru_contract.separator" parent="l10n_ru_contract.main"/>
|
||||
<menuitem name="Виды договоров" id="l10n_ru_contract.contract_profiles" parent="l10n_ru_contract.separator"
|
||||
action="l10n_ru_contract.contract_profile_action"/>
|
||||
<menuitem name="Включенные договора" id="l10n_ru_contract.contract_profile_setting" parent="l10n_ru_contract.separator"
|
||||
action="l10n_ru_contract.contract_allowed_profiles_action"/>
|
||||
</odoo>
|
||||
15
l10n_ru_contract_sale/views/sale_order_views.xml
Normal file
15
l10n_ru_contract_sale/views/sale_order_views.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<odoo>
|
||||
<record id="view_saleorder_form" model="ir.ui.view">
|
||||
<field name="name">view_saleorder_form</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale.view_order_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='partner_id']" position="after">
|
||||
<field name="mt_contract_id"
|
||||
domain="[('partner_id','=',sec_partner_id),('company_id','=',company_id)]"
|
||||
context="{'default_sec_partner_id':partner_id,'default_company_id':company_id,'default_type':'customer'}"/>
|
||||
<field name="sec_partner_id" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user