issue with the layout of the General Ledger report in the PDF format
This commit is contained in:
parent
abbab6ece5
commit
bf9bcbe5cd
|
|
@ -1,137 +1,92 @@
|
||||||
/* @font-face {
|
|
||||||
font-family: Amiri;
|
|
||||||
src: url('/account_financial_report/static/fonts/Amiri-Regular.ttf') format('opentype');
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
.act_as_table {
|
.act_as_table {
|
||||||
display: table !important;
|
display: table !important;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
/* border-style: solid; */
|
|
||||||
/* border-radius: 10px; */
|
|
||||||
}
|
}
|
||||||
.act_as_row {
|
.act_as_row {
|
||||||
display: table-row !important;
|
display: table-row !important;
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
}
|
}
|
||||||
.act_as_cell {
|
.act_as_cell {
|
||||||
display: table-cell !important;
|
display: table-cell !important;
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
border: solid 1px lightGrey !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*.act_as_cell.amount{
|
|
||||||
border: solid 1px lightGrey !important;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
.act_as_thead {
|
.act_as_thead {
|
||||||
display: table-header-group !important;
|
display: table-header-group !important;
|
||||||
}
|
}
|
||||||
.act_as_tbody {
|
.act_as_tbody {
|
||||||
display: table-row-group !important;
|
display: table-row-group !important;
|
||||||
}
|
}
|
||||||
.list_table, .data_table, .totals_table{
|
.list_table,
|
||||||
|
.data_table,
|
||||||
|
.totals_table {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
table-layout: fixed !important;
|
|
||||||
}
|
}
|
||||||
.act_as_row.labels, .act_as_cell.labels {
|
.act_as_row.labels {
|
||||||
background-color:#875A7B; !important;
|
background-color: #f0f0f0 !important;
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
.list_table, .data_table, .totals_table, .list_table .act_as_row {
|
.list_table,
|
||||||
border-left:1px;
|
.data_table,
|
||||||
border-right:1px;
|
.totals_table,
|
||||||
text-align:center;
|
.list_table .act_as_row {
|
||||||
font-size:10px;
|
border-left: 0px;
|
||||||
padding-right:3px;
|
border-right: 0px;
|
||||||
padding-left:3px;
|
text-align: center;
|
||||||
padding-top:2px;
|
font-size: 10px;
|
||||||
padding-bottom:2px;
|
padding-right: 3px;
|
||||||
/* border-collapse:collapse; */
|
padding-left: 3px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
.totals_table {
|
.totals_table {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.list_table .act_as_row.labels, .list_table .act_as_cell.labels, .list_table .act_as_row.initial_balance, .list_table .act_as_row.lines {
|
.list_table .act_as_row.labels,
|
||||||
/* border-color:black !important; */
|
.list_table .act_as_row.initial_balance,
|
||||||
/* border-bottom:1px solid lightGrey !important; */
|
.list_table .act_as_row.lines {
|
||||||
|
border-color: grey !important;
|
||||||
|
border-bottom: 1px solid lightGrey !important;
|
||||||
}
|
}
|
||||||
.data_table .act_as_cell{
|
.data_table .act_as_cell {
|
||||||
text-align: center;
|
border: 1px solid lightGrey;
|
||||||
padding: 5px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 14px !important;
|
|
||||||
}
|
|
||||||
.data_table .act_as_row{
|
|
||||||
transition: all .2s ease-in;
|
|
||||||
}
|
|
||||||
.data_table .act_as_row:hover{
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.data_table .act_as_row.labels:hover, .data_table .act_as_cell.labels:hover{
|
|
||||||
cursor: none;
|
|
||||||
}
|
|
||||||
.data_table .act_as_row:last-child{
|
|
||||||
/* border:none; */
|
|
||||||
}
|
|
||||||
.data_table .lines .act_as_cell{
|
|
||||||
padding: 10px 0 10px 0 !important;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.data_table .act_as_row .act_as_cell:first-child{
|
.data_table .act_as_cell,
|
||||||
font-weight: bold;
|
.list_table .act_as_cell,
|
||||||
}
|
.totals_table .act_as_cell {
|
||||||
.data_table .act_as_row .act_as_cell:nth-child(2){
|
|
||||||
text-align: center;
|
|
||||||
padding-left: 10px !important;
|
|
||||||
}
|
|
||||||
.data_table .act_as_row .act_as_cell:last-child{
|
|
||||||
/* border-right: none; */
|
|
||||||
}
|
|
||||||
.data_table .act_as_thead .labels .act_as_cell{
|
|
||||||
/* border-style: solid; */
|
|
||||||
/* border-bottom: 5px solid; */
|
|
||||||
}
|
|
||||||
.data_table .act_as_row.labels .act_as_cell:last-child {
|
|
||||||
/* border-top-right-radius: 10px; */
|
|
||||||
}
|
|
||||||
.data_table .act_as_row.labels .act_as_cell:first-child {
|
|
||||||
/* border-top-left-radius: 10px; */
|
|
||||||
}
|
|
||||||
.data_table .act_as_cell, .list_table .act_as_cell, .totals_table .act_as_cell {
|
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
.data_table .act_as_row.labels, .totals_table .act_as_row.labels, .act_as_cell.labels{
|
.data_table .act_as_row.labels,
|
||||||
|
.totals_table .act_as_row.labels {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.initial_balance .act_as_cell {
|
.initial_balance .act_as_cell {
|
||||||
font-style:italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
.account_title {
|
.account_title {
|
||||||
font-size:14px;
|
font-size: 11px;
|
||||||
font-weight:bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.account_title.labels {
|
.account_title.labels {
|
||||||
background-color:#F0F0F0 !important;
|
background-color: #f0f0f0 !important;
|
||||||
}
|
}
|
||||||
.act_as_cell.amount {
|
.act_as_cell.amount {
|
||||||
word-wrap:normal;
|
word-wrap: normal;
|
||||||
text-align:center;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.act_as_cell.left {
|
.act_as_cell.left {
|
||||||
text-align:left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
.act_as_cell.right {
|
.act_as_cell.right {
|
||||||
text-align:right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.list_table .act_as_cell{
|
/*.list_table .act_as_cell {*/
|
||||||
/* border-right:1px solid lightGrey; uncomment to active column lines */
|
/* border-right:1px solid lightGrey; uncomment to active column lines */
|
||||||
}
|
/*}*/
|
||||||
.list_table .act_as_cell.first_column {
|
.list_table .act_as_cell.first_column {
|
||||||
padding-left: 0px;
|
padding-left: 0px;
|
||||||
/* border-left:1px solid lightGrey; uncomment to active column lines */
|
/* border-left:1px solid lightGrey; uncomment to active column lines */
|
||||||
}
|
}
|
||||||
.overflow_ellipsis {
|
.overflow_ellipsis {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
@ -139,7 +94,7 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.custom_footer {
|
.custom_footer {
|
||||||
font-size:7px !important;
|
font-size: 7px !important;
|
||||||
}
|
}
|
||||||
.page_break {
|
.page_break {
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
|
|
@ -150,69 +105,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.o_account_financial_reports_page {
|
.o_account_financial_reports_page {
|
||||||
background-color: @odoo-view-background-color;
|
|
||||||
color: @odoo-main-text-color;
|
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
font-family: Helvetica, Arial;
|
||||||
|
|
||||||
|
|
||||||
/*New Style*/
|
|
||||||
.data_table{
|
|
||||||
/* border-radius: 10px !important; */
|
|
||||||
}
|
|
||||||
|
|
||||||
h4{
|
|
||||||
font-weight: bold;
|
|
||||||
padding-bottom: 30px !important;
|
|
||||||
padding-top: 30px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.act_as_cell {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.act_as_thead {
|
|
||||||
/* border-style: solid; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.act_as_thead .act_as_cell {
|
|
||||||
/* border-style: solid; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.first_column {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.splitted_outter{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.splitted_inner{
|
|
||||||
display: table-cell !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data_lines .act_as_cell{
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.bordered_table,table.bordered_table th, table.bordered_table td {
|
|
||||||
border: 1px solid black;
|
|
||||||
border-collapse: collapse;
|
|
||||||
text-align: center;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.bordered_table tr {
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.bordered_table th{
|
|
||||||
background-color: #875A7B;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.bordered_table td a{
|
|
||||||
color: #000;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
from . import models
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
'name': 'Odex Payment Distribution',
|
||||||
|
'version': '1.0',
|
||||||
|
'description': 'Distribute payment on several accounts',
|
||||||
|
'summary': 'Distribute payment on several accounts',
|
||||||
|
'author': 'Abdurrahman Saber',
|
||||||
|
'website': '',
|
||||||
|
'license': 'LGPL-3',
|
||||||
|
'category': 'Accounting',
|
||||||
|
'depends': ['account'],
|
||||||
|
'data': [
|
||||||
|
'security/ir.model.access.csv',
|
||||||
|
'reports/template.xml',
|
||||||
|
'views/account_payment_views.xml'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
from . import account_payment_line, account_payment, account_move
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
from odoo import models, api
|
||||||
|
|
||||||
|
class AccountMove(models.Model):
|
||||||
|
_inherit = 'account.move'
|
||||||
|
|
||||||
|
def write(self, vals):
|
||||||
|
res = super().write(vals)
|
||||||
|
if 'line_ids' in vals and self.payment_id:
|
||||||
|
self.payment_id._compute_payment_line_ids()
|
||||||
|
return res
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
|
class AccountPayment(models.Model):
|
||||||
|
_inherit = 'account.payment'
|
||||||
|
|
||||||
|
payment_line_ids = fields.One2many('account.payment.line', 'payment_id')
|
||||||
|
partner_type = fields.Selection(
|
||||||
|
selection_add=[
|
||||||
|
('many_entries', 'Many Entries'),
|
||||||
|
('account', 'Account'),
|
||||||
|
('employee', 'employee'),
|
||||||
|
],
|
||||||
|
ondelete={
|
||||||
|
'many_entries': 'set default',
|
||||||
|
'account': 'set default',
|
||||||
|
'employee': 'set default',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
sutible_account_ids = fields.Many2many(
|
||||||
|
'account.account',
|
||||||
|
string="Suitable Accounts",
|
||||||
|
compute='_compute_sutible_account_ids',
|
||||||
|
store=False
|
||||||
|
)
|
||||||
|
|
||||||
|
destination_account_id = fields.Many2one(
|
||||||
|
'account.account',
|
||||||
|
domain="[('id', 'in', sutible_account_ids)]"
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.depends('partner_type', 'company_id', 'partner_id', 'payment_type')
|
||||||
|
def _compute_sutible_account_ids(self):
|
||||||
|
for r in self:
|
||||||
|
if r.partner_type == 'account':
|
||||||
|
# إظهار جميع حسابات الشركة
|
||||||
|
company_id = r.company_id.id or self.env.company.id
|
||||||
|
domain = [('company_id', '=', company_id)]
|
||||||
|
r.sutible_account_ids = self.env['account.account'].search(domain)
|
||||||
|
elif r.partner_type == 'employee' and r.payment_type == 'outbound' and r.partner_id:
|
||||||
|
# حالة دفع للموظف - استخدام حساب المدين
|
||||||
|
employee_partner = r.partner_id
|
||||||
|
if employee_partner.property_account_receivable_id:
|
||||||
|
r.sutible_account_ids = employee_partner.property_account_receivable_id
|
||||||
|
else:
|
||||||
|
r.sutible_account_ids = self.env['account.account'].browse()
|
||||||
|
elif r.partner_type == 'employee' and r.payment_type == 'inbound' and r.partner_id:
|
||||||
|
# حالة استلام من الموظف - استخدام حساب الدائن
|
||||||
|
employee_partner = r.partner_id
|
||||||
|
if employee_partner.property_account_payable_id:
|
||||||
|
r.sutible_account_ids = employee_partner.property_account_payable_id
|
||||||
|
else:
|
||||||
|
r.sutible_account_ids = self.env['account.account'].browse()
|
||||||
|
elif r.partner_type in ['customer', 'supplier']:
|
||||||
|
# عرض جميع حسابات الشركة (السلوك الافتراضي كما كان من قبل)
|
||||||
|
company_id = r.company_id.id or self.env.company.id
|
||||||
|
domain = [('company_id', '=', company_id)]
|
||||||
|
r.sutible_account_ids = self.env['account.account'].search(domain)
|
||||||
|
else:
|
||||||
|
r.sutible_account_ids = self.env['account.account'].browse()
|
||||||
|
@api.constrains('payment_line_ids')
|
||||||
|
def _check_payment_line_ids(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.partner_type == 'many_entries' and not rec.payment_line_ids:
|
||||||
|
raise ValidationError(_('At least one distribution line is required for Many Entries partner type'))
|
||||||
|
|
||||||
|
@api.onchange('payment_line_ids')
|
||||||
|
def _compute_payment_amount_from_distribution(self):
|
||||||
|
self.ensure_one()
|
||||||
|
self.amount = sum(self.payment_line_ids.mapped('amount'))
|
||||||
|
|
||||||
|
def _compute_payment_line_ids(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.partner_type == 'many_entries':
|
||||||
|
lines_vals_list = []
|
||||||
|
total_amount = 0
|
||||||
|
|
||||||
|
for line in rec.move_id.line_ids.filtered(lambda l: l.credit != 0):
|
||||||
|
lines_vals_list.append(self._get_payment_line_vals_from_aml(line))
|
||||||
|
total_amount += line.credit
|
||||||
|
|
||||||
|
rec.write({
|
||||||
|
'payment_line_ids': [(5, 0)] + [(0, 0, line) for line in lines_vals_list],
|
||||||
|
'amount': total_amount
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
rec.payment_line_ids = False
|
||||||
|
|
||||||
|
def _get_payment_line_vals_from_aml(self, move_line_id):
|
||||||
|
return {
|
||||||
|
'account_id': move_line_id.account_id.id,
|
||||||
|
'label': move_line_id.name,
|
||||||
|
'partner_id': move_line_id.partner_id.id,
|
||||||
|
'analytic_account_id': move_line_id.analytic_account_id.id,
|
||||||
|
'analytic_tag_ids': [(6, 0, move_line_id.analytic_tag_ids.ids)],
|
||||||
|
'amount': move_line_id.credit
|
||||||
|
}
|
||||||
|
|
||||||
|
def _prepare_move_line_default_vals(self, write_off_line_vals=None):
|
||||||
|
res = super()._prepare_move_line_default_vals(write_off_line_vals)
|
||||||
|
|
||||||
|
if self.partner_type == 'many_entries':
|
||||||
|
counterpart_line = None
|
||||||
|
liquidity_accounts = [
|
||||||
|
self.journal_id.payment_debit_account_id.id,
|
||||||
|
self.journal_id.payment_credit_account_id.id
|
||||||
|
]
|
||||||
|
|
||||||
|
# Find the counterpart line (the line that is NOT the liquidity line)
|
||||||
|
for line in res:
|
||||||
|
if line.get('account_id') not in liquidity_accounts:
|
||||||
|
counterpart_line = line
|
||||||
|
break
|
||||||
|
|
||||||
|
if not counterpart_line:
|
||||||
|
return res
|
||||||
|
|
||||||
|
res.remove(counterpart_line)
|
||||||
|
|
||||||
|
counterpart_lines = self._prepare_counterpart_lines(counterpart_line)
|
||||||
|
res.extend(counterpart_lines)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def _prepare_counterpart_lines(self, counterpart_line):
|
||||||
|
result = []
|
||||||
|
for line in self.payment_line_ids:
|
||||||
|
# Determine debit/credit based on payment type
|
||||||
|
# For inbound payments: debit the accounts (receiving money)
|
||||||
|
# For outbound payments: credit the accounts (paying money)
|
||||||
|
if self.payment_type == 'inbound':
|
||||||
|
line_debit = line.amount
|
||||||
|
line_credit = 0.0
|
||||||
|
amount_currency = line.amount
|
||||||
|
else: # outbound
|
||||||
|
line_debit = 0.0
|
||||||
|
line_credit = line.amount
|
||||||
|
amount_currency = -line.amount
|
||||||
|
|
||||||
|
result.append({
|
||||||
|
'account_id': line.account_id.id,
|
||||||
|
'partner_id': line.partner_id.id,
|
||||||
|
'debit': line_debit,
|
||||||
|
'credit': line_credit,
|
||||||
|
'currency_id': self.currency_id.id,
|
||||||
|
'amount_currency': amount_currency,
|
||||||
|
'name': line.label or counterpart_line['name'],
|
||||||
|
'date_maturity': self.date,
|
||||||
|
'analytic_account_id': line.analytic_account_id.id,
|
||||||
|
'analytic_tag_ids': [(6, 0, line.analytic_tag_ids.ids)]
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _prepare_payment_display_name(self):
|
||||||
|
res = super()._prepare_payment_display_name()
|
||||||
|
res.update({
|
||||||
|
'inbound-many_entries': _('Customer Many Entries'),
|
||||||
|
'outbound-many_entries': _('Vendor Many Entries'),
|
||||||
|
'inbound-account': _('Customer Account'),
|
||||||
|
'outbound-account': _('Vendor Account'),
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
class AccountPaymentLine(models.Model):
|
||||||
|
_name = 'account.payment.line'
|
||||||
|
_description = 'Payment Line'
|
||||||
|
|
||||||
|
account_id = fields.Many2one('account.account', required=True, string='Account')
|
||||||
|
payment_id = fields.Many2one('account.payment', required=True, ondelete='cascade')
|
||||||
|
label = fields.Char(string='Label')
|
||||||
|
partner_id = fields.Many2one('res.partner', string='Partner')
|
||||||
|
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account')
|
||||||
|
analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags')
|
||||||
|
amount = fields.Monetary(currency_field='currency_id', string='Amount', required=True)
|
||||||
|
currency_id = fields.Many2one(related='payment_id.currency_id', readonly=True)
|
||||||
|
|
||||||
|
# حقول إضافية لتحسين UX
|
||||||
|
account_code = fields.Char(related='account_id.code', readonly=True, string='Account Code')
|
||||||
|
account_name = fields.Char(related='account_id.name', readonly=True, string='Account Name')
|
||||||
|
partner_name = fields.Char(related='partner_id.name', readonly=True, string='Partner Name')
|
||||||
|
|
||||||
|
@api.constrains('amount')
|
||||||
|
def _check_amount(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.amount <= 0:
|
||||||
|
raise ValidationError(_('Line amount must be greater than 0!'))
|
||||||
|
|
||||||
|
@api.onchange('account_id')
|
||||||
|
def _onchange_account_id(self):
|
||||||
|
"""تحديد الشريك تلقائياً بناءً على الحساب"""
|
||||||
|
if self.account_id and self.payment_id:
|
||||||
|
# إذا كان الحساب له شريك افتراضي، نستخدمه
|
||||||
|
if hasattr(self.account_id, 'partner_id') and self.account_id.partner_id:
|
||||||
|
self.partner_id = self.account_id.partner_id
|
||||||
|
elif self.payment_id.partner_id:
|
||||||
|
# وإلا نستخدم شريك الدفع
|
||||||
|
self.partner_id = self.payment_id.partner_id
|
||||||
|
|
||||||
|
@api.onchange('partner_id')
|
||||||
|
def _onchange_partner_id(self):
|
||||||
|
"""تحديث التسمية عند تغيير الشريك"""
|
||||||
|
if self.partner_id and not self.label:
|
||||||
|
payment_type_label = _('Payment to') if self.payment_id.payment_type == 'outbound' else _('Receipt from')
|
||||||
|
self.label = f"{payment_type_label} {self.partner_id.name}"
|
||||||
|
|
||||||
|
def name_get(self):
|
||||||
|
"""تحسين عرض السطور في الواجهة"""
|
||||||
|
result = []
|
||||||
|
for record in self:
|
||||||
|
name = f"[{record.account_id.code}] {record.account_id.name}"
|
||||||
|
if record.partner_id:
|
||||||
|
name += f" - {record.partner_id.name}"
|
||||||
|
if record.amount:
|
||||||
|
name += f" ({record.amount:,.2f})"
|
||||||
|
result.append((record.id, name))
|
||||||
|
return result
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<template id="report_payment_receipt_document_inherit" inherit_id="account.report_payment_receipt_document">
|
||||||
|
<xpath expr="//table[@class='table table-sm']" position="after">
|
||||||
|
<!-- نسخة ثانية من الجدول -->
|
||||||
|
<table class="table table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Invoice Date</th>
|
||||||
|
<th>Invoice Number</th>
|
||||||
|
<th>Reference</th>
|
||||||
|
<th class="text-right">Original Amount</th>
|
||||||
|
<th class="text-right">Amount Paid</th>
|
||||||
|
<th class="text-right">Balance</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr t-foreach="o.move_id._get_reconciled_invoices_partials()" t-as="rec">
|
||||||
|
<t t-set="amount" t-value="rec[1]"/>
|
||||||
|
<t t-set="inv" t-value="rec[2].move_id"/>
|
||||||
|
<t t-if="inv.move_type != 'entry'">
|
||||||
|
<td><span t-field="inv.invoice_date"/></td>
|
||||||
|
<td><span t-field="inv.name"/></td>
|
||||||
|
<td><span t-field="inv.ref"/></td>
|
||||||
|
<td class="text-right"><span t-field="inv.amount_total"/></td>
|
||||||
|
<td class="text-right">
|
||||||
|
<span t-esc="amount" t-options="{'widget': 'monetary', 'display_currency': o.currency_id}"/>
|
||||||
|
</td>
|
||||||
|
<td class="text-right"><span t-field="inv.amount_residual"/></td>
|
||||||
|
</t>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_account_payment_line,account.payment.line,model_account_payment_line,,1,1,1,1
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="view_account_payment_form" model="ir.ui.view">
|
||||||
|
<field name="name">view.account.payment.form</field>
|
||||||
|
<field name="model">account.payment</field>
|
||||||
|
<field name="inherit_id" ref="account.view_account_payment_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//sheet" position="inside">
|
||||||
|
<notebook>
|
||||||
|
<page name="amount_distribution" string="Distribution"
|
||||||
|
attrs="{'invisible': [('partner_type', '!=', 'many_entries')]}">
|
||||||
|
<field name="payment_line_ids" attrs="{'readonly': [('state', '!=', 'draft')]}">
|
||||||
|
<tree editable="bottom">
|
||||||
|
<field name="account_id" />
|
||||||
|
<field name="label" />
|
||||||
|
<field name="partner_id" />
|
||||||
|
<field name="analytic_account_id" optional="hide" />
|
||||||
|
<field name="analytic_tag_ids" optional="hide" widget="many2many_tags"/>
|
||||||
|
<field name="amount" sum="Total Amount"/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='amount']" position="attributes">
|
||||||
|
<attribute name="attrs">{'readonly': ['|', ('state', '!=', 'draft'),
|
||||||
|
('partner_type', '=', 'many_entries')]}</attribute>
|
||||||
|
<attribute name="force_save">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='amount']" position="after">
|
||||||
|
<field name="sutible_account_ids" invisible="1"/>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='destination_account_id']" position="attributes">
|
||||||
|
<attribute name="attrs">{'readonly': ['|', '|', ('state', '!=', 'draft'),
|
||||||
|
('is_internal_transfer', '=', True), ('partner_type', '=', 'many_entries')],
|
||||||
|
'required': [('partner_type', 'not in', ['many_entries'])],
|
||||||
|
'invisible': [('partner_type', '=', 'many_entries')]}</attribute>
|
||||||
|
<attribute name="required">0</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='partner_id']" position="attributes">
|
||||||
|
<attribute name="attrs">{'invisible': [('partner_type', '=', 'many_entries')]}</attribute>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
|
|
@ -1,11 +1,69 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from odoo import models, fields, _
|
from odoo import models, fields, _,api
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
class AccountPayment(models.Model):
|
class AccountPayment(models.Model):
|
||||||
_inherit = "account.payment"
|
_inherit = "account.payment"
|
||||||
|
|
||||||
|
# partner_type = fields.Selection(
|
||||||
|
# selection_add=[
|
||||||
|
# ('account', 'Account'),
|
||||||
|
# ('employee', 'Employee'),
|
||||||
|
# ('multi_account', 'Multi account'),
|
||||||
|
# ],
|
||||||
|
# ondelete={
|
||||||
|
# 'account': 'set default',
|
||||||
|
# 'employee': 'set default',
|
||||||
|
# 'multi_account': 'set default',
|
||||||
|
# },
|
||||||
|
# tracking=True
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# destination_account_id = fields.Many2one(
|
||||||
|
# comodel_name='account.account',
|
||||||
|
# string='Destination Account',
|
||||||
|
# store=True, readonly=False,
|
||||||
|
# compute='_compute_destination_account_id',
|
||||||
|
# domain="[('company_id', '=', company_id)]",
|
||||||
|
# check_company=True)
|
||||||
|
|
||||||
|
# @api.depends('journal_id', 'partner_id', 'partner_type', 'is_internal_transfer')
|
||||||
|
# def _compute_destination_account_id(self):
|
||||||
|
# self.destination_account_id = False
|
||||||
|
# for pay in self:
|
||||||
|
# if pay.is_internal_transfer:
|
||||||
|
# pay.destination_account_id = pay.journal_id.company_id.transfer_account_id
|
||||||
|
# elif pay.partner_type == 'customer':
|
||||||
|
# # Receive money from invoice or send money to refund it.
|
||||||
|
# if pay.partner_id:
|
||||||
|
# pay.destination_account_id = pay.partner_id.with_company(
|
||||||
|
# pay.company_id).property_account_receivable_id
|
||||||
|
# else:
|
||||||
|
# pay.destination_account_id = self.env['account.account'].search([
|
||||||
|
# ('company_id', '=', pay.company_id.id),
|
||||||
|
# ('internal_type', '=', 'receivable'),
|
||||||
|
# ('deprecated', '=', False),
|
||||||
|
# ], limit=1)
|
||||||
|
# elif pay.partner_type == 'supplier':
|
||||||
|
# # Send money to pay a bill or receive money to refund it.
|
||||||
|
# if pay.partner_id:
|
||||||
|
# pay.destination_account_id = pay.partner_id.with_company(pay.company_id).property_account_payable_id
|
||||||
|
# else:
|
||||||
|
# pay.destination_account_id = self.env['account.account'].search([
|
||||||
|
# ('company_id', '=', pay.company_id.id),
|
||||||
|
# ('internal_type', '=', 'payable'),
|
||||||
|
# ('deprecated', '=', False),
|
||||||
|
# ], limit=1)
|
||||||
|
#
|
||||||
|
# @api.depends('journal_id', 'partner_id', 'partner_type', 'is_internal_transfer')
|
||||||
|
# def _compute_destination_account_id(self):
|
||||||
|
# for pay in self:
|
||||||
|
# if pay.partner_type == 'account':
|
||||||
|
# pay.destination_account_id = pay.destination_account_id
|
||||||
|
#
|
||||||
|
# return super()._compute_destination_account_id()
|
||||||
|
|
||||||
def action_open_manual_reconciliation_widget(self):
|
def action_open_manual_reconciliation_widget(self):
|
||||||
''' Open the manual reconciliation widget for the current payment.
|
''' Open the manual reconciliation widget for the current payment.
|
||||||
:return: A dictionary representing an action.
|
:return: A dictionary representing an action.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue