[MIG] account_usability_akretion to v18
Move code from account_usability_akretion to base_usability_akretion
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
from . import account_account
|
||||
from . import account_analytic_account
|
||||
#from . import account_bank_statement
|
||||
from . import account_incoterms
|
||||
from . import account_journal
|
||||
from . import account_move
|
||||
from . import account_move_line
|
||||
from . import account_partial_reconcile
|
||||
from . import res_partner
|
||||
from . import res_company
|
||||
#from . import product
|
||||
from . import account_invoice_report
|
||||
from . import res_partner_bank
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright 2015-2022 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class AccountAccount(models.Model):
|
||||
_inherit = 'account.account'
|
||||
|
||||
@api.depends('name', 'code')
|
||||
def name_get(self):
|
||||
if self._context.get('account_account_show_code_only'):
|
||||
res = []
|
||||
for record in self:
|
||||
res.append((record.id, record.code))
|
||||
return res
|
||||
else:
|
||||
return super().name_get()
|
||||
@@ -1,21 +1,20 @@
|
||||
# Copyright 2015-2022 Akretion (http://www.akretion.com)
|
||||
# Copyright 2015-2024 Akretion France (https://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class AccountAnalyticAccount(models.Model):
|
||||
_inherit = 'account.analytic.account'
|
||||
|
||||
def name_get(self):
|
||||
@api.depends_context('analytic_account_show_code_only')
|
||||
def _compute_display_name(self):
|
||||
if self._context.get('analytic_account_show_code_only'):
|
||||
res = []
|
||||
for record in self:
|
||||
res.append((record.id, record.code or record.name))
|
||||
return res
|
||||
for rec in self:
|
||||
rec.display_name = rec.code or rec.name
|
||||
else:
|
||||
return super().name_get()
|
||||
return super()._compute_display_name()
|
||||
|
||||
_sql_constraints = [(
|
||||
'code_company_unique',
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
# Copyright 2015-2020 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools.misc import format_date
|
||||
|
||||
|
||||
class AccountBankStatement(models.Model):
|
||||
_inherit = 'account.bank.statement'
|
||||
|
||||
start_date = fields.Date(
|
||||
compute='_compute_dates', string='Start Date', store=True)
|
||||
end_date = fields.Date(
|
||||
compute='_compute_dates', string='End Date', store=True)
|
||||
line_count = fields.Integer(
|
||||
compute='_compute_dates', string='# of Lines', store=True)
|
||||
hide_bank_statement_balance = fields.Boolean(
|
||||
related='journal_id.hide_bank_statement_balance', readonly=True)
|
||||
|
||||
@api.depends('line_ids.date')
|
||||
def _compute_dates(self):
|
||||
for st in self:
|
||||
dates = [line.date for line in st.line_ids]
|
||||
st.start_date = dates and min(dates) or False
|
||||
st.end_date = dates and max(dates) or False
|
||||
st.line_count = len(dates)
|
||||
|
||||
def _check_balance_end_real_same_as_computed(self):
|
||||
for stmt in self:
|
||||
if not stmt.hide_bank_statement_balance:
|
||||
super(AccountBankStatement, stmt)._check_balance_end_real_same_as_computed()
|
||||
return True
|
||||
|
||||
@api.depends('name', 'start_date', 'end_date')
|
||||
def name_get(self):
|
||||
res = []
|
||||
for statement in self:
|
||||
name = "%s (%s => %s)" % (
|
||||
statement.name,
|
||||
statement.start_date and format_date(self.env, statement.start_date) or '',
|
||||
statement.end_date and format_date(self.env, statement.end_date) or '')
|
||||
res.append((statement.id, name))
|
||||
return res
|
||||
|
||||
def button_reopen(self):
|
||||
self = self.with_context(skip_undo_reconciliation=True)
|
||||
return super().button_reopen()
|
||||
|
||||
def button_undo_reconciliation(self):
|
||||
self.line_ids.button_undo_reconciliation()
|
||||
|
||||
|
||||
class AccountBankStatementLine(models.Model):
|
||||
_inherit = 'account.bank.statement.line'
|
||||
# Native order is:
|
||||
# _order = 'statement_id desc, sequence, id desc'
|
||||
_order = 'statement_id desc, date desc, sequence, id desc'
|
||||
|
||||
# Disable guessing for reconciliation
|
||||
# because my experience with several customers shows that it is a problem
|
||||
# in the following scenario : move line 'x' has been "guessed" by OpenERP
|
||||
# to be reconciled with a statement line 'Y' at the end of the bank
|
||||
# statement, but it is a mistake because it should be reconciled with
|
||||
# statement line 'B' at the beginning of the bank statement
|
||||
# When the user is on statement line 'B', he tries to select
|
||||
# move line 'x', but it can't find it... because it is already "reserved"
|
||||
# by the guess of OpenERP for statement line 'Y' ! To solve this problem,
|
||||
# the user must go to statement line 'Y' and unselect move line 'x'
|
||||
# and then come back on statement line 'B' and select move line 'A'...
|
||||
# but non super-expert users can't do that because it is impossible to
|
||||
# figure out that the fact that the user can't find move line 'x'
|
||||
# is caused by this.
|
||||
# Set search_reconciliation_proposition to False by default
|
||||
# TODO: re-write in v10
|
||||
# def get_data_for_reconciliations(
|
||||
# self, cr, uid, ids, excluded_ids=None,
|
||||
# search_reconciliation_proposition=False, context=None):
|
||||
# # Make variable name shorted for PEP8 !
|
||||
# search_rec_prop = search_reconciliation_proposition
|
||||
# return super().\
|
||||
# get_data_for_reconciliations(
|
||||
# cr, uid, ids, excluded_ids=excluded_ids,
|
||||
# search_reconciliation_proposition=search_rec_prop,
|
||||
# context=context)
|
||||
|
||||
def show_account_move(self):
|
||||
self.ensure_one()
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
'account.action_move_line_form')
|
||||
# Note: this action is on account.move, not account.move.line !
|
||||
action.update({
|
||||
'views': False,
|
||||
'view_id': False,
|
||||
'view_mode': 'form,tree',
|
||||
'res_id': self.move_id.id,
|
||||
})
|
||||
return action
|
||||
|
||||
def button_undo_reconciliation(self):
|
||||
if self._context.get("skip_undo_reconciliation"):
|
||||
return
|
||||
else:
|
||||
return super().button_undo_reconciliation()
|
||||
@@ -1,31 +1,15 @@
|
||||
# Copyright 2015-2022 Akretion (http://www.akretion.com)
|
||||
# Copyright 2015-2024 Akretion France (https://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models
|
||||
from odoo import models
|
||||
|
||||
|
||||
class AccountIncoterms(models.Model):
|
||||
_inherit = 'account.incoterms'
|
||||
_rec_names_search = ["name", "code"]
|
||||
|
||||
_sql_constraints = [(
|
||||
'code_unique',
|
||||
'unique(code)',
|
||||
'This incoterm code already exists.')]
|
||||
|
||||
@api.depends('code', 'name')
|
||||
def name_get(self):
|
||||
res = []
|
||||
for rec in self:
|
||||
res.append((rec.id, '[%s] %s' % (rec.code, rec.name)))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
||||
if args is None:
|
||||
args = []
|
||||
if name and operator == 'ilike':
|
||||
recs = self.search([('code', '=ilike', name + '%')] + args, limit=limit)
|
||||
if recs:
|
||||
return recs.name_get()
|
||||
return super().name_search(name=name, args=args, operator=operator, limit=limit)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Copyright 2022 Akretion (http://www.akretion.com)
|
||||
# Copyright 2022-2024 Akretion France (https://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools import SQL
|
||||
|
||||
|
||||
class AccountInvoiceReport(models.Model):
|
||||
@@ -12,6 +13,6 @@ class AccountInvoiceReport(models.Model):
|
||||
|
||||
@api.model
|
||||
def _select(self):
|
||||
res = super()._select()
|
||||
res += ", COALESCE(partner.industry_id, commercial_partner.industry_id) AS industry_id"
|
||||
return res
|
||||
return SQL(
|
||||
"%s, COALESCE(partner.industry_id, commercial_partner.industry_id) AS industry_id",
|
||||
super()._select())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2015-2022 Akretion (http://www.akretion.com)
|
||||
# Copyright 2015-2024 Akretion France (https://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
@@ -17,41 +17,34 @@ class AccountJournal(models.Model):
|
||||
"the start/end balance and you regularly check the accounting balance "
|
||||
"of the bank account vs the amount of your bank account."
|
||||
)
|
||||
# Used to set default user_type_id on account fields via context
|
||||
# account_type_current_assets_id = fields.Many2one(
|
||||
# 'account.account.type',
|
||||
# default=lambda self: self.env.ref('account.data_account_type_current_assets').id)
|
||||
|
||||
@api.depends(
|
||||
'name', 'currency_id', 'company_id', 'company_id.currency_id', 'code')
|
||||
def name_get(self):
|
||||
res = []
|
||||
@api.depends('name', 'currency_id', 'company_id', 'code')
|
||||
@api.depends_context('journal_show_code_only')
|
||||
def _compute_display_name(self):
|
||||
if self._context.get('journal_show_code_only'):
|
||||
for journal in self:
|
||||
res.append((journal.id, journal.code))
|
||||
return res
|
||||
journal.display_name = journal.code
|
||||
else:
|
||||
for journal in self:
|
||||
name = "[%s] %s" % (journal.code, journal.name)
|
||||
name = f"[{journal.code}] {journal.name}"
|
||||
if (
|
||||
journal.currency_id and
|
||||
journal.currency_id != journal.company_id.currency_id):
|
||||
name = "%s (%s)" % (name, journal.currency_id.name)
|
||||
res.append((journal.id, name))
|
||||
return res
|
||||
name = f"{name} ({journal.currency_id.name})"
|
||||
journal.display_name = name
|
||||
|
||||
def open_outstanding_payments(self):
|
||||
self.ensure_one()
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
"account.action_account_moves_all")
|
||||
action['domain'] = [
|
||||
('account_id', 'in', (self.payment_debit_account_id.id, self.payment_credit_account_id.id)),
|
||||
('journal_id', '=', self.id),
|
||||
('display_type', 'not in', ('line_section', 'line_note')),
|
||||
('parent_state', '!=', 'cancel'),
|
||||
]
|
||||
action['context'] = {
|
||||
'search_default_unreconciled': True,
|
||||
'search_default_posted': True,
|
||||
}
|
||||
return action
|
||||
# def open_outstanding_payments(self):
|
||||
# self.ensure_one()
|
||||
# action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
# "account.action_account_moves_all")
|
||||
# action['domain'] = [
|
||||
# ('account_id', 'in', (self.payment_debit_account_id.id, self.payment_credit_account_id.id)),
|
||||
# ('journal_id', '=', self.id),
|
||||
# ('display_type', 'not in', ('line_section', 'line_note')),
|
||||
# ('parent_state', '!=', 'cancel'),
|
||||
# ]
|
||||
# action['context'] = {
|
||||
# 'search_default_unreconciled': True,
|
||||
# 'search_default_posted': True,
|
||||
# }
|
||||
# return action
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
# Copyright 2015-2022 Akretion (http://www.akretion.com)
|
||||
# Copyright 2015-2024 Akretion France (https://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from datetime import timedelta
|
||||
from collections import defaultdict
|
||||
import logging
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.osv import expression
|
||||
from odoo.tools import float_is_zero
|
||||
from odoo.tools.misc import format_date
|
||||
from odoo.tools.safe_eval import safe_eval, time
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -19,9 +16,6 @@ _logger = logging.getLogger(__name__)
|
||||
class AccountMove(models.Model):
|
||||
_inherit = 'account.move'
|
||||
|
||||
# By default, we can still modify "ref" when account move is posted
|
||||
# which seems a bit lazy for me...
|
||||
ref = fields.Char(states={'posted': [('readonly', True)]})
|
||||
invoice_date_due = fields.Date(tracking=True)
|
||||
invoice_payment_term_id = fields.Many2one(tracking=True)
|
||||
journal_id = fields.Many2one(tracking=True)
|
||||
@@ -38,36 +32,34 @@ class AccountMove(models.Model):
|
||||
compute="_compute_sales_dates",
|
||||
help="This information appear on invoice qweb report "
|
||||
"(you may use it for your own report)")
|
||||
# There is a native "blocked" field (bool) on account.move.line
|
||||
# We want to have that field on invoices to improve usability
|
||||
# while keeping compatibility with the standard Odoo datamodel
|
||||
blocked = fields.Boolean(
|
||||
compute="_compute_blocked",
|
||||
inverse="_inverse_blocked",
|
||||
store=True,
|
||||
string="Dispute",
|
||||
tracking=True,
|
||||
)
|
||||
# The native "blocked" field (bool) on account.move.line has been removed in v18
|
||||
# blocked = fields.Boolean(
|
||||
# compute="_compute_blocked",
|
||||
# inverse="_inverse_blocked",
|
||||
# store=True,
|
||||
# string="Dispute",
|
||||
# tracking=True,
|
||||
# )
|
||||
# Field search_account_id is just for search view
|
||||
search_account_id = fields.Many2one(related='line_ids.account_id')
|
||||
|
||||
@api.depends("line_ids", "line_ids.blocked")
|
||||
def _compute_blocked(self):
|
||||
for move in self:
|
||||
move.blocked = any(
|
||||
[
|
||||
l.blocked
|
||||
for l in move.line_ids
|
||||
if l.account_id.account_type in ("liability_payable", "asset_receivable")
|
||||
]
|
||||
)
|
||||
# @api.depends("line_ids", "line_ids.blocked")
|
||||
# def _compute_blocked(self):
|
||||
# for move in self:
|
||||
# move.blocked = any(
|
||||
# [
|
||||
# l.blocked
|
||||
# for l in move.line_ids
|
||||
# if l.account_id.account_type in ("liability_payable", "asset_receivable")
|
||||
# ]
|
||||
# )
|
||||
|
||||
def _inverse_blocked(self):
|
||||
for move in self:
|
||||
for line in move.line_ids.filtered(
|
||||
lambda l: l.account_id.account_type in ("liability_payable", "asset_receivable")
|
||||
):
|
||||
line.blocked = move.blocked
|
||||
# def _inverse_blocked(self):
|
||||
# for move in self:
|
||||
# for line in move.line_ids.filtered(
|
||||
# lambda l: l.account_id.account_type in ("liability_payable", "asset_receivable")
|
||||
# ):
|
||||
# line.blocked = move.blocked
|
||||
|
||||
def _compute_has_discount(self):
|
||||
prec = self.env['decimal.precision'].precision_get('Discount')
|
||||
@@ -103,35 +95,6 @@ class AccountMove(models.Model):
|
||||
res = [('id', value and 'in' or 'not in', list(att_inv_ids))]
|
||||
return res
|
||||
|
||||
# when you have an invoice created from a lot of sale orders, the 'name'
|
||||
# field is very large, which makes the name_get() of that invoice very big
|
||||
# which screws-up the form view of that invoice because of the link at the
|
||||
# top of the screen
|
||||
# That's why we have to cut the name_get() when it's too long
|
||||
def name_get(self):
|
||||
old_res = super().name_get()
|
||||
res = []
|
||||
for old_re in old_res:
|
||||
name = old_re[1]
|
||||
if name and len(name) > 100:
|
||||
# nice cut
|
||||
name = '%s ...' % ', '.join(name.split(', ')[:3])
|
||||
# if not enough, hard cut
|
||||
if len(name) > 120:
|
||||
name = '%s ...' % old_re[1][:120]
|
||||
res.append((old_re[0], name))
|
||||
return res
|
||||
|
||||
def _reverse_moves(self, default_values_list=None, cancel=False):
|
||||
reverse_moves = super()._reverse_moves(
|
||||
default_values_list=default_values_list, cancel=cancel)
|
||||
# In the simple scenario 1 invoice -> 1 refund, we add a message in the chatter
|
||||
# of the invoice and in the chatter of the refund
|
||||
if len(self) == 1 and len(reverse_moves) == 1:
|
||||
self.message_post(body=_("A reverse journal entry <a href=# data-oe-model=account.move data-oe-id=%d>%s</a> has been generated.") % (reverse_moves.id, reverse_moves.display_name))
|
||||
reverse_moves.message_post(body=_("This journal entry has been generated as the reverse of <a href=# data-oe-model=account.move data-oe-id=%d>%s</a>.") % (self.id, self.display_name))
|
||||
return reverse_moves
|
||||
|
||||
def delete_lines_qty_zero(self):
|
||||
lines = self.env['account.move.line'].search([
|
||||
('display_type', '=', 'product'),
|
||||
@@ -204,94 +167,27 @@ class AccountMove(models.Model):
|
||||
])
|
||||
move.suitable_journal_ids = self.env['account.journal'].search(domain)
|
||||
|
||||
def button_draft(self):
|
||||
# There is no more attachment by default on invoice reports...
|
||||
# TODO check what's the editor strategy on this
|
||||
# def button_draft(self):
|
||||
# Delete attached pdf invoice
|
||||
for move in self.filtered(lambda x: x.move_type in ('out_invoice', 'out_refund')):
|
||||
for report_xmlid in ('account.account_invoices', 'account.account_invoices_without_payment'):
|
||||
report = self.env.ref(report_xmlid)
|
||||
attach = report.retrieve_attachment(move)
|
||||
if attach:
|
||||
attach.unlink()
|
||||
super().button_draft()
|
||||
# for move in self.filtered(lambda x: x.move_type in ('out_invoice', 'out_refund')):
|
||||
# for report_xmlid in ('account.account_invoices', 'account.account_invoices_without_payment'):
|
||||
# report = self.env.ref(report_xmlid)
|
||||
# attach = report.retrieve_attachment(move)
|
||||
# if attach:
|
||||
# attach.unlink()
|
||||
# super().button_draft()
|
||||
|
||||
def _get_accounting_date(self, invoice_date, has_tax):
|
||||
def _get_accounting_date(self, invoice_date, has_tax, lock_dates=None):
|
||||
# On vendor bills/refunds, we want date = invoice_date unless
|
||||
# we have a company tax_lock_date and the invoice has taxes
|
||||
# and invoice_date <= tax_lock_date
|
||||
date = super()._get_accounting_date(invoice_date, has_tax)
|
||||
if self.is_purchase_document(include_receipts=True):
|
||||
tax_lock_date = self.company_id.tax_lock_date
|
||||
if invoice_date and tax_lock_date and has_tax and invoice_date <= tax_lock_date:
|
||||
invoice_date = tax_lock_date + timedelta(days=1)
|
||||
date = invoice_date
|
||||
date = super()._get_accounting_date(invoice_date, has_tax, lock_dates=lock_dates)
|
||||
lock_dates = lock_dates or self._get_violated_lock_dates(invoice_date, has_tax)
|
||||
if self.is_purchase_document(include_receipts=True) and invoice_date:
|
||||
if lock_dates:
|
||||
date = max([entry[0] for entry in lock_dates]) + timedelta(1)
|
||||
else:
|
||||
date = invoice_date
|
||||
return date
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
_inherit = 'account.move.line'
|
||||
# Native order:
|
||||
# _order = "date desc, move_name desc, id"
|
||||
# Problem: when you manually create a journal entry, the
|
||||
# order of the lines is inverted when you save ! It is quite annoying for
|
||||
# the user...
|
||||
_order = "date desc, id asc"
|
||||
|
||||
# In the 'account' module, we have related stored field for:
|
||||
# name (move_name), date, ref, state (parent_state),
|
||||
# journal_id, company_id, payment_id, statement_line_id,
|
||||
account_reconcile = fields.Boolean(related='account_id.reconcile')
|
||||
full_reconcile_id = fields.Many2one(string='Full Reconcile')
|
||||
matched_debit_ids = fields.One2many(string='Partial Reconcile Debit')
|
||||
matched_credit_ids = fields.One2many(string='Partial Reconcile Credit')
|
||||
# for optional display in tree view
|
||||
product_barcode = fields.Char(related='product_id.barcode', string="Product Barcode")
|
||||
|
||||
def show_account_move_form(self):
|
||||
self.ensure_one()
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
'account.action_move_line_form')
|
||||
action.update({
|
||||
'res_id': self.move_id.id,
|
||||
'view_id': False,
|
||||
'views': False,
|
||||
'view_mode': 'form,tree',
|
||||
})
|
||||
return action
|
||||
|
||||
def update_matching_number(self):
|
||||
records = self.search([("matching_number", "=", "P")])
|
||||
_logger.info(f"Update partial reconcile number for {len(records)} lines")
|
||||
records._compute_matching_number()
|
||||
|
||||
# def _compute_matching_number(self):
|
||||
# TODO maybe it will be better to have the same maching_number for
|
||||
# all partial so it will be easier to group by
|
||||
# super()._compute_matching_number()
|
||||
# for record in self:
|
||||
# if record.matching_number == "P":
|
||||
# record.matching_number = ", ".join([
|
||||
# "a%d" % pr.id
|
||||
# for pr in record.matched_debit_ids + record.matched_credit_ids
|
||||
# ])
|
||||
|
||||
def _compute_name(self):
|
||||
# This is useful when you want to have the product code in a dedicated
|
||||
# column in your customer invoice report
|
||||
# The same ir.config_parameter is used in sale_usability,
|
||||
# purchase_usability and account_usability
|
||||
no_product_code_param = self.env['ir.config_parameter'].sudo().get_param(
|
||||
'usability.line_name_no_product_code')
|
||||
if no_product_code_param and no_product_code_param == 'True':
|
||||
self = self.with_context(display_default_code=False)
|
||||
return super()._compute_name()
|
||||
|
||||
def reconcile(self):
|
||||
"""Explicit error message if unposted lines"""
|
||||
unposted_ids = self.filtered(lambda l: l.move_id.state != "posted")
|
||||
if unposted_ids:
|
||||
m = _("Please post the following entries before reconciliation :")
|
||||
sep = "\n - "
|
||||
unpost = sep.join([am.display_name for am in unposted_ids.move_id])
|
||||
raise UserError(m + sep + unpost)
|
||||
|
||||
return super().reconcile()
|
||||
|
||||
70
account_usability_akretion/models/account_move_line.py
Normal file
70
account_usability_akretion/models/account_move_line.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# Copyright 2015-2024 Akretion France (https://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
_inherit = 'account.move.line'
|
||||
# Native order:
|
||||
# _order = "date desc, move_name desc, id"
|
||||
# Problem: when you manually create a journal entry, the
|
||||
# order of the lines is inverted when you save ! It is quite annoying for
|
||||
# the user...
|
||||
_order = "date desc, id asc"
|
||||
|
||||
# for optional display in list view
|
||||
product_barcode = fields.Char(related='product_id.barcode', string="Product Barcode")
|
||||
|
||||
def show_account_move_form(self):
|
||||
self.ensure_one()
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
'account.action_move_line_form')
|
||||
action.update({
|
||||
'res_id': self.move_id.id,
|
||||
'view_id': False,
|
||||
'views': False,
|
||||
'view_mode': 'form,list',
|
||||
})
|
||||
return action
|
||||
|
||||
# def update_matching_number(self):
|
||||
# records = self.search([("matching_number", "=", "P")])
|
||||
# _logger.info(f"Update partial reconcile number for {len(records)} lines")
|
||||
# records._compute_matching_number()
|
||||
|
||||
# def _compute_matching_number(self):
|
||||
# TODO maybe it will be better to have the same maching_number for
|
||||
# all partial so it will be easier to group by
|
||||
# super()._compute_matching_number()
|
||||
# for record in self:
|
||||
# if record.matching_number == "P":
|
||||
# record.matching_number = ", ".join([
|
||||
# "a%d" % pr.id
|
||||
# for pr in record.matched_debit_ids + record.matched_credit_ids
|
||||
# ])
|
||||
|
||||
def _compute_name(self):
|
||||
# This is useful when you want to have the product code in a dedicated
|
||||
# column in your customer invoice report
|
||||
# The same ir.config_parameter is used in sale_usability,
|
||||
# purchase_usability and account_usability
|
||||
no_product_code_param = self.env['ir.config_parameter'].sudo().get_param(
|
||||
'usability.line_name_no_product_code')
|
||||
if no_product_code_param and no_product_code_param == 'True':
|
||||
self = self.with_context(display_default_code=False)
|
||||
return super()._compute_name()
|
||||
|
||||
# def reconcile(self):
|
||||
# """Explicit error message if unposted lines"""
|
||||
# unposted_ids = self.filtered(lambda l: l.move_id.state != "posted")
|
||||
# if unposted_ids:
|
||||
# m = _("Please post the following entries before reconciliation :")
|
||||
# sep = "\n - "
|
||||
# unpost = sep.join([am.display_name for am in unposted_ids.move_id])
|
||||
# raise UserError(m + sep + unpost)
|
||||
# return super().reconcile()
|
||||
@@ -3,21 +3,21 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
from odoo.tools.misc import formatLang
|
||||
# from odoo.tools.misc import formatLang
|
||||
|
||||
|
||||
class AccountPartialReconcile(models.Model):
|
||||
_inherit = "account.partial.reconcile"
|
||||
_rec_name = "id"
|
||||
# _rec_name = "id"
|
||||
|
||||
def name_get(self):
|
||||
res = []
|
||||
for rec in self:
|
||||
# def name_get(self):
|
||||
# res = []
|
||||
# for rec in self:
|
||||
# There is no seq for partial rec, so I simulate one with the ID
|
||||
# Prefix for full rec: 'A' (upper case)
|
||||
# Prefix for partial rec: 'a' (lower case)
|
||||
amount_fmt = formatLang(
|
||||
self.env, rec.amount, currency_obj=rec.company_currency_id)
|
||||
name = 'a%d (%s)' % (rec.id, amount_fmt)
|
||||
res.append((rec.id, name))
|
||||
return res
|
||||
# amount_fmt = formatLang(
|
||||
# self.env, rec.amount, currency_obj=rec.company_currency_id)
|
||||
# name = 'a%d (%s)' % (rec.id, amount_fmt)
|
||||
# res.append((rec.id, name))
|
||||
# return res
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
# CODE DISABLED FOR THE MOMENT. I need to decide if I want to drop it
|
||||
# because native code is enough and if I want to re-enable it
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
@@ -13,7 +13,7 @@ class ResCompany(models.Model):
|
||||
# But there are several problems with this native field:
|
||||
# - it is copied on the 'narration' field of account.move => we don't want that
|
||||
# - the text block is very small on the form view of res.config.settings
|
||||
# So I decided to have our own field "fixed_invoice_terms"
|
||||
# So I decided to have our own field "static_invoice_terms"
|
||||
# The native field can still be used when you need to customise some
|
||||
# terms and conditions on each invoice (not very common, but...)
|
||||
# To underline this different with the native field, I prefix it with 'static_'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2017-2022 Akretion France (https://akretion.com/)
|
||||
# Copyright 2017-2024 Akretion France (https://akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# Copyright 2015-2022 Akretion France (http://www.akretion.com/)
|
||||
# @author: Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ResPartnerBank(models.Model):
|
||||
_inherit = 'res.partner.bank'
|
||||
|
||||
def name_get(self):
|
||||
res = []
|
||||
for acc in self:
|
||||
name = acc.acc_number
|
||||
if acc.currency_id:
|
||||
name = "%s (%s)" % (name, acc.currency_id.name)
|
||||
if acc.bank_id.name:
|
||||
name = "%s - %s" % (name, acc.bank_id.name)
|
||||
res += [(acc.id, name)]
|
||||
return res
|
||||
|
||||
Reference in New Issue
Block a user