Public release from ruodoo-project: 19.0 - 2026-05-10 21:19:01 UTC

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

View File

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
from . import sale_order
from . import sale_order_line
from . import order_prepaid
from . import order_prepaid_line
from . import account_payment
from . import res_company
from . import res_config_settings

View File

@ -0,0 +1,55 @@
from odoo import models, fields, api
class AccountPayment(models.Model):
_inherit = 'account.payment'
prepaid_id = fields.Many2one(comodel_name='order.prepaid', string='Авансовый счет')
amount_adv_currency = fields.Float(string='Сумма от счета', default=0)
@api.depends('journal_id', 'partner_id', 'partner_type')
def _compute_destination_account_id(self):
for pay in self:
pay.destination_account_id = False
company = pay.company_id
if pay.prepaid_id:
if pay.payment_type == 'inbound' and company.advance_in_id:
pay.destination_account_id = company.advance_in_id.id
elif pay.payment_type == 'outbound' and company.advance_out_id:
pay.destination_account_id = company.advance_out_id.id
if pay.destination_account_id:
continue
partner = pay.partner_id
# if pay.default_is_internal_transfer:
# pay.destination_account_id = pay.destination_journal_id.company_id.transfer_account_id
if pay.partner_type == 'customer':
pay.destination_account_id = self._get_partner_account(
partner,
company,
account_type='asset_receivable',
partner_account_field='property_account_receivable_id'
)
elif pay.partner_type == 'supplier':
pay.destination_account_id = self._get_partner_account(
partner,
company,
account_type='liability_payable',
partner_account_field='property_account_payable_id'
)
def _get_partner_account(self, partner, company, account_type, partner_account_field):
if partner:
account = getattr(partner.with_company(company), partner_account_field, False)
if account:
return account.id
account = self.env['account.account'].search([
*self.env['account.account']._check_company_domain(company),
('account_type', '=', account_type),
('deprecated', '=', False),
], limit=1)
return account.id if account else False

View File

@ -0,0 +1,195 @@
from odoo import models, fields, api
class OrderPrepaid(models.Model):
_name = 'order.prepaid'
_description = 'Авансовые платежи'
_inherit = ['mail.thread', 'mail.activity.mixin']
name = fields.Char(string='Название', default='Draft', copy=False)
partner_id = fields.Many2one(comodel_name='res.partner', string='Контрагент')
invoice_partner_display_name = fields.Char(compute='_compute_invoice_partner_display_info', store=True)
payment_terms = fields.Char(string='Условия оплаты')
invoice_date = fields.Date(string='Дата счета', default=fields.Date.context_today, required=True)
invoice_date_due = fields.Date(string='Срок оплаты', default=fields.Date.context_today, required=True)
company_id = fields.Many2one(comodel_name='res.company', string='Компания')
sale_order_id = fields.Many2one(comodel_name='sale.order', string='Заказ продаж')
advance_type = fields.Selection(selection=[('outbound', 'Исходящий'),('inbound', 'Входящий')],
string='Тип платежа', default='inbound')
comment = fields.Text(string='Комментарий')
state = fields.Selection(selection=[('cancel', 'Отменено'),
('draft', 'Черновик'),
('posted', 'Проведено')],
string='Статус', default='draft')
prepaid_line = fields.One2many(comodel_name='order.prepaid.line', inverse_name='prepaid_id', string='Строки счета')
currency_id = fields.Many2one(comodel_name='res.currency', string='Валюта', tracking=True, required=True, readonly=False,
compute='_compute_currency_id', inverse='_inverse_currency_id',
store=True, precompute=True)
partner_bank_id = fields.Many2one(comodel_name='res.partner.bank', string="Банковский счёт получателя")
amount = fields.Monetary(currency_field='currency_id', store=True, readonly=False,
compute='_compute_amount', string='Всего')
payment_line_ids = fields.One2many(comodel_name='account.payment', inverse_name='prepaid_id',
string='Связанные платежи', compute_sudo=True, store=True)
company_partner_id = fields.Many2one(string='Контакт компании', related='company_id.partner_id')
payment_state = fields.Selection(selection=[('not_paid', 'Не оплачен'),
('in_payment', 'В оплате'),
('paid', 'Оплачено'),
('partial', 'Частично оплачено'),
],
string="Статус платежа", readonly=True, copy=False, tracking=True,
compute='_compute_payment_state', store=True)
payment_id = fields.Many2one(comodel_name='account.payment', string='Платеж')
payment_amount = fields.Monetary(currency_field='currency_id', compute='_compute_payment_amount', store=True, string='Выплачено')
amount_sum_line = fields.Monetary(currency_field='currency_id', store=True, readonly=False,
compute='_compute_amount_sum_line', string='Сумма')
amount_residual = fields.Monetary(currency_field='currency_id', store=True, readonly=False,
compute='_compute_amount_residual', string='Остаток долга', default=0, copy=False)
all_total = fields.Monetary(currency_field='currency_id', store=True, readonly=True,
compute='_compute_all_total', string='Всего', default=0, copy=False)
th_field_taxes = fields.Boolean(string='Проверка столбца налогов', compute='_th_field_taxes', store=True)
@api.depends('prepaid_line.tax_ids')
def _th_field_taxes(self):
for rec in self:
values = rec.prepaid_line.mapped('tax_ids')
if values:
rec.th_field_taxes = True
else:
rec.th_field_taxes = False
@api.depends('amount')
def _compute_all_total(self):
for rec in self:
if rec.amount > 0:
rec.all_total = -(rec.amount) if rec.advance_type == 'outbound' else rec.amount
else:
rec.all_total = 0
@api.depends('partner_id', 'partner_id.display_name')
def _compute_invoice_partner_display_info(self):
for record in self:
vendor_display_name = record.partner_id.display_name if record.partner_id else ''
record.invoice_partner_display_name = vendor_display_name
@api.depends('amount', 'payment_amount', 'state')
def _compute_amount_residual(self):
for rec in self:
if rec.state == 'posted':
rec.amount_residual = rec.amount - abs(rec.payment_amount)
else:
rec.amount_residual = 0
@api.depends('prepaid_line', 'prepaid_line.tax_ids')
def _compute_amount_sum_line(self):
for rec in self:
amount = 0
for el in rec.prepaid_line:
amount += el.price_subtotal
rec.amount_sum_line = amount
@api.depends('payment_amount', 'payment_line_ids.reconciled_statement_line_ids')
def _compute_payment_state(self):
if not self.payment_line_ids:
self.payment_state = 'not_paid'
elif abs(self.payment_amount) != 0:
if abs(self.payment_amount) >= self.amount:
bool = True
for rec in self.payment_line_ids:
if not rec.reconciled_statement_line_ids:
bool = False
break
self.payment_state = 'paid' if bool else 'in_payment'
else:
self.payment_state = 'partial'
else:
self.payment_state = 'not_paid'
@api.depends('payment_line_ids', 'payment_line_ids.state')
def _compute_payment_amount(self):
for rec in self:
payments = self.env['account.payment'].with_company(rec.company_id)
records = payments.search([('state', '=', 'posted'),
('prepaid_id', '=', rec.id),
('company_id', '=', rec.company_id.id)])
amount = sum(records.mapped('amount_adv_currency'))
rec.payment_amount = amount
@api.depends('prepaid_line')
def _compute_amount(self):
for rec in self:
amount = 0
for el in rec.prepaid_line:
amount += el.price_unit * el.quantity
rec.amount = amount
@api.depends('company_id')
def _compute_currency_id(self):
for invoice in self:
invoice.currency_id = invoice.company_id.currency_id
@api.onchange('currency_id')
def _inverse_currency_id(self):
self.currency_id = self.currency_id
def action_post(self):
if self.name == 'Draft':
self.name = self.env['ir.sequence'].next_by_code('order.prepaid')
self.state = 'posted'
def button_draft(self):
self.state = 'draft'
payments = self.env['account.payment'].with_company(self.company_id)
records = payments.search([('prepaid_id', '=', self.id), ('company_id', '=', self.company_id.id)])
if records:
for el in records:
el.action_draft()
el.action_cancel()
el.unlink()
def button_cancel(self):
self.state = 'cancel'
def action_register_payment(self):
journals = self.env['account.journal'].with_company(self.company_id.id)
journal = journals.search([('type', 'in', ['bank', 'cash']), ('company_id', '=', self.company_id.id)])
if journal:
if self.partner_bank_id:
journal_bank = journal.search([('bank_account_id', '=', self.partner_bank_id.id)], limit=1)
journal_id = journal_bank.id if journal_bank else journal[0].id
else:
journal_id = journal[0].id
else:
journal_id = False
delta_amount = self.amount - abs(self.payment_amount)
default_amount = delta_amount if delta_amount > 0 else 0
return {
'name': 'Регистрация платежа',
'res_model': 'payment.register.prepaid',
'view_mode': 'form',
'views': [[False, 'form']],
'context': {
'default_prepaid_id': self.id,
'default_company_id': self.company_id.id,
'default_communication': self.name,
'default_amount': default_amount,
'default_amount_const': default_amount,
'default_journal_id': journal_id
},
'target': 'new',
'type': 'ir.actions.act_window',
}

View File

@ -0,0 +1,82 @@
from odoo import models, fields, api
class OrderPrepaidLine(models.Model):
_name = 'order.prepaid.line'
_inherit = "analytic.mixin"
_description = 'Order Prepaid line'
product_id = fields.Many2one(comodel_name='product.product', string='Продукт')
name = fields.Char(string='Метка', compute='_compute_name')
label = fields.Char(string='Метка')
account_id = fields.Many2one(comodel_name='account.account', string='Счёт')
quantity = fields.Float(string='Количество', default=1, digits='Product Unit of Measure')
product_uom_id = fields.Many2one(comodel_name='uom.uom', string='Ед. измерения', compute='_compute_product_uom_id')
price_unit = fields.Float(string='Цена', digits='Product Price', default=1)
tax_ids = fields.Many2many(comodel_name='account.tax', string="Налоги")
prepaid_id = fields.Many2one(comodel_name='order.prepaid', string='Авансовый счет')
sale_ids = fields.Many2many(comodel_name='sale.order.line', string='Связные строки заказа')
analytic_distribution = fields.Json(string='Аналитическое распределение')
price_subtotal = fields.Monetary(
string='Subtotal',
compute='_compute_totals', store=True,
currency_field='currency_id',
)
price_total = fields.Monetary(
string='Total',
compute='_compute_totals', store=True,
currency_field='currency_id',
)
currency_id = fields.Many2one(
comodel_name='res.currency',
string='Currency',
compute='_compute_currency_id', store=True, readonly=False, precompute=True,
required=True,
)
@api.depends('prepaid_id.currency_id')
def _compute_currency_id(self):
for line in self:
line.currency_id = line.prepaid_id.currency_id
@api.depends('quantity', 'price_unit', 'tax_ids', 'currency_id')
def _compute_totals(self):
for line in self:
subtotal = line.quantity * line.price_unit
if line.tax_ids:
taxes_res = line.tax_ids.compute_all(
line.price_unit,
quantity=line.quantity,
currency=line.currency_id,
product=line.product_id,
partner=self.prepaid_id.partner_id,
is_refund=False,
)
line.price_subtotal = taxes_res['total_excluded']
line.price_total = taxes_res['total_included']
else:
line.price_total = line.price_subtotal = subtotal
@api.depends('product_id')
def _compute_product_uom_id(self):
for line in self:
if line.product_id:
line.product_uom_id = line.product_id.uom_id
else:
line.product_uom_id = False
@api.depends('product_id')
def _compute_name(self):
for line in self:
if line.product_id:
line.name = line.product_id.name
else:
line.name = ''

View File

@ -0,0 +1,8 @@
from odoo import models, fields
class ResCompany(models.Model):
_inherit = 'res.company'
advance_out_id = fields.Many2one(comodel_name='account.account', string='Исходящий счет')
advance_in_id = fields.Many2one(comodel_name='account.account', string='Входящий счет')

View File

@ -0,0 +1,14 @@
from odoo import models, fields
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
advance_out_id = fields.Many2one(comodel_name='account.account', string='Исходящий счет', related='company_id.advance_out_id',readonly=False)
advance_in_id = fields.Many2one(comodel_name='account.account', string='Входящий счет', related='company_id.advance_in_id',readonly=False)

View File

@ -0,0 +1,68 @@
from odoo import models, fields
from odoo.fields import Command
class SaleOrder(models.Model):
_inherit = 'sale.order'
prepaid_advance_count = fields.Integer(string='Закупки', compute='_compute_prepaid_advance_count')
def _compute_prepaid_advance_count(self):
for el in self:
prepaid = self.env['order.prepaid'].search([('sale_order_id', '=', self.id), ('state', '!=', 'cancel')])
el.prepaid_advance_count = len(prepaid)
def action_prepaid_advance(self):
action = self.env['ir.actions.act_window']._for_xml_id('l10n_ru_advance_payments.action_order_prepaid')
prepaid = self.env['order.prepaid'].search([('sale_order_id', '=', self.id), ('state', '!=', 'cancel')])
if len(prepaid) > 1:
action['domain'] = [('sale_order_id', '=', self.id)]
action['context'] = {
'group_by': ['advance_type']
}
elif len(prepaid) == 1:
return {
'type': 'ir.actions.act_window',
'res_model': 'order.prepaid',
'res_id': prepaid.id,
'view_mode': 'form',
'view_type': 'form',
'target': 'self'
}
return action
def button_advance(self):
prepaid_vals = {
'partner_id': self.partner_id.id,
'company_id': self.company_id.id,
'sale_order_id': self.id,
'prepaid_line': [],
}
for line in self.order_line:
elem = self._prepare_line(line)
prepaid_vals['prepaid_line'].append((0, 0, elem))
prepaid = self.env['order.prepaid'].create(prepaid_vals)
return {
'type': 'ir.actions.act_window',
'res_model': 'order.prepaid',
'res_id': prepaid.id,
'view_mode': 'form',
'view_type': 'form',
'target': 'self'
}
def _prepare_line(self, line):
res = {
'product_id': line.product_id.id,
'product_uom_id': line.product_uom_id.id,
'quantity': line.product_uom_qty,
'price_unit': line.price_unit,
'tax_ids': [(6, 0, line.tax_ids.ids)],
'sale_ids': [Command.link(line.id)],
}
if line.analytic_distribution:
res['analytic_distribution'] = line.analytic_distribution
return res

View File

@ -0,0 +1,9 @@
from odoo import models, fields
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
prepaid_ids = fields.Many2many('order.prepaid.line', string='Связные строки авансовых счетов')
bool_const_bill = fields.Boolean(copy=False)
bool_const_bill_bill = fields.Boolean(copy=False)