4 Commits

132 changed files with 31836 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
from . import wizard
from . import models
from . import report

View File

@@ -0,0 +1,32 @@
{
'name': 'Odoo 19 Assets Management',
'version': '19.0.1.0.0', # __odoosky_original_version__: '1.0.0'
'author': 'Odoo Mates, Odoo SA',
'depends': ['account'],
'description': """Manage assets owned by a company or a person.
Keeps track of depreciation's, and creates corresponding journal entries""",
'summary': 'Odoo 19 Assets Management',
'category': 'Accounting',
'sequence': 10,
'website': 'https://www.odoomates.tech',
'license': 'LGPL-3',
'images': ['static/description/assets.gif'],
'data': [
'data/account_asset_data.xml',
'security/account_asset_security.xml',
'security/ir.model.access.csv',
'wizard/asset_depreciation_confirmation_wizard_views.xml',
'wizard/asset_modify_views.xml',
'views/account_asset_views.xml',
'views/account_move_views.xml',
'views/account_asset_templates.xml',
'views/asset_category_views.xml',
'views/product_views.xml',
'report/account_asset_report_views.xml',
],
'assets': {
'web.assets_backend': [
'om_account_asset/static/src/scss/account_asset.scss',
],
},
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding='UTF-8'?>
<odoo>
<data noupdate="1">
<record id="account_asset_cron" model="ir.cron">
<field name="name">Account Asset: Generate asset entries</field>
<field name="model_id" ref="model_account_asset_asset"/>
<field name="state">code</field>
<field name="code">model._cron_generate_entries()</field>
<field name="interval_number">1</field>
<field name="interval_type">months</field>
</record>
</data>
</odoo>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import account
from . import account_asset
from . import account_move
from . import product

View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class AccountMove(models.Model):
_inherit = 'account.move'
asset_depreciation_ids = fields.One2many('account.asset.depreciation.line', 'move_id',
string='Assets Depreciation Lines')
def button_cancel(self):
for move in self:
for line in move.asset_depreciation_ids:
line.move_posted_check = False
return super(AccountMove, self).button_cancel()
def action_post(self):
for move in self:
for depreciation_line in move.asset_depreciation_ids:
depreciation_line.post_lines_and_close_asset()
return super(AccountMove, self).action_post()

View File

@@ -0,0 +1,728 @@
import calendar
from datetime import date, datetime
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import UserError, ValidationError
from odoo.tools import float_compare, float_is_zero
from markupsafe import Markup
class AccountAssetCategory(models.Model):
_name = 'account.asset.category'
_description = 'Asset category'
_inherit = ['mail.thread', 'mail.activity.mixin', 'analytic.mixin']
exclude_types = ['asset_receivable', 'asset_cash', 'liability_payable',
'liability_credit_card', 'equity', 'equity_unaffected']
active = fields.Boolean(default=True)
name = fields.Char(required=True, index=True, string="Asset Type")
account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
account_asset_id = fields.Many2one(
'account.account', string='Asset Account',
required=True,
domain=[('account_type', 'not in', exclude_types)],
help="Account used to record the purchase of the asset at its original price."
)
account_depreciation_id = fields.Many2one(
'account.account', string='Depreciation Entries: Asset Account',
required=True,
domain=[('account_type', 'not in', exclude_types)],
help="Account used in the depreciation entries, to decrease the asset value."
)
account_depreciation_expense_id = fields.Many2one(
'account.account', string='Depreciation Entries: Expense Account',
required=True,
domain=[('account_type', 'not in', exclude_types)],
help="Account used in the periodical entries "
"to record a part of the asset as expense."
)
journal_id = fields.Many2one(
'account.journal', string='Journal', required=True
)
company_id = fields.Many2one(
'res.company', string='Company',
required=True, default=lambda self: self.env.company
)
method = fields.Selection(
[('linear', 'Linear'), ('degressive', 'Degressive')],
string='Computation Method', required=True, default='linear',
help="Choose the method to use to compute the amount of depreciation lines.\n"
" * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n"
" * Degressive: Calculated on basis of: Residual Value * Degressive Factor"
)
method_number = fields.Integer(
string='Number of Depreciations', default=5,
help="The number of depreciations needed to depreciate your asset"
)
method_period = fields.Integer(
string='Period Length', default=1,
help="State here the time between 2 depreciations, in months", required=True
)
method_progress_factor = fields.Float(
'Degressive Factor', default=0.3
)
method_time = fields.Selection(
[('number', 'Number of Entries'), ('end', 'Ending Date')],
string='Time Method', required=True, default='number',
help="Choose the method to use to compute the dates and number of entries.\n"
" * Number of Entries: Fix the number of entries and the time between 2 depreciations.\n"
" * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."
)
method_end = fields.Date('Ending date')
prorata = fields.Boolean(
string='Prorata Temporis',
help='Indicates that the first depreciation entry for this asset have to be done from the '
'purchase date instead of the first of January'
)
open_asset = fields.Boolean(
string='Auto-Confirm Assets',
help="Check this if you want to automatically confirm the assets "
"of this category when created by invoices."
)
group_entries = fields.Boolean(
string='Group Journal Entries',
help="Check this if you want to group the generated entries by categories."
)
type = fields.Selection(
[('sale', 'Sale: Revenue Recognition'), ('purchase', 'Purchase: Asset')],
required=True, index=True, default='purchase'
)
date_first_depreciation = fields.Selection([
('last_day_period', 'Based on Last Day of Purchase Period'),
('manual', 'Manual (Defaulted on Purchase Date)')],
string='Depreciation Dates', default='manual', required=True,
help='The way to compute the date of the first depreciation.\n'
' * Based on last day of purchase period: The depreciation dates will'
' be based on the last day of the purchase month or the purchase'
' year (depending on the periodicity of the depreciations).\n'
' * Based on purchase date: The depreciation dates will be based on the purchase date.')
@api.onchange('account_asset_id')
def onchange_account_asset(self):
if self.type == "purchase":
self.account_depreciation_id = self.account_asset_id
elif self.type == "sale":
self.account_depreciation_expense_id = self.account_asset_id
@api.onchange('type')
def onchange_type(self):
if self.type == 'sale':
self.prorata = True
self.method_period = 1
else:
self.method_period = 12
@api.onchange('method_time')
def _onchange_method_time(self):
if self.method_time != 'number':
self.prorata = False
class AccountAssetAsset(models.Model):
_name = 'account.asset.asset'
_description = 'Asset/Revenue Recognition'
_inherit = ['mail.thread', 'mail.activity.mixin', 'analytic.mixin']
entry_count = fields.Integer(compute='_entry_count', string='# Asset Entries')
name = fields.Char(string='Asset Name', required=True)
code = fields.Char(string='Reference', size=32)
value = fields.Monetary(string='Gross Value', required=True)
currency_id = fields.Many2one(
'res.currency', string='Currency', required=True,
default=lambda self: self.env.user.company_id.currency_id.id
)
company_id = fields.Many2one(
'res.company', string='Company', required=True,
default=lambda self: self.env.company)
note = fields.Text()
category_id = fields.Many2one(
'account.asset.category', string='Category',
required=True, change_default=True
)
date = fields.Date(string='Date', required=True, default=fields.Date.context_today)
state = fields.Selection([('draft', 'Draft'), ('open', 'Running'), ('close', 'Close')],
'Status', required=True, copy=False, default='draft',
help="When an asset is created, the status is 'Draft'.\n"
"If the asset is confirmed, the status goes in 'Running' and the depreciation "
"lines can be posted in the accounting.\n"
"You can manually close an asset when the depreciation is over. If the last line"
" of depreciation is posted, the asset automatically goes in that status.")
active = fields.Boolean(default=True)
partner_id = fields.Many2one('res.partner', string='Partner')
method = fields.Selection(
[('linear', 'Linear'), ('degressive', 'Degressive')],
string='Computation Method', required=True, default='linear',
help="Choose the method to use to compute the amount of depreciation lines.\n * Linear:"
" Calculated on basis of: Gross Value / Number of Depreciations\n"
" * Degressive: Calculated on basis of: Residual Value * Degressive Factor"
)
method_number = fields.Integer(string='Number of Depreciations', default=5,
help="The number of depreciations needed to depreciate your asset")
method_period = fields.Integer(
string='Number of Months in a Period', required=True, default=12,
help="The amount of time between two depreciations, in months"
)
method_end = fields.Date(string='Ending Date')
method_progress_factor = fields.Float(
string='Degressive Factor', default=0.3
)
value_residual = fields.Monetary(compute='_amount_residual', string='Residual Value')
method_time = fields.Selection(
[('number', 'Number of Entries'), ('end', 'Ending Date')],
string='Time Method', required=True, default='number',
help="Choose the method to use to compute the dates and number of entries.\n"
" * Number of Entries: Fix the number of entries and the time between 2 depreciations.\n"
" * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."
)
prorata = fields.Boolean(
string='Prorata Temporis',
help='Indicates that the first depreciation entry for this asset'
' have to be done from the asset date (purchase date) '
'instead of the first January / Start date of fiscal year'
)
depreciation_line_ids = fields.One2many(
'account.asset.depreciation.line', 'asset_id', string='Depreciation Lines'
)
salvage_value = fields.Monetary(
string='Salvage Value',
help="It is the amount you plan to have that you cannot depreciate."
)
invoice_id = fields.Many2one('account.move', string='Invoice', copy=False)
type = fields.Selection(related="category_id.type", string='Type', required=True)
account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
date_first_depreciation = fields.Selection([
('last_day_period', 'Based on Last Day of Purchase Period'),
('manual', 'Manual')],
string='Depreciation Dates', default='manual',
required=True,
help='The way to compute the date of the first depreciation.\n'
' * Based on last day of purchase period: The depreciation'
' dates will be based on the last day of the purchase month or the '
'purchase year (depending on the periodicity of the depreciations).\n'
' * Based on purchase date: The depreciation dates will be based on the purchase date.\n')
first_depreciation_manual_date = fields.Date(
string='First Depreciation Date',
help='Note that this date does not alter the computation of the first '
'journal entry in case of prorata temporis assets. It simply changes its accounting date'
)
def unlink(self):
for asset in self:
if asset.state in ['open', 'close']:
raise UserError(_('You cannot delete a document that is in %s state.') % (asset.state,))
for depreciation_line in asset.depreciation_line_ids:
if depreciation_line.move_id:
raise UserError(_('You cannot delete a document that contains posted entries.'))
return super(AccountAssetAsset, self).unlink()
@api.model
def _cron_generate_entries(self):
self.compute_generated_entries(datetime.today())
@api.model
def compute_generated_entries(self, date, asset_type=None):
# Entries generated : one by grouped category and one by asset from ungrouped category
created_move_ids = []
type_domain = []
if asset_type:
type_domain = [('type', '=', asset_type)]
ungrouped_assets = self.env['account.asset.asset'].search(type_domain + [('state', '=', 'open'), ('category_id.group_entries', '=', False)])
created_move_ids += ungrouped_assets._compute_entries(date, group_entries=False)
for grouped_category in self.env['account.asset.category'].search(type_domain + [('group_entries', '=', True)]):
assets = self.env['account.asset.asset'].search([('state', '=', 'open'), ('category_id', '=', grouped_category.id)])
created_move_ids += assets._compute_entries(date, group_entries=True)
return created_move_ids
def _compute_board_amount(self, sequence, residual_amount, amount_to_depr,
undone_dotation_number, posted_depreciation_line_ids,
total_days, depreciation_date):
amount = 0
if sequence == undone_dotation_number:
amount = residual_amount
else:
if self.method == 'linear':
amount = amount_to_depr / (undone_dotation_number - len(posted_depreciation_line_ids))
if self.prorata:
amount = amount_to_depr / self.method_number
if sequence == 1:
date = self.date
if self.method_period % 12 != 0:
month_days = calendar.monthrange(date.year, date.month)[1]
days = month_days - date.day + 1
amount = (amount_to_depr / self.method_number) / month_days * days
else:
days = (self.company_id.compute_fiscalyear_dates(date)['date_to'] - date).days + 1
amount = (amount_to_depr / self.method_number) / total_days * days
elif self.method == 'degressive':
amount = residual_amount * self.method_progress_factor
if self.prorata:
if sequence == 1:
date = self.date
if self.method_period % 12 != 0:
month_days = calendar.monthrange(date.year, date.month)[1]
days = month_days - date.day + 1
amount = (residual_amount * self.method_progress_factor) / month_days * days
else:
days = (self.company_id.compute_fiscalyear_dates(date)['date_to'] - date).days + 1
amount = (residual_amount * self.method_progress_factor) / total_days * days
return amount
def _compute_board_undone_dotation_nb(self, depreciation_date, total_days):
undone_dotation_number = self.method_number
if self.method_time == 'end':
end_date = self.method_end
undone_dotation_number = 0
while depreciation_date <= end_date:
depreciation_date = date(depreciation_date.year, depreciation_date.month,
depreciation_date.day) + relativedelta(months=+self.method_period)
undone_dotation_number += 1
if self.prorata:
undone_dotation_number += 1
return undone_dotation_number
def compute_depreciation_board(self):
self.ensure_one()
posted_depreciation_line_ids = self.depreciation_line_ids.filtered(lambda x: x.move_check).sorted(key=lambda l: l.depreciation_date)
unposted_depreciation_line_ids = self.depreciation_line_ids.filtered(lambda x: not x.move_check)
# Remove old unposted depreciation lines. We cannot use unlink() with One2many field
commands = [(2, line_id.id, False) for line_id in unposted_depreciation_line_ids]
if self.value_residual != 0.0:
amount_to_depr = residual_amount = self.value_residual
# if we already have some previous validated entries, starting date is last entry + method period
if posted_depreciation_line_ids and posted_depreciation_line_ids[-1].depreciation_date:
last_depreciation_date = fields.Date.from_string(posted_depreciation_line_ids[-1].depreciation_date)
depreciation_date = last_depreciation_date + relativedelta(months=+self.method_period)
else:
# depreciation_date computed from the purchase date
depreciation_date = self.date
if self.date_first_depreciation == 'last_day_period':
# depreciation_date = the last day of the month
depreciation_date = depreciation_date + relativedelta(day=31)
# ... or fiscalyear depending the number of period
if self.method_period == 12:
depreciation_date = depreciation_date + relativedelta(month=int(self.company_id.fiscalyear_last_month))
depreciation_date = depreciation_date + relativedelta(day=int(self.company_id.fiscalyear_last_day))
if depreciation_date < self.date:
depreciation_date = depreciation_date + relativedelta(years=1)
elif self.first_depreciation_manual_date and self.first_depreciation_manual_date != self.date:
# depreciation_date set manually from the 'first_depreciation_manual_date' field
depreciation_date = self.first_depreciation_manual_date
total_days = (depreciation_date.year % 4) and 365 or 366
month_day = depreciation_date.day
undone_dotation_number = self._compute_board_undone_dotation_nb(depreciation_date, total_days)
for x in range(len(posted_depreciation_line_ids), undone_dotation_number):
sequence = x + 1
amount = self._compute_board_amount(sequence, residual_amount, amount_to_depr,
undone_dotation_number, posted_depreciation_line_ids,
total_days, depreciation_date)
amount = self.currency_id.round(amount)
if float_is_zero(amount, precision_rounding=self.currency_id.rounding):
continue
residual_amount -= amount
vals = {
'amount': amount,
'asset_id': self.id,
'sequence': sequence,
'name': (self.code or '') + '/' + str(sequence),
'remaining_value': residual_amount,
'depreciated_value': self.value - (self.salvage_value + residual_amount),
'depreciation_date': depreciation_date,
}
commands.append((0, False, vals))
depreciation_date = depreciation_date + relativedelta(months=+self.method_period)
if month_day > 28 and self.date_first_depreciation == 'manual':
max_day_in_month = calendar.monthrange(depreciation_date.year, depreciation_date.month)[1]
depreciation_date = depreciation_date.replace(day=min(max_day_in_month, month_day))
# datetime doesn't take into account that the number of days is not the same for each month
if not self.prorata and self.method_period % 12 != 0 and self.date_first_depreciation == 'last_day_period':
max_day_in_month = calendar.monthrange(depreciation_date.year, depreciation_date.month)[1]
depreciation_date = depreciation_date.replace(day=max_day_in_month)
self.write({'depreciation_line_ids': commands})
return True
def validate(self):
self.write({'state': 'open'})
fields = [
'method',
'method_number',
'method_period',
'method_end',
'method_progress_factor',
'method_time',
'salvage_value',
'invoice_id',
]
ref_tracked_fields = self.env['account.asset.asset'].fields_get(fields)
for asset in self:
tracked_fields = ref_tracked_fields.copy()
if asset.method == 'linear':
del(tracked_fields['method_progress_factor'])
if asset.method_time != 'end':
del(tracked_fields['method_end'])
else:
del(tracked_fields['method_number'])
dummy, tracking_value_ids = asset._mail_track(tracked_fields, dict.fromkeys(fields))
asset.message_post(subject=_('Asset created'), tracking_value_ids=tracking_value_ids)
def _return_disposal_view(self, move_ids):
name = _('Disposal Move')
view_mode = 'form'
if len(move_ids) > 1:
name = _('Disposal Moves')
view_mode = 'tree,form'
return {
'name': name,
'view_type': 'form',
'view_mode': view_mode,
'res_model': 'account.move',
'type': 'ir.actions.act_window',
'target': 'current',
'res_id': move_ids[0],
}
def _get_disposal_moves(self):
move_ids = []
for asset in self:
unposted_depreciation_line_ids = asset.depreciation_line_ids.filtered(lambda x: not x.move_check)
if unposted_depreciation_line_ids:
old_values = {
'method_end': asset.method_end,
'method_number': asset.method_number,
}
# Remove all unposted depr. lines
commands = [(2, line_id.id, False) for line_id in unposted_depreciation_line_ids]
# Create a new depr. line with the residual amount and post it
sequence = len(asset.depreciation_line_ids) - len(unposted_depreciation_line_ids) + 1
today = fields.Datetime.today()
vals = {
'amount': asset.value_residual,
'asset_id': asset.id,
'sequence': sequence,
'name': (asset.code or '') + '/' + str(sequence),
'remaining_value': 0,
'depreciated_value': asset.value - asset.salvage_value, # the asset is completely depreciated
'depreciation_date': today,
}
commands.append((0, False, vals))
asset.write({'depreciation_line_ids': commands, 'method_end': today, 'method_number': sequence})
tracked_fields = self.env['account.asset.asset'].fields_get(['method_number', 'method_end'])
changes, tracking_value_ids = asset._mail_track(tracked_fields, old_values)
if changes:
asset.message_post(subject=_('Asset sold or disposed. Accounting entry awaiting for validation.'), tracking_value_ids=tracking_value_ids)
move_ids += asset.depreciation_line_ids[-1].create_move(post_move=False)
return move_ids
def set_to_close(self):
move_ids = self._get_disposal_moves()
if move_ids:
return self._return_disposal_view(move_ids)
# Fallback, as if we just clicked on the smartbutton
return self.open_entries()
def set_to_draft(self):
self.write({'state': 'draft'})
@api.depends('value', 'salvage_value', 'depreciation_line_ids.move_check', 'depreciation_line_ids.amount')
def _amount_residual(self):
for rec in self:
total_amount = 0.0
for line in rec.depreciation_line_ids:
if line.move_check:
total_amount += line.amount
rec.value_residual = rec.value - total_amount - rec.salvage_value
@api.onchange('company_id')
def onchange_company_id(self):
self.currency_id = self.company_id.currency_id.id
@api.onchange('date_first_depreciation')
def onchange_date_first_depreciation(self):
for record in self:
if record.date_first_depreciation == 'manual':
record.first_depreciation_manual_date = record.date
@api.depends('depreciation_line_ids.move_id')
def _entry_count(self):
for asset in self:
res = self.env['account.asset.depreciation.line'].search_count([('asset_id', '=', asset.id), ('move_id', '!=', False)])
asset.entry_count = res or 0
@api.constrains('prorata', 'method_time')
def _check_prorata(self):
if self.prorata and self.method_time != 'number':
raise ValidationError(_('Prorata temporis can be applied only for the "number of depreciations" time method.'))
@api.onchange('category_id')
def onchange_category_id(self):
vals = self.onchange_category_id_values(self.category_id.id)
# We cannot use 'write' on an object that doesn't exist yet
if vals:
for k, v in vals['value'].items():
setattr(self, k, v)
def onchange_category_id_values(self, category_id):
if category_id:
category = self.env['account.asset.category'].browse(category_id)
return {
'value': {
'method': category.method,
'method_number': category.method_number,
'method_time': category.method_time,
'method_period': category.method_period,
'method_progress_factor': category.method_progress_factor,
'method_end': category.method_end,
'prorata': category.prorata,
'date_first_depreciation': category.date_first_depreciation,
'account_analytic_id': category.account_analytic_id.id,
'analytic_distribution': category.analytic_distribution,
}
}
@api.onchange('method_time')
def onchange_method_time(self):
if self.method_time != 'number':
self.prorata = False
def copy_data(self, default=None):
if default is None:
default = {}
default['name'] = self.name + _(' (copy)')
return super(AccountAssetAsset, self).copy_data(default)
def _compute_entries(self, date, group_entries=False):
depreciation_ids = self.env['account.asset.depreciation.line'].search([
('asset_id', 'in', self.ids), ('depreciation_date', '<=', date),
('move_check', '=', False)])
if group_entries:
return depreciation_ids.create_grouped_move()
return depreciation_ids.create_move()
@api.model_create_multi
def create(self, vals_list):
assets = super(AccountAssetAsset, self.with_context(mail_create_nolog=True)).create(vals_list)
for asset in assets:
asset.sudo().compute_depreciation_board()
return assets
def write(self, vals):
res = super(AccountAssetAsset, self).write(vals)
if 'depreciation_line_ids' not in vals and 'state' not in vals:
for rec in self:
rec.compute_depreciation_board()
return res
def open_entries(self):
move_ids = []
for asset in self:
for depreciation_line in asset.depreciation_line_ids:
if depreciation_line.move_id:
move_ids.append(depreciation_line.move_id.id)
return {
'name': _('Journal Entries'),
'view_type': 'form',
'view_mode': 'list,form',
'res_model': 'account.move',
'view_id': False,
'type': 'ir.actions.act_window',
'domain': [('id', 'in', move_ids)],
}
class AccountAssetDepreciationLine(models.Model):
_name = 'account.asset.depreciation.line'
_description = 'Asset depreciation line'
name = fields.Char(string='Depreciation Name', required=True, index=True)
sequence = fields.Integer(required=True)
asset_id = fields.Many2one('account.asset.asset', string='Asset',
required=True, ondelete='cascade')
parent_state = fields.Selection(related='asset_id.state',
string='State of Asset')
amount = fields.Monetary(string='Current Depreciation',
required=True)
remaining_value = fields.Monetary(string='Next Period Depreciation',
required=True)
depreciated_value = fields.Monetary(string='Cumulative Depreciation',
required=True)
depreciation_date = fields.Date('Depreciation Date', index=True)
move_id = fields.Many2one('account.move', string='Depreciation Entry')
move_check = fields.Boolean(compute='_get_move_check', string='Linked',
store=True)
move_posted_check = fields.Boolean(compute='_get_move_posted_check',
string='Posted', store=True)
currency_id = fields.Many2one('res.currency', string='Currency',
related='asset_id.currency_id',
readonly=True)
@api.depends('move_id')
def _get_move_check(self):
for line in self:
line.move_check = bool(line.move_id)
@api.depends('move_id.state')
def _get_move_posted_check(self):
for line in self:
line.move_posted_check = True if line.move_id and line.move_id.state == 'posted' else False
def create_move(self, post_move=True):
created_moves = self.env['account.move']
for line in self:
if line.move_id:
raise UserError(_('This depreciation is already linked to a journal entry. Please post or delete it.'))
move_vals = self._prepare_move(line)
move = self.env['account.move'].create(move_vals)
line.write({'move_id': move.id, 'move_check': True})
created_moves |= move
if post_move and created_moves:
created_moves.filtered(lambda m: any(m.asset_depreciation_ids.mapped('asset_id.category_id.open_asset'))).action_post()
return [x.id for x in created_moves]
def _prepare_move(self, line):
category_id = line.asset_id.category_id
analytic_distribution = line.asset_id.analytic_distribution
depreciation_date = self.env.context.get('depreciation_date') or line.depreciation_date or fields.Date.context_today(self)
company_currency = line.asset_id.company_id.currency_id
current_currency = line.asset_id.currency_id
prec = company_currency.decimal_places
amount = current_currency._convert(
line.amount, company_currency, line.asset_id.company_id, depreciation_date)
asset_name = line.asset_id.name + ' (%s/%s)' % (line.sequence, len(line.asset_id.depreciation_line_ids))
move_line_1 = {
'name': asset_name,
'account_id': category_id.account_depreciation_id.id,
'debit': 0.0 if float_compare(amount, 0.0, precision_digits=prec) > 0 else -amount,
'credit': amount if float_compare(amount, 0.0, precision_digits=prec) > 0 else 0.0,
'partner_id': line.asset_id.partner_id.id,
'analytic_distribution': analytic_distribution,
'currency_id': company_currency != current_currency and current_currency.id or company_currency.id,
'amount_currency': - 1.0 * line.amount
}
move_line_2 = {
'name': asset_name,
'account_id': category_id.account_depreciation_expense_id.id,
'credit': 0.0 if float_compare(amount, 0.0, precision_digits=prec) > 0 else -amount,
'debit': amount if float_compare(amount, 0.0, precision_digits=prec) > 0 else 0.0,
'partner_id': line.asset_id.partner_id.id,
'analytic_distribution': analytic_distribution,
'currency_id': company_currency != current_currency and current_currency.id or company_currency.id,
'amount_currency': line.amount,
}
move_vals = {
'ref': line.asset_id.code,
'date': depreciation_date or False,
'journal_id': category_id.journal_id.id,
'line_ids': [(0, 0, move_line_1), (0, 0, move_line_2)],
}
return move_vals
def _prepare_move_grouped(self):
asset_id = self[0].asset_id
category_id = asset_id.category_id # we can suppose that all lines have the same category
account_analytic_id = asset_id.account_analytic_id
# analytic_tag_ids = asset_id.analytic_tag_ids
analytic_distribution = asset_id.analytic_distribution
depreciation_date = self.env.context.get('depreciation_date') or fields.Date.context_today(self)
amount = 0.0
for line in self:
# Sum amount of all depreciation lines
company_currency = line.asset_id.company_id.currency_id
current_currency = line.asset_id.currency_id
company = line.asset_id.company_id
amount += current_currency._convert(line.amount, company_currency, company, fields.Date.today())
name = category_id.name + _(' (grouped)')
move_line_1 = {
'name': name,
'account_id': category_id.account_depreciation_id.id,
'debit': 0.0,
'credit': amount,
'journal_id': category_id.journal_id.id,
'analytic_distribution': analytic_distribution,
}
move_line_2 = {
'name': name,
'account_id': category_id.account_depreciation_expense_id.id,
'credit': 0.0,
'debit': amount,
'journal_id': category_id.journal_id.id,
'analytic_distribution': analytic_distribution,
}
move_vals = {
'ref': category_id.name,
'date': depreciation_date or False,
'journal_id': category_id.journal_id.id,
'line_ids': [(0, 0, move_line_1), (0, 0, move_line_2)],
}
return move_vals
def create_grouped_move(self, post_move=True):
if not self.exists():
return []
created_moves = self.env['account.move']
move = self.env['account.move'].create(self._prepare_move_grouped())
self.write({'move_id': move.id, 'move_check': True})
created_moves |= move
if post_move and created_moves:
created_moves.action_post()
return [x.id for x in created_moves]
def post_lines_and_close_asset(self):
# we re-evaluate the assets to determine whether we can close them
for line in self:
line.log_message_when_posted()
asset = line.asset_id
if asset.currency_id.is_zero(asset.value_residual):
asset.message_post(body=_("Document closed."))
asset.write({'state': 'close'})
def log_message_when_posted(self):
def _format_message(message_description, tracked_values):
message = ''
if message_description:
message = '<span>%s</span>' % message_description
for name, values in tracked_values.items():
message += '<div> &nbsp; &nbsp; &bull; <b>%s</b>: ' % name
message += '%s</div>' % values
return Markup(message)
for line in self:
if line.move_id and line.move_id.state == 'draft':
partner_name = line.asset_id.partner_id.name
currency_name = line.asset_id.currency_id.name
msg_values = {_('Currency'): currency_name, _('Amount'): line.amount}
if partner_name:
msg_values[_('Partner')] = partner_name
msg = _format_message(_('Depreciation line posted.'), msg_values)
line.asset_id.message_post(body=msg)
def unlink(self):
for record in self:
if record.move_check:
if record.asset_id.category_id.type == 'purchase':
msg = _("You cannot delete posted depreciation lines.")
else:
msg = _("You cannot delete posted installment lines.")
raise UserError(msg)
return super(AccountAssetDepreciationLine, self).unlink()

View File

@@ -0,0 +1,160 @@
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import UserError, ValidationError
class AccountMove(models.Model):
_inherit = 'account.move'
asset_ids = fields.One2many(
'account.asset.asset', 'invoice_id', string="Assets"
)
def button_draft(self):
res = super(AccountMove, self).button_draft()
for move in self:
if any(asset_id.state != 'draft' for asset_id in move.asset_ids):
raise ValidationError(_(
'You cannot reset to draft for an entry having a posted asset'))
if move.asset_ids:
move.asset_ids.sudo().write({'active': False})
for asset in move.asset_ids:
asset.sudo().message_post(body=_("Vendor bill cancelled."))
return res
@api.model
def _refund_cleanup_lines(self, lines):
result = super(AccountMove, self)._refund_cleanup_lines(lines)
for i, line in enumerate(lines):
for name, field in line._fields.items():
if name == 'asset_category_id':
result[i][2][name] = False
break
return result
def action_cancel(self):
res = super(AccountMove, self).action_cancel()
assets = self.env['account.asset.asset'].sudo().search(
[('invoice_id', 'in', self.ids)])
if assets:
assets.sudo().write({'active': False})
for asset in assets:
asset.sudo().message_post(body=_("Vendor bill cancelled."))
return res
def action_post(self):
result = super(AccountMove, self).action_post()
for inv in self:
context = dict(self.env.context)
context.pop('default_type', None)
for mv_line in inv.invoice_line_ids:
mv_line.with_context(context).asset_create()
return result
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
asset_category_id = fields.Many2one(
'account.asset.category', string='Asset Category'
)
asset_start_date = fields.Date(
string='Asset Start Date', compute='_get_asset_date',
readonly=True, store=True
)
asset_end_date = fields.Date(
string='Asset End Date', compute='_get_asset_date',
readonly=True, store=True
)
asset_mrr = fields.Float(
string='Monthly Recurring Revenue', compute='_get_asset_date',
readonly=True, store=True
)
@api.model
def default_get(self, fields):
res = super(AccountMoveLine, self).default_get(fields)
if self.env.context.get('create_bill') and not self.asset_category_id:
if self.product_id and self.move_id.move_type == 'out_invoice' and \
self.product_id.product_tmpl_id.deferred_revenue_category_id:
self.asset_category_id = self.product_id.product_tmpl_id.deferred_revenue_category_id.id
elif self.product_id and self.product_id.product_tmpl_id.asset_category_id and \
self.move_id.move_type == 'in_invoice':
self.asset_category_id = self.product_id.product_tmpl_id.asset_category_id.id
self.onchange_asset_category_id()
return res
@api.depends('asset_category_id', 'move_id.invoice_date')
def _get_asset_date(self):
for rec in self:
rec.asset_mrr = 0
rec.asset_start_date = False
rec.asset_end_date = False
cat = rec.asset_category_id
if cat:
if cat.method_number == 0 or cat.method_period == 0:
raise UserError(_('The number of depreciations or the period length of '
'your asset category cannot be 0.'))
months = cat.method_number * cat.method_period
if rec.move_id.move_type in ['out_invoice', 'out_refund']:
price_subtotal = self.currency_id._convert(
self.price_subtotal,
self.company_currency_id,
self.company_id,
self.move_id.invoice_date or fields.Date.context_today(
self))
rec.asset_mrr = price_subtotal / months
if rec.move_id.invoice_date:
start_date = rec.move_id.invoice_date.replace(day=1)
end_date = (start_date + relativedelta(months=months, days=-1))
rec.asset_start_date = start_date
rec.asset_end_date = end_date
def asset_create(self):
if self.asset_category_id:
price_subtotal = self.currency_id._convert(
self.price_subtotal,
self.company_currency_id,
self.company_id,
self.move_id.invoice_date or fields.Date.context_today(
self))
vals = {
'name': self.name,
'code': self.name or False,
'category_id': self.asset_category_id.id,
'value': price_subtotal,
'partner_id': self.move_id.partner_id.id,
'company_id': self.move_id.company_id.id,
'currency_id': self.move_id.company_currency_id.id,
'date': self.move_id.invoice_date or self.move_id.date,
'invoice_id': self.move_id.id,
}
changed_vals = self.env['account.asset.asset'].onchange_category_id_values(vals['category_id'])
vals.update(changed_vals['value'])
asset = self.env['account.asset.asset'].create(vals)
if self.asset_category_id.open_asset:
if asset.date_first_depreciation == 'manual':
asset.first_depreciation_manual_date = asset.date
asset.validate()
return True
@api.onchange('asset_category_id', 'product_uom_id')
def onchange_asset_category_id(self):
if self.move_id.move_type == 'out_invoice' and self.asset_category_id:
self.account_id = self.asset_category_id.account_asset_id.id
elif self.move_id.move_type == 'in_invoice' and self.asset_category_id:
self.account_id = self.asset_category_id.account_asset_id.id
@api.onchange('product_id')
def _inverse_product_id(self):
res = super(AccountMoveLine, self)._inverse_product_id()
for rec in self:
if rec.product_id:
if rec.move_id.move_type == 'out_invoice':
rec.asset_category_id = rec.product_id.product_tmpl_id.deferred_revenue_category_id.id
elif rec.move_id.move_type == 'in_invoice':
rec.asset_category_id = rec.product_id.product_tmpl_id.asset_category_id.id
def get_invoice_line_account(self, type, product, fpos, company):
return product.asset_category_id.account_asset_id or super(AccountMoveLine, self).get_invoice_line_account(type, product, fpos, company)

View File

@@ -0,0 +1,22 @@
from odoo import api, fields, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
asset_category_id = fields.Many2one(
'account.asset.category', string='Asset Type',
company_dependent=True, ondelete="restrict"
)
deferred_revenue_category_id = fields.Many2one(
'account.asset.category', string='Deferred Revenue Type',
company_dependent=True, ondelete="restrict"
)
def _get_asset_accounts(self):
res = super(ProductTemplate, self)._get_asset_accounts()
if self.asset_category_id:
res['stock_input'] = self.property_account_expense_id
if self.deferred_revenue_category_id:
res['stock_output'] = self.property_account_income_id
return res

View File

@@ -0,0 +1 @@
from . import account_asset_report

View File

@@ -0,0 +1,65 @@
from odoo import api, fields, models, tools
class AssetAssetReport(models.Model):
_name = "asset.asset.report"
_description = "Assets Analysis"
_auto = False
name = fields.Char(string='Year', required=False, readonly=True)
date = fields.Date(readonly=True)
depreciation_date = fields.Date(string='Depreciation Date', readonly=True)
asset_id = fields.Many2one('account.asset.asset', string='Asset', readonly=True)
asset_category_id = fields.Many2one('account.asset.category', string='Asset category', readonly=True)
partner_id = fields.Many2one('res.partner', string='Partner', readonly=True)
state = fields.Selection([('draft', 'Draft'), ('open', 'Running'), ('close', 'Close')], string='Status', readonly=True)
depreciation_value = fields.Float(string='Amount of Depreciation Lines', readonly=True)
installment_value = fields.Float(string='Amount of Installment Lines', readonly=True)
move_check = fields.Boolean(string='Posted', readonly=True)
installment_nbr = fields.Integer(string='Installment Count', readonly=True)
depreciation_nbr = fields.Integer(string='Depreciation Count', readonly=True)
gross_value = fields.Float(string='Gross Amount', readonly=True)
posted_value = fields.Float(string='Posted Amount', readonly=True)
unposted_value = fields.Float(string='Unposted Amount', readonly=True)
company_id = fields.Many2one('res.company', string='Company', readonly=True)
def init(self):
tools.drop_view_if_exists(self.env.cr, 'asset_asset_report')
self.env.cr.execute("""
create or replace view asset_asset_report as (
select
min(dl.id) as id,
dl.name as name,
dl.depreciation_date as depreciation_date,
a.date as date,
(CASE WHEN dlmin.id = min(dl.id)
THEN a.value
ELSE 0
END) as gross_value,
dl.amount as depreciation_value,
dl.amount as installment_value,
(CASE WHEN dl.move_check
THEN dl.amount
ELSE 0
END) as posted_value,
(CASE WHEN NOT dl.move_check
THEN dl.amount
ELSE 0
END) as unposted_value,
dl.asset_id as asset_id,
dl.move_check as move_check,
a.category_id as asset_category_id,
a.partner_id as partner_id,
a.state as state,
count(dl.*) as installment_nbr,
count(dl.*) as depreciation_nbr,
a.company_id as company_id
from account_asset_depreciation_line dl
left join account_asset_asset a on (dl.asset_id=a.id)
left join (select min(d.id) as id,ac.id as ac_id from account_asset_depreciation_line as d inner join account_asset_asset as ac ON (ac.id=d.asset_id) group by ac_id) as dlmin on dlmin.ac_id=a.id
where a.active is true
group by
dl.amount,dl.asset_id,dl.depreciation_date,dl.name,
a.date, dl.move_check, a.state, a.category_id, a.partner_id, a.company_id,
a.value, a.id, a.salvage_value, dlmin.id
)""")

View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="action_account_asset_report_pivot" model="ir.ui.view">
<field name="name">asset.asset.report.pivot</field>
<field name="model">asset.asset.report</field>
<field name="arch" type="xml">
<pivot string="Assets Analysis" disable_linking="True">
<field name="asset_category_id" type="row"/>
<field name="gross_value" type="measure"/>
<field name="unposted_value" type="measure"/>
</pivot>
</field>
</record>
<record id="action_account_asset_report_graph" model="ir.ui.view">
<field name="name">asset.asset.report.graph</field>
<field name="model">asset.asset.report</field>
<field name="arch" type="xml">
<graph string="Assets Analysis">
<field name="asset_category_id" type="row"/>
<field name="gross_value" type="measure"/>
<field name="unposted_value" type="measure"/>
</graph>
</field>
</record>
<record id="view_asset_asset_report_search" model="ir.ui.view">
<field name="name">asset.asset.report.search</field>
<field name="model">asset.asset.report</field>
<field name="arch" type="xml">
<search string="Assets Analysis">
<field name="date"/>
<field name="depreciation_date"/>
<filter string="Draft" name="draft" domain="[('state','=','draft')]"
help="Assets in draft state"/>
<filter string="Running" name="running" domain="[('state','=','open')]"
help="Assets in running state"/>
<separator/>
<filter string="Posted" name="posted" domain="[('move_check','=',True)]"
help="Posted depreciation lines" context="{'unposted_value_visible': 0}"/>
<field name="asset_id"/>
<field name="asset_category_id"/>
<group>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
<group>
<filter string="Asset" name="asset" context="{'group_by':'asset_id'}"/>
<filter string="Asset Category" name="asset_category"
context="{'group_by':'asset_category_id'}"/>
<filter string="Company" name="company" context="{'group_by':'company_id'}"
groups="base.group_multi_company"/>
<separator/>
<filter string="Purchase Month" name="purchase_month" help="Date of asset purchase"
context="{'group_by':'date:month'}"/>
<filter string="Depreciation Month" name="deprecation_month" help="Date of depreciation"
context="{'group_by':'depreciation_date:month'}"/>
</group>
</search>
</field>
</record>
<record id="action_asset_asset_report" model="ir.actions.act_window">
<field name="name">Assets Analysis</field>
<field name="res_model">asset.asset.report</field>
<field name="view_mode">graph,pivot</field>
<field name="search_view_id" ref="view_asset_asset_report_search"/>
<field name="domain">[('asset_category_id.type', '=', 'purchase')]</field>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No content
</p><p>
From this report, you can have an overview on all depreciations. The
search bar can also be used to personalize your assets depreciation reporting.
</p>
</field>
</record>
<menuitem id="menu_action_asset_asset_report"
name="Assets"
action="action_asset_asset_report"
parent="account.account_reports_management_menu"
sequence="21"/>
</odoo>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="account_asset_category_multi_company_rule" model="ir.rule">
<field name="name">Account Asset Category multi-company</field>
<field ref="model_account_asset_category" name="model_id"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
</record>
<record id="account_asset_asset_multi_company_rule" model="ir.rule">
<field name="name">Account Asset multi-company</field>
<field ref="model_account_asset_asset" name="model_id"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,14 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_account_asset_category,account.asset.category,model_account_asset_category,account.group_account_user,1,0,0,0
access_asset_depreciation_confirmation_wizard,access_asset_depreciation_confirmation_wizard,model_asset_depreciation_confirmation_wizard,account.group_account_user,1,1,1,0
access_asset_modify,access_asset_modify,model_asset_modify,account.group_account_user,1,1,1,0
access_account_asset_asset,account.asset.asset,model_account_asset_asset,account.group_account_user,1,0,0,0
access_account_asset_category_manager,account.asset.category,model_account_asset_category,account.group_account_manager,1,1,1,1
access_account_asset_asset_manager,account.asset.asset,model_account_asset_asset,account.group_account_manager,1,1,1,1
access_account_asset_depreciation_line,account.asset.depreciation.line,model_account_asset_depreciation_line,account.group_account_user,1,0,0,0
access_account_asset_depreciation_line_manager,account.asset.depreciation.line,model_account_asset_depreciation_line,account.group_account_manager,1,1,1,1
access_asset_asset_report,asset.asset.report,model_asset_asset_report,account.group_account_user,1,0,0,0
access_asset_asset_report_manager,asset.asset.report,model_asset_asset_report,account.group_account_manager,1,1,1,1
access_account_asset_category_invoicing_payment,account.asset.category,model_account_asset_category,account.group_account_invoice,1,0,0,0
access_account_asset_asset_invoicing_payment,account.asset.asset,model_account_asset_asset,account.group_account_invoice,1,0,1,0
access_account_asset_depreciation_line_invoicing_payment,account.asset.depreciation.line,model_account_asset_depreciation_line,account.group_account_invoice,1,0,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_account_asset_category account.asset.category model_account_asset_category account.group_account_user 1 0 0 0
3 access_asset_depreciation_confirmation_wizard access_asset_depreciation_confirmation_wizard model_asset_depreciation_confirmation_wizard account.group_account_user 1 1 1 0
4 access_asset_modify access_asset_modify model_asset_modify account.group_account_user 1 1 1 0
5 access_account_asset_asset account.asset.asset model_account_asset_asset account.group_account_user 1 0 0 0
6 access_account_asset_category_manager account.asset.category model_account_asset_category account.group_account_manager 1 1 1 1
7 access_account_asset_asset_manager account.asset.asset model_account_asset_asset account.group_account_manager 1 1 1 1
8 access_account_asset_depreciation_line account.asset.depreciation.line model_account_asset_depreciation_line account.group_account_user 1 0 0 0
9 access_account_asset_depreciation_line_manager account.asset.depreciation.line model_account_asset_depreciation_line account.group_account_manager 1 1 1 1
10 access_asset_asset_report asset.asset.report model_asset_asset_report account.group_account_user 1 0 0 0
11 access_asset_asset_report_manager asset.asset.report model_asset_asset_report account.group_account_manager 1 1 1 1
12 access_account_asset_category_invoicing_payment account.asset.category model_account_asset_category account.group_account_invoice 1 0 0 0
13 access_account_asset_asset_invoicing_payment account.asset.asset model_account_asset_asset account.group_account_invoice 1 0 1 0
14 access_account_asset_depreciation_line_invoicing_payment account.asset.depreciation.line model_account_asset_depreciation_line account.group_account_invoice 1 0 1 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1023 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="70" height="70" viewBox="0 0 70 70"><defs><path id="a" d="M4 0h61c4 0 5 1 5 5v60c0 4-1 5-5 5H4c-3 0-4-1-4-5V5c0-4 1-5 4-5z"/><linearGradient id="c" x1="100%" x2="0%" y1="0%" y2="100%"><stop offset="0%" stop-color="#DA956B"/><stop offset="100%" stop-color="#CC7039"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><g mask="url(#b)"><path fill="url(#c)" d="M0 0H70V70H0z"/><path fill="#FFF" fill-opacity=".383" d="M4 1h61c2.667 0 4.333.667 5 2V0H0v3c.667-1.333 2-2 4-2z"/><path fill="#393939" d="M4 69c-2 0-4-.146-4-4.09V40.738L18.16 24H52l1 2.045v6.137l-10.585 11.3 10.05 4.09L37.071 69H4z" opacity=".324"/><path fill="#000" fill-opacity=".383" d="M4 69h61c2.667 0 4.333-1 5-3v4H0v-4c.667 2 2 3 4 3z"/><path fill="#000" d="M53 42.084v5.66c0 1.837-1.111 3.34-3.556 3.34h-28c-2.466 0-4.444-1.503-4.444-3.34V28.34c0-1.837 1.978-3.34 4.444-3.34H49c2.444 0 4 1.368 4 3.205v5.88H37c-2.667 0-4 1.857-4 3.957 0 2.1 1.333 4.042 4 4.042h16zm-15-1.39a2.656 2.656 0 0 1-2.667-2.652A2.656 2.656 0 0 1 38 35.39a2.656 2.656 0 0 1 2.667 2.653A2.656 2.656 0 0 1 38 40.695z" opacity=".3"/><path fill="#FFF" d="M53 40.084v5.66c0 1.837-1.111 3.34-3.556 3.34h-28c-2.466 0-4.444-1.503-4.444-3.34V26.34c0-1.837 1.978-3.34 4.444-3.34H49c2.444 0 4 1.368 4 3.205v5.88H37c-2.667 0-4 1.857-4 3.957 0 2.1 1.333 4.042 4 4.042h16zm-15-1.39a2.656 2.656 0 0 1-2.667-2.652A2.656 2.656 0 0 1 38 33.39a2.656 2.656 0 0 1 2.667 2.653A2.656 2.656 0 0 1 38 38.695z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,84 @@
<section class="oe_container oe_dark">
<div class="col-md-12">
<h2 class="oe_slogan" style="font-size: 35px;color:#2C0091"><b>Odoo 19 Asset Management</b></h2>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div style="text-align:center;">
<p class="fa fa-hand-o-right" style="color:CRIMSON;font-size: 25px;">
<span style="color:#2dd280;font-size: 15px;">Manage assets owned by a company or a person.</span>
</p><br/>
<p class="fa fa-hand-o-right" style="color:CRIMSON;font-size: 25px;">
<span style="color:#2dd280;font-size: 15px;">Keeps track of depreciation's, and creates corresponding journal entries</span>
</p><br/>
</div>
<br/>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_centeralign oe_websiteonly">
<h4 class="oe_slogan"><a href="https://www.youtube.com/watch?v=KudvDOTvx2I" target="_blank" style="color: #FFFFFF !important; border-radius: 0; background-color: #9c676e; border-color: #005ca7; padding: 15px; font-weight: bold;">
<i class="fa fa-youtube"></i>
Watch on YouTube
</a></h4>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h3 class="oe_slogan" style="color:#332c3c;font-size: 28px;">Asset Category</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img src="asset_types.png">
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<h3 class="oe_slogan" style="color:#332c3c;font-size: 28px;">Assets</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img src="assets.png">
</div>
</div>
</section>
<hr style="width: 100%;height: 4px;background: #2C0091;margin: 0px 0px;">
<hr style="width: 100%;height: 4px;background: #148963;margin: 0px 0px;">
<section class="oe_container oe_dark">
<div class="oe_row ">
<div class="oe_slogan text-center">
<img src="odoo_mates.png"/>
<div style="color:#269900;">
<h3 style="color:#2C0091;font-size: 25px;">If you need any help or want more features, just contact us:</h3><br>
<h3 style="color:#2C0091;font-size: 20px;">Email: <a href="odoomates@gmail.com">odoomates@gmail.com</a> <br></h3>
</div>
<div class="oe_slogan">
<h2>
<a target="_blank" href="https://www.facebook.com/odoomate/" target="new">
<i class="fa fa-facebook-square" style="font-size:38px;"></i>
</a>
<a target="_blank" href="https://twitter.com/odoomates/" target="new">
<i class="fa fa-twitter" style="font-size:38px;"></i>
</a>
<a href="#" target="_blank">
<i class="fa fa-linkedin" style="font-size:38px;"></i>
</a>
<a target="_blank" href="https://www.youtube.com/channel/UCVKlUZP7HAhdQgs-9iTJklQ">
<i class="fa fa-youtube-play" style="font-size:38px;"></i>
</a>
</h2>
</div>
</div>
</div>
</section>
<hr style="width: 100%;height: 4px;background: #148963;margin: 0px 0px;">
<hr style="width: 100%;height: 4px;background: #2C0091;margin: 0px 0px;">

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -0,0 +1,9 @@
.o_web_client .o_deprec_lines_toggler {
color: theme-color('danger');
&.o_is_posted {
color: theme-color('success');
}
&.o_unposted {
color: theme-color('warning');
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_assets_scss_backend" model="ir.asset">
<field name="name">aAccount Assets SCSS</field>
<field name="bundle">web.assets_backend</field>
<field name="path">/om_account_asset/static/src/scss/account_asset.scss</field>
<field name="sequence" eval="18"/>
</record>
</odoo>

View File

@@ -0,0 +1,238 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_asset_asset_form" model="ir.ui.view">
<field name="name">account.asset.asset.form</field>
<field name="model">account.asset.asset</field>
<field name="arch" type="xml">
<form string="Asset">
<header>
<button name="validate" string="Confirm" type="object" class="oe_highlight" invisible="state != 'draft'"/>
<button type="object" name="compute_depreciation_board" string="Compute Depreciation"
invisible="state != 'draft'"/>
<button name="set_to_close" invisible="state != 'open'" string="Sell or Dispose" type="object"
class="oe_highlight"/>
<button name="set_to_draft" string="Set to Draft" type="object"
invisible="entry_count != 0 or state != 'open'"/>
<button name="%(action_asset_modify)d" invisible="state != 'open'" string="Modify Depreciation" type="action"/>
<field name="state" widget="statusbar" statusbar_visible="draft,open"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="open_entries" type="object" icon="fa-pencil">
<field string="Items" name="entry_count" widget="statinfo"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name" placeholder="e.g. Laptop iBook" readonly="state != 'draft'"/>
</h1>
</div>
<group>
<group>
<field name="category_id" string="Asset Category"
domain="[('type', '=', 'purchase')]"
readonly="state != 'draft'"
context="{'default_type': 'purchase'}" help="Category of asset"/>
<field name="code" readonly="state != 'draft'"/>
<field name="date" help="Date of asset" readonly="state != 'draft'"/>
<field name="date_first_depreciation" readonly="state != 'draft'"/>
<field name="first_depreciation_manual_date"
readonly="state != 'draft'"
invisible="date_first_depreciation != 'manual'"
required="date_first_depreciation == 'manual'"/>
<field name="type" invisible="1"/>
<field name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
</group>
<group>
<field name="currency_id" groups="base.group_multi_currency"
readonly="state != 'draft'"/>
<field name="company_id" options="{'no_create': True}"
readonly="state != 'draft'"
groups="base.group_multi_company"/>
<field name="value" widget="monetary"
readonly="state != 'draft'" help="Gross value of asset"/>
<field name="salvage_value" widget="monetary"
readonly="state != 'draft'"
invisible="type == 'sale'"/>
<field name="value_residual" widget="monetary"/>
<field name="partner_id" string="Vendor" widget="res_partner_many2one"
readonly="state != 'draft'"
context="{'res_partner_search_mode': 'supplier'}"/>
<field name="invoice_id" string="Invoice" options="{'no_create': True}"/>
<field name="analytic_distribution" widget="analytic_distribution"/>
</group>
</group>
<notebook>
<page string="Depreciation Board">
<field name="depreciation_line_ids" mode="list"
readonly="state not in ('draft', 'open')"
options="{'reload_whole_on_button': true}">
<list string="Depreciation Lines" decoration-info="(move_check == False)"
create="false">
<field name="depreciation_date"/>
<field name="amount" widget="monetary" string="Depreciation"/>
<field name="depreciated_value" readonly="1"/>
<field name="remaining_value" readonly="1" widget="monetary" string="Residual"/>
<field name="move_check" widget="deprec_lines_toggler"
invisible="parent_state != 'open'"/>
<field name="move_posted_check" invisible="1"/>
<field name="parent_state" invisible="1"/>
</list>
<form string="Depreciation Lines" create="false">
<group>
<group>
<field name="parent_state" invisible="1"/>
<field name="name"/>
<field name="sequence"/>
<field name="move_id"/>
<field name="move_check"/>
<field name="parent_state" invisible="1"/>
</group>
<group>
<field name="amount" widget="monetary"/>
<field name="depreciation_date"/>
<field name="depreciated_value"/>
<field name="remaining_value"/>
</group>
</group>
</form>
</field>
</page>
<page string="Depreciation Information">
<group>
<field name="method" widget="radio"
invisible="type == 'sale'" readonly="state != 'draft'"/>
<field name="method_progress_factor"
readonly="state != 'draft'"
invisible="method == 'linear'"
required="method == 'degressive'"/>
<field name="method_time" string="Time Method Based On"
widget="radio"
readonly="state != 'draft'"
invisible="type != 'purchase'"/>
<field name="prorata"
invisible="method_time == 'end'"
readonly="state != 'draft'"/>
</group>
<group>
<field name="method_number"
readonly="state != 'draft'"
invisible="method_time == 'end'"
required="method_time == 'number'"/>
<field name="method_period" readonly="state != 'draft'"/>
<field name="method_end"
readonly="state != 'draft'"
invisible="method_time == 'end'"
required="method_time == 'number'"/>
</group>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<record id="view_account_asset_asset_kanban" model="ir.ui.view">
<field name="name">account.asset.asset.kanban</field>
<field name="model">account.asset.asset</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="name"/>
<field name="category_id"/>
<field name="date"/>
<field name="state"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<div class="row mb4">
<div class="col-6">
<strong>
<span>
<t t-esc="record.name.value"/>
</span>
</strong>
</div>
<div class="col-6 text-end">
<strong>
<t t-esc="record.date.value"/>
</strong>
</div>
</div>
<div class="row">
<div class="col-6 text-muted">
<span>
<t t-esc="record.category_id.value"/>
</span>
</div>
<div class="col-6">
<span class="float-right text-end">
<field name="state" widget="kanban_label_selection"
options="{'classes': {'draft': 'primary', 'open': 'success', 'close': 'default'}}"/>
</span>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="view_account_asset_asset_purchase_tree" model="ir.ui.view">
<field name="name">account.asset.asset.purchase.list</field>
<field name="model">account.asset.asset</field>
<field name="arch" type="xml">
<list string="Assets" decoration-info="(state == 'draft')" decoration-muted="(state == 'close')">
<field name="name"/>
<field name="category_id" string="Asset Category"/>
<field name="date"/>
<field name="partner_id" string="Vendor"/>
<field name="value"/>
<field name="value_residual" widget="monetary"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="state"/>
</list>
</field>
</record>
<record id="view_account_asset_search" model="ir.ui.view">
<field name="name">account.asset.asset.search</field>
<field name="model">account.asset.asset</field>
<field name="arch" type="xml">
<search string="Asset Account">
<field name="name" string="Asset"/>
<field name="date"/>
<filter string="Current" name="current" domain="[('state','in', ('draft','open'))]"
help="Assets in draft and open states"/>
<filter string="Closed" name="closed" domain="[('state','=', 'close')]"
help="Assets in closed state"/>
<field name="category_id" string="Asset Category"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<group>
<filter string="Date" name="month" domain="[]" context="{'group_by':'date'}"/>
<filter string="Asset Category" name="category" domain="[]" context="{'group_by':'category_id'}"/>
</group>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_account_asset_asset_form">
<field name="name">Assets</field>
<field name="res_model">account.asset.asset</field>
<field name="view_mode">list,kanban,form</field>
<field name="view_id" ref="view_account_asset_asset_purchase_tree"/>
<field name="domain">[('category_id.type', '=', 'purchase')]</field>
</record>
<menuitem id="menu_action_account_asset_asset_form"
parent="account.account_account_menu"
action="action_account_asset_asset_form"
sequence="101"
groups="account.group_account_manager"/>
</odoo>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_invoice_asset_category" model="ir.ui.view">
<field name="name">account.move.supplier.form</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='invoice_line_ids']/list/field[@name='account_id']" position="before">
<field string="Asset Category" name="asset_category_id"
force_save="1" column_invisible="parent.move_type != 'in_invoice'"
domain="[('type','=','purchase')]" context="{'default_type':'purchase'}"/>
</xpath>
<xpath expr="//field[@name='line_ids']/list/field[@name='account_id']" position="before">
<field string="Asset Category" name="asset_category_id"
column_invisible="1"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_asset_category_form" model="ir.ui.view">
<field name="name">account.asset.category.form</field>
<field name="model">account.asset.category</field>
<field name="arch" type="xml">
<form string="Asset category">
<sheet>
<div class="oe_title">
<label for="name" string="Asset Type" class="oe_edit_only"
invisible="type != 'purchase'"/>
<label for="name" string="Deferred Revenue Type" class="oe_edit_only"
invisible="type == 'purchase'"/>
<h1>
<field name="name" placeholder="e.g. Computers"/>
</h1>
</div>
<group string="Journal Entries">
<group>
<field name="journal_id"/>
<div>
<label for="account_asset_id" invisible="type != 'purchase'"
style="font-weight: bold" class="o_light_label"/>
<label for="account_asset_id" string="Deferred Revenue Account"
invisible="type != 'sale'" style="font-weight: bold"
class="o_light_label"/>
</div>
<field name="account_asset_id" nolabel="1"
domain="[('company_ids', 'in', company_id)]"/>
<div>
<label for="account_depreciation_id" invisible="type != 'purchase'"
style="font-weight: bold" class="o_light_label"/>
<label for="account_depreciation_id" string="Recognition Income Account"
invisible="type != 'sale'"
style="font-weight: bold" class="o_light_label"/>
</div>
<field name="account_depreciation_id" nolabel="1"
domain="[('company_ids', 'in', company_id)]"/>
</group>
<group>
<div>
<label for="account_depreciation_expense_id"
invisible="type != 'purchase'"
style="font-weight: bold" class="o_light_label"/>
<label for="account_depreciation_expense_id" string="Recognition Account"
invisible="type != 'sale'"
style="font-weight: bold" class="o_light_label"/>
</div>
<field name="account_depreciation_expense_id" nolabel="1"
domain="[('company_ids', 'in', company_id)]"/>
<field name="account_analytic_id" domain="[('company_id', 'in', company_id)]"
groups="analytic.group_analytic_accounting"/>
<field name="analytic_distribution" widget="analytic_distribution"/>
</group>
</group>
<group>
<group string="Periodicity">
<field name="method_time" string="Time Method Based On" widget="radio"
invisible="type != 'purchase'"/>
<field name="method_number" string="Number of Entries"
required="method_time == 'number'"
invisible="method_time != 'number' or type == False"/>
<label for="method_period" string="One Entry Every"/>
<div>
<field name="method_period" nolabel="1"
invisible="type == False" class="oe_inline"/>
months
</div>
<field name="method_end"
required="method_time == 'end'"
invisible="method_time != 'end'"/>
</group>
<group>
<field name="type" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="company_id" options="{'no_create': True}"
groups="base.group_multi_company"/>
</group>
<group string="Additional Options">
<field name="open_asset"/>
<field name="group_entries"/>
<field name="date_first_depreciation"/>
</group>
<group invisible="type == 'sale'" string="Depreciation Method">
<field name="method" widget="radio"/>
<field name="method_progress_factor"
invisible="method_time == 'linear'" required="method == 'degressive'"/>
<field name="prorata" invisible="method_time == 'end'"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_account_asset_asset_category_kanban" model="ir.ui.view">
<field name="name">account.asset.category.kanban</field>
<field name="model">account.asset.category</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="name"/>
<field name="journal_id"/>
<field name="method"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_card oe_kanban_global_click">
<div class="row mb4">
<div class="col-6">
<strong>
<span>
<t t-esc="record.name.value"/>
</span>
</strong>
</div>
<div class="col-6 text-end">
<span class="badge badge-pill">
<strong>
<t t-esc="record.method.value"/>
</strong>
</span>
</div>
</div>
<div>
<t t-esc="record.journal_id.value"/>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="view_account_asset_category_tree" model="ir.ui.view">
<field name="name">account.asset.category.list</field>
<field name="model">account.asset.category</field>
<field name="arch" type="xml">
<list string="Asset category">
<field name="name"/>
<field name="journal_id"/>
<field name="method"/>
<field name="company_id" groups="base.group_multi_company"/>
</list>
</field>
</record>
<record id="view_account_asset_category_search" model="ir.ui.view">
<field name="name">account.asset.category.search</field>
<field name="model">account.asset.category</field>
<field name="arch" type="xml">
<search string="Search Asset Category">
<filter string="Sales" name="sales" domain="[('type','=', 'sale')]" help="Deferred Revenues"/>
<filter string="Purchase" name="purchase" domain="[('type','=', 'purchase')]" help="Assets"/>
<field name="name" string="Category"/>
<field name="journal_id"/>
<group>
<filter string="Type" name="type" domain="[]" context="{'group_by':'type'}"/>
</group>
</search>
</field>
</record>
<record id="action_account_asset_asset_list_normal_purchase" model="ir.actions.act_window">
<field name="name">Asset Category</field>
<field name="res_model">account.asset.category</field>
<field name="domain">[('type', '=', 'purchase')]</field>
<field name="view_mode">list,kanban,form</field>
<field name="context">{'default_type': 'purchase'}</field>
</record>
<menuitem id="menu_action_account_asset_asset_list_normal_purchase"
parent="account.account_account_menu"
action="action_account_asset_asset_list_normal_purchase"
sequence="6"/>
</odoo>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_product_template_form_inherit" model="ir.ui.view">
<field name="name">Product Template (form)</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="account.product_template_form_view"/>
<field name="arch" type="xml">
<field name="property_account_expense_id" position="after">
<field name="asset_category_id"
domain="[('type', '=', 'purchase')]"
context="{'default_type': 'purchase'}"
groups="account.group_account_user"/>
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import asset_depreciation_confirmation_wizard
from . import asset_modify

View File

@@ -0,0 +1,29 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
class AssetDepreciationConfirmationWizard(models.TransientModel):
_name = "asset.depreciation.confirmation.wizard"
_description = "asset.depreciation.confirmation.wizard"
date = fields.Date(
'Account Date', required=True,
help="Choose the period for which you want to automatically post the depreciation lines of running assets",
default=fields.Date.context_today
)
def asset_compute(self):
self.ensure_one()
context = self.env.context
created_move_ids = self.env['account.asset.asset'].compute_generated_entries(self.date, asset_type=context.get('asset_type'))
return {
'name': _('Created Asset Moves') if context.get('asset_type') == 'purchase' else _('Created Revenue Moves'),
'view_type': 'form',
'view_mode': 'list,form',
'res_model': 'account.move',
'view_id': False,
'domain': "[('id','in',[" + ','.join(str(id) for id in created_move_ids) + "])]",
'type': 'ir.actions.act_window',
}

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_asset_depreciation_confirmation_wizard" model="ir.ui.view">
<field name="name">asset.depreciation.confirmation.wizard</field>
<field name="model">asset.depreciation.confirmation.wizard</field>
<field name="arch" type="xml">
<form string="Compute Asset">
<div>
<p>
This wizard will post installment/depreciation lines for the selected month.<br/>
This will generate journal entries for all related installment lines on this period
of asset/revenue recognition as well.
</p>
</div>
<group>
<field name="date"/>
</group>
<footer>
<button string="Generate Entries" name="asset_compute" type="object" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_asset_depreciation_confirmation_wizard" model="ir.actions.act_window">
<field name="name">Post Depreciation Lines</field>
<field name="res_model">asset.depreciation.confirmation.wizard</field>
<field name="view_mode">list,form</field>
<field name="view_id" ref="view_asset_depreciation_confirmation_wizard"/>
<field name="target">new</field>
<field name="context">{'asset_type': 'purchase'}</field>
</record>
<menuitem id="menu_finance_entries_generate_entries"
parent="account.menu_finance_entries"
name="Generate Entries"/>
<menuitem id="menu_asset_depreciation_confirmation_wizard"
name="Generate Assets Entries"
action="action_asset_depreciation_confirmation_wizard"
parent="om_account_asset.menu_finance_entries_generate_entries"
sequence="111"
groups="account.group_account_manager"/>
</odoo>

View File

@@ -0,0 +1,67 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class AssetModify(models.TransientModel):
_name = 'asset.modify'
_description = 'Modify Asset'
name = fields.Text(string='Reason', required=True)
method_number = fields.Integer(
string='Number of Depreciation', required=True
)
method_period = fields.Integer(string='Period Length')
method_end = fields.Date(string='Ending date')
asset_method_time = fields.Char(
compute='_get_asset_method_time', string='Asset Method Time', readonly=True
)
def _get_asset_method_time(self):
if self.env.context.get('active_id'):
asset = self.env['account.asset.asset'].browse(self.env.context.get('active_id'))
self.asset_method_time = asset.method_time
@api.model
def default_get(self, fields):
res = super(AssetModify, self).default_get(fields)
asset_id = self.env.context.get('active_id')
asset = self.env['account.asset.asset'].browse(asset_id)
if 'name' in fields:
res.update({'name': asset.name})
if 'method_number' in fields and asset.method_time == 'number':
res.update({'method_number': asset.method_number})
if 'method_period' in fields:
res.update({'method_period': asset.method_period})
if 'method_end' in fields and asset.method_time == 'end':
res.update({'method_end': asset.method_end})
if self.env.context.get('active_id'):
active_asset = self.env['account.asset.asset'].browse(self.env.context.get('active_id'))
res['asset_method_time'] = active_asset.method_time
return res
def modify(self):
""" Modifies the duration of asset for calculating depreciation
and maintains the history of old values, in the chatter.
"""
asset_id = self.env.context.get('active_id', False)
asset = self.env['account.asset.asset'].browse(asset_id)
old_values = {
'method_number': asset.method_number,
'method_period': asset.method_period,
'method_end': asset.method_end,
}
asset_vals = {
'method_number': self.method_number,
'method_period': self.method_period,
'method_end': self.method_end,
}
if asset_vals['method_number'] <= asset.entry_count:
raise UserError(_('The number of depreciations must be greater than the number of posted or draft entries '
'to allow for complete depreciation of the asset.'))
asset.write(asset_vals)
asset.compute_depreciation_board()
tracked_fields = self.env['account.asset.asset'].fields_get(['method_number', 'method_period', 'method_end'])
changes, tracking_value_ids = asset._mail_track(tracked_fields, old_values)
if changes:
asset.message_post(subject=_('Depreciation board modified'), body=self.name, tracking_value_ids=tracking_value_ids)
return {'type': 'ir.actions.act_window_close'}

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="asset_modify_form" model="ir.ui.view">
<field name="name">wizard.asset.modify.form</field>
<field name="model">asset.modify</field>
<field name="arch" type="xml">
<form string="Modify Asset">
<field name="asset_method_time" invisible="1"/>
<group string="Asset Durations to Modify" col="4">
<group colspan="2" col="2">
<field name="name"/>
<field name="method_number" invisible="asset_method_time == 'end'"/>
</group>
<group colspan="2" col="2">
<field name="method_end" invisible="asset_method_time == 'number'"/>
<label for="method_period"/>
<div>
<field name="method_period" class="oe_inline"/> months
</div>
</group>
</group>
<footer>
<button name="modify" string="Modify" type="object" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_asset_modify" model="ir.actions.act_window">
<field name="name">Modify Asset</field>
<field name="res_model">asset.modify</field>
<field name="type">ir.actions.act_window</field>
<field name="view_mode">list,form</field>
<field name="view_id" ref="asset_modify_form"/>
<field name="target">new</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,21 @@
{
'name': 'Odoo 19 Budget Management',
'author': 'Odoo Mates, Odoo SA',
'category': 'Accounting',
'version': '19.0.1.0.1', # __odoosky_original_version__: '1.0.1'
'description': """Use budgets to compare actual with expected revenues and costs""",
'summary': 'Odoo 19 Budget Management',
'sequence': 10,
'website': 'https://www.odoomates.tech',
'depends': ['account'],
'license': 'LGPL-3',
'data': [
'security/ir.model.access.csv',
'security/security.xml',
'views/account_analytic_account_views.xml',
'views/account_budget_views.xml',
'views/res_config_settings_views.xml',
],
'images': ['static/description/banner.gif'],
'demo': ['data/account_budget_demo.xml'],
}

View File

@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="crossovered_budget_budgetoptimistic0" model="crossovered.budget">
<field eval="'Budget '+str(datetime.now().year+1)+': Optimistic'" name="name"/>
<field eval="str(datetime.now().year+1)+'-01-01'" name="date_from"/>
<field eval="&quot;&quot;&quot;draft&quot;&quot;&quot;" name="state"/>
<field eval="str(datetime.now().year+1)+'-12-31'" name="date_to"/>
<field name="user_id" ref="base.user_root"/>
</record>
<record id="budget_line_analytic_admin" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-01-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-12-31'" name="date_to"/>
<field name="planned_amount">-35000</field>
<field name="analytic_account_id" ref="analytic.analytic_administratif"/>
</record>
<record id="budget_line_analytic_agrolait1" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-01-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-01-31'" name="date_to"/>
<field name="planned_amount">10000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait2" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-02-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-02-28'" name="date_to"/>
<field name="planned_amount">10000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait3" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-03-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-03-31'" name="date_to"/>
<field name="planned_amount">12000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait4" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-04-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-04-30'" name="date_to"/>
<field name="planned_amount">15000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait5" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-05-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-05-31'" name="date_to"/>
<field name="planned_amount">15000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait6" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-06-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-06-30'" name="date_to"/>
<field name="planned_amount">15000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait7" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-07-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-07-31'" name="date_to"/>
<field name="planned_amount">13000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait8" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-08-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-08-31'" name="date_to"/>
<field name="planned_amount">9000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait9" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-09-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-09-30'" name="date_to"/>
<field name="planned_amount">8000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait10" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-10-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-10-31'" name="date_to"/>
<field name="planned_amount">15000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait11" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-11-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-11-30'" name="date_to"/>
<field name="planned_amount">15000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait12" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetoptimistic0"/>
<field eval="str(datetime.now().year+1)+'-12-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-12-31'" name="date_to"/>
<field name="planned_amount">18000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<!-- pessimistic-->
<record id="crossovered_budget_budgetpessimistic0" model="crossovered.budget">
<field eval="'Budget '+str(datetime.now().year+1)+': Pessimistic'" name="name"/>
<field eval="str(datetime.now().year+1)+'-01-01'" name="date_from"/>
<field eval="&quot;&quot;&quot;draft&quot;&quot;&quot;" name="state"/>
<field eval="str(datetime.now().year+1)+'-12-31'" name="date_to"/>
<field name="user_id" ref="base.user_root"/>
</record>
<record id="budget_line_analytic_admin_pessim" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-01-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-12-31'" name="date_to"/>
<field name="planned_amount">-55000</field>
<field name="analytic_account_id" ref="analytic.analytic_administratif"/>
</record>
<record id="budget_line_analytic_agrolait_pessim1" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-01-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-01-31'" name="date_to"/>
<field name="planned_amount">9000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim2" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-02-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-02-28'" name="date_to"/>
<field name="planned_amount">8000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim3" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-03-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-03-31'" name="date_to"/>
<field name="planned_amount">10000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim4" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-04-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-04-30'" name="date_to"/>
<field name="planned_amount">14000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim5" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-05-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-05-31'" name="date_to"/>
<field name="planned_amount">16000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim6" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-06-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-06-30'" name="date_to"/>
<field name="planned_amount">13000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim7" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-07-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-07-31'" name="date_to"/>
<field name="planned_amount">10000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim8" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-08-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-08-31'" name="date_to"/>
<field name="planned_amount">8000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim9" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-09-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-09-30'" name="date_to"/>
<field name="planned_amount">7000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim10" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-10-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-10-31'" name="date_to"/>
<field name="planned_amount">12000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim11" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-11-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-11-30'" name="date_to"/>
<field name="planned_amount">18000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
<record id="budget_line_analytic_agrolait_pessim12" model="crossovered.budget.lines">
<field name="crossovered_budget_id" ref="crossovered_budget_budgetpessimistic0"/>
<field eval="str(datetime.now().year+1)+'-12-01'" name="date_from"/>
<field eval="str(datetime.now().year+1)+'-12-31'" name="date_to"/>
<field name="planned_amount">18000</field>
<field name="analytic_account_id" ref="analytic.analytic_agrolait"/>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,515 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * om_account_budget
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-04-15 18:16+0000\n"
"PO-Revision-Date: 2022-04-15 18:16+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"End Date\" of the budget line should be included in the Period of the "
"budget"
msgstr "يجب تضمين \"تاريخ الانتهاء\" لبند الميزانية في فترة الميزانية\n"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"Start Date\" of the budget line should be included in the Period of the "
"budget"
msgstr "يجب تضمين \"تاريخ البدء\" لبند الميزانية في فترة الميزانية\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_kanban
msgid "<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" title=\"Period\"/>"
msgstr ""
"<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" title=\"فترة\n"
"\"/>"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__account_ids
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
msgid "Accounts"
msgstr "الحسابات"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__percentage
msgid "Achievement"
msgstr "موهلات"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction
msgid "Action Needed"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__practical_amount
msgid "Amount really earned/spent."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__theoritical_amount
msgid "Amount you are supposed to have earned/spent at this date."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__planned_amount
msgid ""
"Amount you plan to earn/spend. Record a positive amount if it is a revenue "
"and a negative amount if it is a cost."
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_analytic_account
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_account_id
msgid "Analytic Account"
msgstr "الحساب التحليلي"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_plan_id
msgid "Analytic Group"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Approve"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_attachment_count
msgid "Attachment Count"
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_tree
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Budget"
msgstr "الدخل\n"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_account_analytic_account_cb_lines
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Budget Items"
msgstr "بنود الميزانية\n"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget_lines
msgid "Budget Line"
msgstr "حد الميزانية\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__crossovered_budget_line
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__crossovered_budget_line
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_tree
msgid "Budget Lines"
msgstr "خطوط الميزانية\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__name
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Budget Name"
msgstr "اسم الميزانية\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_state
msgid "Budget State"
msgstr "دولة الميزانية\n"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_budget_post
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__general_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_tree
msgid "Budgetary Position"
msgstr "موقف الميزانية\n"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.open_budget_post_form
#: model:ir.ui.menu,name:om_account_budget.menu_budget_post_form
msgid "Budgetary Positions"
msgstr "وظائف الميزانية\n"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_view
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Budgets"
msgstr "الميزانيات\n"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_lines_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_lines_view
msgid "Budgets Analysis"
msgstr "تحليل الميزانيات\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Cancel Budget"
msgstr "إلغاء الميزانية\n"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__cancel
msgid "Cancelled"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Click to create a new budget."
msgstr "انقر لإنشاء ميزانية جديدة.\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__company_id
msgid "Company"
msgstr "الشركة"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__percentage
msgid ""
"Comparison between practical and theoretical amount. This measure tells you "
"if you are below or over budget."
msgstr ""
"مقارنة بين المقدار العملي والنظري. يخبرك هذا الإجراء إذا كنت أقل من "
"الميزانية أو تزيد عنها.\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Confirm"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__confirm
msgid "Confirmed"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_uid
msgid "Created by"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_date
msgid "Created on"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__currency_id
msgid "Currency"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__display_name
msgid "Display Name"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__done
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Done"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__draft
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft Budgets"
msgstr "مشروع الميزانيات\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_to
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_to
msgid "End Date"
msgstr "تاريخ الانتهاء"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Entries..."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_follower_ids
msgid "Followers"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_partner_ids
msgid "Followers (Partners)"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Group By"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__has_message
msgid "Has Message"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__id
msgid "ID"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread
msgid "If checked, new messages require your attention."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "If checked, some messages have a delivery error."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__is_above_budget
msgid "Is Above Budget"
msgstr "فوق الميزانية\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_is_follower
msgid "Is Follower"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines____last_update
msgid "Last Modified on"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_uid
msgid "Last Updated by"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_date
msgid "Last Updated on"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error
msgid "Message Delivery error"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_ids
msgid "Messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__name
msgid "Name"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Not Cancelled"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of Actions"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of errors"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of messages which requires an action"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Number of unread messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__paid_date
msgid "Paid Date"
msgstr "تاريخ المدفوعة\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Period"
msgstr "فترة\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__planned_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Planned Amount"
msgstr "المبلغ المخطط\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Planned amount"
msgstr "المبلغ المخطط\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__practical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Practical Amount"
msgstr "المبلغ العملي\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Practical amount"
msgstr "المبلغ العملي\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Reset to Draft"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__user_id
msgid "Responsible"
msgstr "المسؤول "
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "SMS Delivery error"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_from
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_from
msgid "Start Date"
msgstr "تاريخ البداية"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__state
msgid "Status"
msgstr ""
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid "The budget must have at least one account."
msgstr "يجب أن تحتوي الميزانية على حساب واحد على الأقل.\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__theoritical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Theoretical Amount"
msgstr "المبلغ النظري\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Theoritical Amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Theoritical amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve Budgets"
msgstr "لاعتماد الميزانيات\n"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread
msgid "Unread Messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Unread Messages Counter"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Use budgets to compare actual with expected revenues and costs"
msgstr ""
"استخدم الميزانيات لمقارنة الإيرادات الفعلية مع الإيرادات والتكاليف "
"المتوقعة\n"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__validate
msgid "Validated"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website Messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website communication history"
msgstr ""
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"You have to enter at least a budgetary position or analytic account on a "
"budget line."
msgstr ""
"يجب عليك إدخال موقف ميزانية أو حساب تحليلي على الأقل في بند الميزانية.\n"

View File

@@ -0,0 +1,508 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * om_account_budget
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-06 03:01+0000\n"
"PO-Revision-Date: 2022-07-06 03:01+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"End Date\" of the budget line should be included in the Period of the "
"budget"
msgstr ""
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"Start Date\" of the budget line should be included in the Period of the "
"budget"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_kanban
msgid "<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" title=\"Period\"/>"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__account_ids
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
msgid "Accounts"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__percentage
msgid "Achievement"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction
msgid "Action Needed"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__practical_amount
msgid "Amount really earned/spent."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__theoritical_amount
msgid "Amount you are supposed to have earned/spent at this date."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__planned_amount
msgid ""
"Amount you plan to earn/spend. Record a positive amount if it is a revenue "
"and a negative amount if it is a cost."
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_analytic_account
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_account_id
msgid "Analytic Account"
msgstr "الحساب التحليلي"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_plan_id
msgid "Analytic Group"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Approve"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_attachment_count
msgid "Attachment Count"
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_tree
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Budget"
msgstr ""
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_account_analytic_account_cb_lines
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Budget Items"
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget_lines
msgid "Budget Line"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__crossovered_budget_line
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__crossovered_budget_line
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_tree
msgid "Budget Lines"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__name
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Budget Name"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_state
msgid "Budget State"
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_budget_post
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__general_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_tree
msgid "Budgetary Position"
msgstr ""
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.open_budget_post_form
#: model:ir.ui.menu,name:om_account_budget.menu_budget_post_form
msgid "Budgetary Positions"
msgstr "وظائف الميزانية\n"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_view
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Budgets"
msgstr "الميزانيات\n"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_lines_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_lines_view
msgid "Budgets Analysis"
msgstr "تحليل الميزانيات\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Cancel Budget"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__cancel
msgid "Cancelled"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Click to create a new budget."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__company_id
msgid "Company"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__percentage
msgid ""
"Comparison between practical and theoretical amount. This measure tells you "
"if you are below or over budget."
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Confirm"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__confirm
msgid "Confirmed"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_uid
msgid "Created by"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_date
msgid "Created on"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__currency_id
msgid "Currency"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__display_name
msgid "Display Name"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__done
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Done"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__draft
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft Budgets"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_to
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_to
msgid "End Date"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Entries..."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_follower_ids
msgid "Followers"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_partner_ids
msgid "Followers (Partners)"
msgstr "المتابعون (الشركاء)\n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Group By"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__has_message
msgid "Has Message"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__id
msgid "ID"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread
msgid "If checked, new messages require your attention."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "If checked, some messages have a delivery error."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__is_above_budget
msgid "Is Above Budget"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_is_follower
msgid "Is Follower"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines____last_update
msgid "Last Modified on"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_uid
msgid "Last Updated by"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_date
msgid "Last Updated on"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error
msgid "Message Delivery error"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_ids
msgid "Messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__name
msgid "Name"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Not Cancelled"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of Actions"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of errors"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of messages which requires an action"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Number of unread messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__paid_date
msgid "Paid Date"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Period"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__planned_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Planned Amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Planned amount"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__practical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Practical Amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Practical amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Reset to Draft"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__user_id
msgid "Responsible"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "SMS Delivery error"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_from
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_from
msgid "Start Date"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__state
msgid "Status"
msgstr ""
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid "The budget must have at least one account."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__theoritical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Theoretical Amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Theoritical Amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Theoritical amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve Budgets"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread
msgid "Unread Messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Unread Messages Counter"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Use budgets to compare actual with expected revenues and costs"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__validate
msgid "Validated"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website Messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website communication history"
msgstr ""
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"You have to enter at least a budgetary position or analytic account on a "
"budget line."
msgstr ""

View File

@@ -0,0 +1,461 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * om_account_budget
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 19.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-22 12:14+0000\n"
"PO-Revision-Date: 2024-03-22 12:14+0000\n"
"Last-Translator: Sergio Ariel Ameghino <ariel.ameghino@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_kanban
msgid "<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" title=\"Period\"/>"
msgstr "<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Período\" title=\"Período\"/>"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__account_ids
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
msgid "Accounts"
msgstr "Cuentas"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__percentage
msgid "Achievement"
msgstr "Logros"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction
msgid "Action Needed"
msgstr "Acción requerida"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__practical_amount
msgid "Amount really earned/spent."
msgstr "Importe realmente ganado/gastado"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__theoritical_amount
msgid "Amount you are supposed to have earned/spent at this date."
msgstr "Importe que se supone que debe haber ganado/gastado en esta fecha"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__planned_amount
msgid ""
"Amount you plan to earn/spend. Record a positive amount if it is a revenue "
"and a negative amount if it is a cost."
msgstr ""
"Importe que planea ganar/gastar. Registre una cantidad positiva si es un "
"ingreso y una cantidad negativa si es un costo."
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_analytic_account
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_account_id
msgid "Analytic Account"
msgstr "Cuenta analítica"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_plan_id
msgid "Analytic Plan"
msgstr "Plan analítico"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Approve"
msgstr "Aprobar"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_attachment_count
msgid "Attachment Count"
msgstr "Cantidad de adjuntos"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_tree
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Budget"
msgstr "Presupuesto"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_account_analytic_account_cb_lines
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Budget Items"
msgstr "Items de presupuesto"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget_lines
msgid "Budget Line"
msgstr "Línea de presupuesto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__crossovered_budget_line
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__crossovered_budget_line
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_tree
msgid "Budget Lines"
msgstr "Líneas de presupuesto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__name
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Budget Name"
msgstr "Nombre del presupuesto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_state
msgid "Budget State"
msgstr "Estado del presupuesto"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_budget_post
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__general_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_tree
msgid "Budgetary Position"
msgstr "Situación presupuestaria"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.open_budget_post_form
#: model:ir.ui.menu,name:om_account_budget.menu_budget_post_form
msgid "Budgetary Positions"
msgstr "Situaciones presupuestarias"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_view
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Budgets"
msgstr "Presupuestos"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_lines_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_lines_view
msgid "Budgets Analysis"
msgstr "Análisis de presupuestos"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Cancel Budget"
msgstr "Cancelar presupuesto"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__cancel
msgid "Cancelled"
msgstr "Cancelado"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Click to create a new budget."
msgstr "Haga clic para crear un nuevo presupuesto."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__company_id
msgid "Company"
msgstr "Compañía"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__percentage
msgid ""
"Comparison between practical and theoretical amount. This measure tells you "
"if you are below or over budget."
msgstr ""
"Comparación entre importe práctico y teórico. Esta medida le dice si está "
"por debajo o por encima del presupuesto."
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Confirm"
msgstr "Confirmar"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__confirm
msgid "Confirmed"
msgstr "Confirmado"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_date
msgid "Created on"
msgstr "Creado en"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__currency_id
msgid "Currency"
msgstr "Moneda"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__display_name
msgid "Display Name"
msgstr "Nombre mostrado"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__done
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Done"
msgstr "Hecho"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__draft
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft"
msgstr "Borrador"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft Budgets"
msgstr "Presupuestos en Borrador"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_to
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_to
msgid "End Date"
msgstr "Fecha final"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Entries..."
msgstr "Asientos..."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_follower_ids
msgid "Followers"
msgstr "Seguidores"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_partner_ids
msgid "Followers (Partners)"
msgstr "Seguidores (Empresas)"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Group By"
msgstr "Agrupar por"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__has_message
msgid "Has Message"
msgstr "Tiene un mensaje"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__id
msgid "ID"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction
msgid "If checked, new messages require your attention."
msgstr "Si está marcado, mensajes nuevos requieren su atención."
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "If checked, some messages have a delivery error."
msgstr "Si está marcado, algunos mensajes tienen un error de entrega."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__is_above_budget
msgid "Is Above Budget"
msgstr "Está por encima del presupuesto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_is_follower
msgid "Is Follower"
msgstr "Es seguidor"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_uid
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_date
msgid "Last Updated on"
msgstr "Ultima actualización en"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error
msgid "Message Delivery error"
msgstr "Mensaje de error de entrega"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_ids
msgid "Messages"
msgstr "Mensajes"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__name
msgid "Name"
msgstr "Nombre"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Not Cancelled"
msgstr "No cancelado"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of Actions"
msgstr "Número de acciones"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of errors"
msgstr "Número de errores"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of messages requiring action"
msgstr "Número de mensajes que requieren una acción"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr "Número de mensajes con error de entrega"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__paid_date
msgid "Paid Date"
msgstr "Fecha de pago"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Period"
msgstr "Período"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__planned_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Planned Amount"
msgstr "Importe planificado"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Planned amount"
msgstr "Importe planificado"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__practical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Practical Amount"
msgstr "Importe práctico"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Practical amount"
msgstr "Importe práctico"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__rating_ids
msgid "Ratings"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Reset to Draft"
msgstr "Restablecer a Borrador"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__user_id
msgid "Responsible"
msgstr "Responsable"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "SMS Delivery error"
msgstr "Error de Entrega SMS"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_from
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_from
msgid "Start Date"
msgstr "Fecha de inicio"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__state
msgid "Status"
msgstr "Estado"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__theoritical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Theoretical Amount"
msgstr "Importe teórico"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Theoritical Amount"
msgstr "Importe teórico"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Theoritical amount"
msgstr "Importe teórico"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve"
msgstr "Aprobar"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve Budgets"
msgstr "Aprobar presupuestos"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Use budgets to compare actual with expected revenues and costs"
msgstr ""
"Utilice presupuestos para comparar los ingresos y costos reales con los "
"esperados."
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__validate
msgid "Validated"
msgstr "Validado"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website Messages"
msgstr "Mensajes del sitio web"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website communication history"
msgstr "Historial de Comunicación del sitio web"

View File

@@ -0,0 +1,515 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * om_account_budget
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0-20220319\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-06-12 03:15+0000\n"
"PO-Revision-Date: 2022-06-11 22:15-0500\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es_MX\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
"X-Generator: Poedit 3.1\n"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid "\"End Date\" of the budget line should be included in the Period of the budget"
msgstr ""
"La \"fecha de finalización\" de la línea presupuestaria debe incluirse en el período del "
"presupuesto"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid "\"Start Date\" of the budget line should be included in the Period of the budget"
msgstr ""
"La \"fecha de inicio\" de la línea presupuestaria debe incluirse en el período del "
"presupuesto"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_kanban
msgid "<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" title=\"Period\"/>"
msgstr "<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Periodo\" title=\"Periodo\"/>"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__account_ids
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
msgid "Accounts"
msgstr "Cuentas"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__percentage
msgid "Achievement"
msgstr "Logro"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction
msgid "Action Needed"
msgstr "Acción requerida"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__practical_amount
msgid "Amount really earned/spent."
msgstr "Importe realmente ingresado/gastado"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__theoritical_amount
msgid "Amount you are supposed to have earned/spent at this date."
msgstr "Importe supuestamente ingresado/gastado a esta fecha"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__planned_amount
msgid ""
"Amount you plan to earn/spend. Record a positive amount if it is a revenue and a "
"negative amount if it is a cost."
msgstr ""
"Cantidad que planea ganar/gastar. Registre una cantidad positiva si es un ingreso y una "
"cantidad negativa si es un costo."
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_analytic_account
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_account_id
msgid "Analytic Account"
msgstr "Cuenta analítica"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_plan_id
msgid "Analytic Group"
msgstr "Grupo analítico"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Approve"
msgstr "Aprobado"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_attachment_count
msgid "Attachment Count"
msgstr "Conteo de archivos adjuntos"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_tree
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Budget"
msgstr "Presupuestos"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_account_analytic_account_cb_lines
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Budget Items"
msgstr "Elementos de presupuesto"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget_lines
msgid "Budget Line"
msgstr "Línea de presupuesto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__crossovered_budget_line
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__crossovered_budget_line
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_tree
msgid "Budget Lines"
msgstr "Líneas de presupuesto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__name
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Budget Name"
msgstr "Nombre del presupuesto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_state
msgid "Budget State"
msgstr "Estado del presupuesto"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_budget_post
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__general_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_tree
msgid "Budgetary Position"
msgstr "Posición presupuestaria"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.open_budget_post_form
#: model:ir.ui.menu,name:om_account_budget.menu_budget_post_form
msgid "Budgetary Positions"
msgstr "Posiciones presupuestarias"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_view
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Budgets"
msgstr "Presupuestos"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_lines_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_lines_view
msgid "Budgets Analysis"
msgstr "Análisis de presupuestos"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Cancel Budget"
msgstr "Cancelar presupuesto"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__cancel
msgid "Cancelled"
msgstr "Cancelado"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Click to create a new budget."
msgstr "Clic aquí para crear un nuevo presupuesto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__company_id
msgid "Company"
msgstr "Compañia"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__percentage
msgid ""
"Comparison between practical and theoretical amount. This measure tells you if you are "
"below or over budget."
msgstr ""
"Comparación entre cantidad práctica y teórica. Esta medida le dice si está por debajo o "
"por encima del presupuesto."
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Confirm"
msgstr "Confirmar"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__confirm
msgid "Confirmed"
msgstr "Confirmado"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_date
msgid "Created on"
msgstr "Creado el"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__currency_id
msgid "Currency"
msgstr "Moneda"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__display_name
msgid "Display Name"
msgstr "Nombre mostrado"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__done
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Done"
msgstr "Hecho"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__draft
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft"
msgstr "Borrador"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft Budgets"
msgstr "Presupuestos borrador"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_to
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_to
msgid "End Date"
msgstr "Fecha final"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Entries..."
msgstr "Asientos"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_follower_ids
msgid "Followers"
msgstr "Seguidores"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_partner_ids
msgid "Followers (Partners)"
msgstr "Seguidores (Empresas)"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Group By"
msgstr "Agrupar por"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__has_message
msgid "Has Message"
msgstr "Tiene mensajes"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__id
msgid "ID"
msgstr "ID"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread
msgid "If checked, new messages require your attention."
msgstr "Si está marcado hay nuevos mensajes que requieren su atención."
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "If checked, some messages have a delivery error."
msgstr "Si está marcado hay nuevos mensajes que requieren su atención."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__is_above_budget
msgid "Is Above Budget"
msgstr "Es superior al presupuesto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_is_follower
msgid "Is Follower"
msgstr "Es un seguidor"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines____last_update
msgid "Last Modified on"
msgstr "Última modificación en"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_uid
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_date
msgid "Last Updated on"
msgstr "Última actualización el"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_main_attachment_id
msgid "Main Attachment"
msgstr "Adjuntos principales"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error
msgid "Message Delivery error"
msgstr "Error de Envío de Mensaje"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_ids
msgid "Messages"
msgstr "Mensajes"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__name
msgid "Name"
msgstr "Nombre"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Not Cancelled"
msgstr "No cancelado"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of Actions"
msgstr "Número de acciones"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of errors"
msgstr "Numero de errores"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of messages which requires an action"
msgstr "Número de mensajes que requieren una acción"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr "Número de mensajes con error de envío"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Number of unread messages"
msgstr "Número de mensajes no leídos"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__paid_date
msgid "Paid Date"
msgstr "Fecha de pago"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Period"
msgstr "Periodo"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__planned_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Planned Amount"
msgstr "Importe previsto"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Planned amount"
msgstr "Importe previsto"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__practical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Practical Amount"
msgstr "Importe real"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Practical amount"
msgstr "Importe real"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Reset to Draft"
msgstr "Cambiar a borrador"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__user_id
msgid "Responsible"
msgstr "Responsable"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "SMS Delivery error"
msgstr "Error de entrega del SMS"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_from
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_from
msgid "Start Date"
msgstr "Fecha de inicio"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__state
msgid "Status"
msgstr "Estatus"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid "The budget must have at least one account."
msgstr "El presupuesto debe tener al menos una cuenta."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__theoritical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Theoretical Amount"
msgstr "Importe teórico"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Theoritical Amount"
msgstr "Importe teórico"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Theoritical amount"
msgstr "Importe teórico"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve"
msgstr "Para aprobar"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve Budgets"
msgstr "Presupuestos para aprobar"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread
msgid "Unread Messages"
msgstr "Mensajes sin leer"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Unread Messages Counter"
msgstr "Contador de mensajes sin leer"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Use budgets to compare actual with expected revenues and costs"
msgstr "Use los presupuestos para comparar los ingresos y costos reales con los esperados."
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__validate
msgid "Validated"
msgstr "Validado"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website Messages"
msgstr "Mensajes del sitio web"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website communication history"
msgstr "Historial de comunicaciones del sitio web"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"You have to enter at least a budgetary position or analytic account on a budget line."
msgstr ""
"Debe ingresar al menos una posición presupuestaria o una cuenta analítica en una línea "
"de presupuesto."

View File

@@ -0,0 +1,526 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * om_account_budget
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0-20220319\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-06-12 03:15+0000\n"
"PO-Revision-Date: 2022-07-06 00:09+0200\n"
"Last-Translator: Sylvain Lc\n"
"Language-Team: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 3.1\n"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"End Date\" of the budget line should be included in the Period of the "
"budget"
msgstr ""
"La \"date de fin\" de la ligne budgétaire doit être incluse dans la période "
"du budget"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"Start Date\" of the budget line should be included in the Period of the "
"budget"
msgstr ""
"La \"date de début\" de la ligne budgétaire doit être incluse dans la "
"période du budget"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_kanban
msgid ""
"<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" title=\"Period"
"\"/>"
msgstr ""
"<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Période\" title="
"\"Période\"/>"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__account_ids
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
msgid "Accounts"
msgstr "Comptes"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__percentage
msgid "Achievement"
msgstr "Réalisation"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction
msgid "Action Needed"
msgstr "Action nécessaire"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__practical_amount
msgid "Amount really earned/spent."
msgstr "Montant vraiment gagné/dépensé."
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__theoritical_amount
msgid "Amount you are supposed to have earned/spent at this date."
msgstr "Montant que vous êtes supposé avoir gagné/dépensé à cette date."
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__planned_amount
msgid ""
"Amount you plan to earn/spend. Record a positive amount if it is a revenue "
"and a negative amount if it is a cost."
msgstr ""
"Montant que vous prévoyez gagner / dépenser. Enregistrez un montant positif "
"s'il s'agit d'un revenu et un montant négatif s'il s'agit d'un coût."
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_analytic_account
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_account_id
msgid "Analytic Account"
msgstr "Compte analytique"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_plan_id
msgid "Analytic Group"
msgstr "Groupe analytique"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Approve"
msgstr "Approuver"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_attachment_count
msgid "Attachment Count"
msgstr "Nombre de pièces jointes"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_tree
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Budget"
msgstr "Budget"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_account_analytic_account_cb_lines
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Budget Items"
msgstr "Postes budgétaires"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget_lines
msgid "Budget Line"
msgstr "Ligne de budget"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__crossovered_budget_line
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__crossovered_budget_line
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_tree
msgid "Budget Lines"
msgstr "Lignes de budget"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__name
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Budget Name"
msgstr "Nom du budget"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_state
msgid "Budget State"
msgstr "Etat du Budget"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_budget_post
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__general_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_tree
msgid "Budgetary Position"
msgstr "Poste budgétaire"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.open_budget_post_form
#: model:ir.ui.menu,name:om_account_budget.menu_budget_post_form
msgid "Budgetary Positions"
msgstr "Positions budgétaires"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_view
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Budgets"
msgstr "Budgets"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_lines_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_lines_view
msgid "Budgets Analysis"
msgstr "Analyse budgétaire"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Cancel Budget"
msgstr "Annuler le budget"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__cancel
msgid "Cancelled"
msgstr "Annulé"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Click to create a new budget."
msgstr "Cliquer pour créer un nouveau budget."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__company_id
msgid "Company"
msgstr "Société"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__percentage
msgid ""
"Comparison between practical and theoretical amount. This measure tells you "
"if you are below or over budget."
msgstr ""
"Comparaison entre le montant pratique et le montant théorique. Ceci vous "
"permet de savoir si vous êtes en dessous ou au dessus du budget."
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Confirm"
msgstr "Confirmer"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__confirm
msgid "Confirmed"
msgstr "Confirmé"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_uid
msgid "Created by"
msgstr "Créé par"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_date
msgid "Created on"
msgstr "Créé sur"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__currency_id
msgid "Currency"
msgstr "Devise"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__display_name
msgid "Display Name"
msgstr "Afficher un nom"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__done
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Done"
msgstr "Terminé"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__draft
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft"
msgstr "Brouillon"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft Budgets"
msgstr "Budgets brouillons"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_to
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_to
msgid "End Date"
msgstr "Date de fin"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Entries..."
msgstr "Ecritures..."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_follower_ids
msgid "Followers"
msgstr "Suiveuses"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_partner_ids
msgid "Followers (Partners)"
msgstr "Abonnés (Partenaires)"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Group By"
msgstr "Grouper par"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__has_message
msgid "Has Message"
msgstr "A un message"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__id
msgid "ID"
msgstr "ID"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread
msgid "If checked, new messages require your attention."
msgstr "Si coché, de nouveaux messages demandent votre attention."
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "If checked, some messages have a delivery error."
msgstr "Si actif, certains messages ont une erreur de livraison."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__is_above_budget
msgid "Is Above Budget"
msgstr "Est Au-dessus du Budget"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_is_follower
msgid "Is Follower"
msgstr "Est un abonné"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_uid
msgid "Last Updated by"
msgstr "Dernière mise à jour par"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_date
msgid "Last Updated on"
msgstr "Dernière mise à jour le"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_main_attachment_id
msgid "Main Attachment"
msgstr "Pièce jointe principale"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error
msgid "Message Delivery error"
msgstr "Erreur d'envoi du message"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_ids
msgid "Messages"
msgstr "Messages"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__name
msgid "Name"
msgstr "Nom"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Not Cancelled"
msgstr "Pas Annulé"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of Actions"
msgstr "Nombre d'actions"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of errors"
msgstr "Nombre d'erreurs"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of messages which requires an action"
msgstr "Nombre de messages exigeant une action"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr "Nombre de messages avec des erreurs d'envoi"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Number of unread messages"
msgstr "Nombre de messages non lus"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__paid_date
msgid "Paid Date"
msgstr "Date de paiement"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Period"
msgstr "Période"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__planned_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Planned Amount"
msgstr "Montant prévu"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Planned amount"
msgstr "Montant prévu"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__practical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Practical Amount"
msgstr "Montant réel"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Practical amount"
msgstr "Montant Réel"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Reset to Draft"
msgstr "Remettre en brouillon"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__user_id
msgid "Responsible"
msgstr "Responsable"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "SMS Delivery error"
msgstr "Erreur d'envoi SMS"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_from
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_from
msgid "Start Date"
msgstr "Date de début"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__state
msgid "Status"
msgstr "Statut"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid "The budget must have at least one account."
msgstr "Le budget doit avoir au moins un compte."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__theoritical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Theoretical Amount"
msgstr "Montant théorique"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Theoritical Amount"
msgstr "Montant théorique"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Theoritical amount"
msgstr "Montant théorique"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve"
msgstr "À approuver"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve Budgets"
msgstr "Budgets à approuver"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread
msgid "Unread Messages"
msgstr "Messages non lus"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Unread Messages Counter"
msgstr "Compteur de messages non lus"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Use budgets to compare actual with expected revenues and costs"
msgstr ""
"Utilisez les budgets pour comparer les revenus et coûts attendus à la "
"situation actuelle"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__validate
msgid "Validated"
msgstr "Validé"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website Messages"
msgstr "Messages du site web"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website communication history"
msgstr "Historique de communication du site web"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"You have to enter at least a budgetary position or analytic account on a "
"budget line."
msgstr ""
"Vous devez saisir au moins une position budgétaire ou un compte analytique "
"sur une ligne budgétaire."

View File

@@ -0,0 +1,515 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * om_account_budget
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-04-15 06:43+0000\n"
"PO-Revision-Date: 2022-04-15 06:43+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"End Date\" of the budget line should be included in the Period of the "
"budget"
msgstr "Bütçe satırının \"bitiş tarihi\", bütçe dönemi içinde olmalıdır."
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"Start Date\" of the budget line should be included in the Period of the "
"budget"
msgstr "Bütçe satırının \"başlangıç tarihi\", bütçe dönemi içinde olmalıdır."
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_kanban
msgid "<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" title=\"Period\"/>"
msgstr "<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Dönem\" title=\"Dönem\"/>"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__account_ids
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
msgid "Accounts"
msgstr "Hesaplar"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__percentage
msgid "Achievement"
msgstr "Kazanım"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction
msgid "Action Needed"
msgstr "Eylem Gerekli"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__practical_amount
msgid "Amount really earned/spent."
msgstr "Gerçekten kazanılan/harcanan tutar."
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__theoritical_amount
msgid "Amount you are supposed to have earned/spent at this date."
msgstr "Bu tarihe dek kazanmanız/harcamanız gereken tutar"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__planned_amount
msgid ""
"Amount you plan to earn/spend. Record a positive amount if it is a revenue "
"and a negative amount if it is a cost."
msgstr ""
"Kazanmayı/harcamayı planladığınız tutar. Bu bir gelir ise pozitif, gider ise"
" negatif değer giriniz."
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_analytic_account
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_account_id
msgid "Analytic Account"
msgstr "Analitik Hesap"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_plan_id
msgid "Analytic Group"
msgstr "Analitik Grup"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Approve"
msgstr "Onayla"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_attachment_count
msgid "Attachment Count"
msgstr "Ek Sayısı"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_tree
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Budget"
msgstr "Bütçe"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_account_analytic_account_cb_lines
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Budget Items"
msgstr "Bütçe Kalemleri"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget_lines
msgid "Budget Line"
msgstr "Bütçe Satırı"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__crossovered_budget_line
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__crossovered_budget_line
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_tree
msgid "Budget Lines"
msgstr "Bütçe Satırları"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__name
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Budget Name"
msgstr "Bütçe Adı"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_state
msgid "Budget State"
msgstr "Bütçe Durumu"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_budget_post
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__general_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_tree
msgid "Budgetary Position"
msgstr "Bütçe Pozisyonu"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.open_budget_post_form
#: model:ir.ui.menu,name:om_account_budget.menu_budget_post_form
msgid "Budgetary Positions"
msgstr "Bütçe Pozisyonları"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_view
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Budgets"
msgstr "Bütçeler"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_lines_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_lines_view
msgid "Budgets Analysis"
msgstr "Bütçe Analizi"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Cancel Budget"
msgstr "Bütçeyi İptal Et"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__cancel
msgid "Cancelled"
msgstr "İptal Edildi"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Click to create a new budget."
msgstr "Yeni bir bütçe oluşturmak için tıklayınız"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__company_id
msgid "Company"
msgstr "Şirket"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__percentage
msgid ""
"Comparison between practical and theoretical amount. This measure tells you "
"if you are below or over budget."
msgstr ""
"Pratik ve teorik tutarların karşılaştırması. Bu kriter size bütçenin altında"
" mı üstünde mi olduğunuzu söyler."
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Confirm"
msgstr "Onayla"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__confirm
msgid "Confirmed"
msgstr "Teyit Edildi"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_uid
msgid "Created by"
msgstr "Oluşturan"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_date
msgid "Created on"
msgstr "Oluşturulma Tarihi"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__currency_id
msgid "Currency"
msgstr "Para Birimi"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__display_name
msgid "Display Name"
msgstr "Görüntülenen Ad"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__done
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Done"
msgstr "Tamamlandı"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__draft
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft"
msgstr "Taslak"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft Budgets"
msgstr "Taslak Bütçe"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_to
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_to
msgid "End Date"
msgstr "Bitiş Tarihi"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Entries..."
msgstr "Kayıtlar"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_follower_ids
msgid "Followers"
msgstr "Takipçiler"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_partner_ids
msgid "Followers (Partners)"
msgstr "Takipçiler (İş Ortakları)"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Group By"
msgstr "Gruplama"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__has_message
msgid "Has Message"
msgstr "Mesajı Olan"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__id
msgid "ID"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread
msgid "If checked, new messages require your attention."
msgstr "İşaretlenirse, yeni mesajlarla ilgilenmeniz gerekir."
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "If checked, some messages have a delivery error."
msgstr "İşaretlenirse, bazı iletilerde teslim hatası olur."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__is_above_budget
msgid "Is Above Budget"
msgstr "Bütçenin Üzerinde"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_is_follower
msgid "Is Follower"
msgstr "Takipçi mi?"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines____last_update
msgid "Last Modified on"
msgstr "Son Değişiklik Tarihi"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_uid
msgid "Last Updated by"
msgstr "Son Güncellemeyi Yapan"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_date
msgid "Last Updated on"
msgstr "Son Güncelleme Tarihi"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_main_attachment_id
msgid "Main Attachment"
msgstr "Ana Ek"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error
msgid "Message Delivery error"
msgstr "Teslim hatası mesajı"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_ids
msgid "Messages"
msgstr "Mesajlar"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__name
msgid "Name"
msgstr "İsim"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Not Cancelled"
msgstr "İptal Edilmedi"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of Actions"
msgstr "Eylem Sayısı"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of errors"
msgstr "Hata Sayısı"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of messages which requires an action"
msgstr "Eylem gerektiren mesaj sayısı"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr "Teslim hatası içeren mesaj hatası"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Number of unread messages"
msgstr "Okunmamış mesaj sayısı"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__paid_date
msgid "Paid Date"
msgstr "Ödeme Tarihi"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Period"
msgstr "Dönem"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__planned_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Planned Amount"
msgstr "Planlanan Tutar"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Planned amount"
msgstr "Planlanan Tutar"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__practical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Practical Amount"
msgstr "Pratikteki Tutar"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Practical amount"
msgstr "Pratikteki tutar"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Reset to Draft"
msgstr "Taslak durumuna sıfırla"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__user_id
msgid "Responsible"
msgstr "Sorumlu"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "SMS Delivery error"
msgstr "SMS Teslim Hatası"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_from
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_from
msgid "Start Date"
msgstr "Başlangıç Tarihi"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__state
msgid "Status"
msgstr "Durum"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid "The budget must have at least one account."
msgstr "Bütçe en az bir hesap içermelidir."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__theoritical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Theoretical Amount"
msgstr "Teorik Tutar"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Theoritical Amount"
msgstr "Teorik Tutar"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Theoritical amount"
msgstr "Teorik Tutar"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve"
msgstr "Onaylamak"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve Budgets"
msgstr "Onay Bekleyen Bütçe"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread
msgid "Unread Messages"
msgstr "Okunmamış Mesajlar"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Unread Messages Counter"
msgstr "Okunmamış Mesaj Sayacı"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Use budgets to compare actual with expected revenues and costs"
msgstr ""
"Beklenen gelir ve harcamalar ile gerçekte değerleri karşılaştırmak için "
"bütçeleri kullanabilirsiniz"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__validate
msgid "Validated"
msgstr "Doğrulandı"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website Messages"
msgstr "Websitesi Mesajları"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website communication history"
msgstr "Websitesi iletişim geçmişi"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"You have to enter at least a budgetary position or analytic account on a "
"budget line."
msgstr ""
"Bütçe satırına en az bir bütçe pozisyonu ya da analitik hesap girmelisiniz."

View File

@@ -0,0 +1,513 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * om_account_budget
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-07 07:13+0000\n"
"PO-Revision-Date: 2022-07-07 07:13+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"End Date\" of the budget line should be included in the Period of the "
"budget"
msgstr ""
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"Start Date\" of the budget line should be included in the Period of the "
"budget"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_kanban
msgid "<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" title=\"Period\"/>"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__account_ids
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
msgid "Accounts"
msgstr "Рахунки"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__percentage
msgid "Achievement"
msgstr "Досягнення"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction
msgid "Action Needed"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__practical_amount
msgid "Amount really earned/spent."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__theoritical_amount
msgid "Amount you are supposed to have earned/spent at this date."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__planned_amount
msgid ""
"Amount you plan to earn/spend. Record a positive amount if it is a revenue "
"and a negative amount if it is a cost."
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_analytic_account
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_account_id
msgid "Analytic Account"
msgstr "Аналітичний рахунок"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_plan_id
msgid "Analytic Group"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Approve"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_attachment_count
msgid "Attachment Count"
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_tree
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Budget"
msgstr ""
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_account_analytic_account_cb_lines
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Budget Items"
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget_lines
msgid "Budget Line"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__crossovered_budget_line
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__crossovered_budget_line
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_tree
msgid "Budget Lines"
msgstr "Рядки бюджету"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__name
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Budget Name"
msgstr "Назва бюджету"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_state
msgid "Budget State"
msgstr ""
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_budget_post
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__general_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_tree
msgid "Budgetary Position"
msgstr "Стаття бюджету"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.open_budget_post_form
#: model:ir.ui.menu,name:om_account_budget.menu_budget_post_form
msgid "Budgetary Positions"
msgstr "Стаття бюджету"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_view
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Budgets"
msgstr "Бюджети"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_lines_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_lines_view
msgid "Budgets Analysis"
msgstr "Аналіз бюджетів"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Cancel Budget"
msgstr "Скасувати бюджет"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__cancel
msgid "Cancelled"
msgstr "Скасовано"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Click to create a new budget."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__company_id
msgid "Company"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__percentage
msgid ""
"Comparison between practical and theoretical amount. This measure tells you "
"if you are below or over budget."
msgstr ""
"Порівняння практичної та теоритичної сум. Цей захід сповістить Вас при "
"недовикористанні або превищенні бюджету."
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Confirm"
msgstr "Підтвердити"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__confirm
msgid "Confirmed"
msgstr "Підтверджено"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_uid
msgid "Created by"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_date
msgid "Created on"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__currency_id
msgid "Currency"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__display_name
msgid "Display Name"
msgstr "Відобразити назву"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__done
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Done"
msgstr "Виконано"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__draft
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft"
msgstr "Чернетка"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft Budgets"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_to
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_to
msgid "End Date"
msgstr "Дата закінчення"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Entries..."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_follower_ids
msgid "Followers"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_channel_ids
msgid "Followers (Channels)"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_partner_ids
msgid "Followers (Partners)"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Group By"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__id
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__id
msgid "ID"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread
msgid "If checked, new messages require your attention."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "If checked, some messages have a delivery error."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__is_above_budget
msgid "Is Above Budget"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_is_follower
msgid "Is Follower"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget____last_update
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines____last_update
msgid "Last Modified on"
msgstr "Останні зміни"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_uid
msgid "Last Updated by"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_date
msgid "Last Updated on"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error
msgid "Message Delivery error"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_ids
msgid "Messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__name
msgid "Name"
msgstr "Назва"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Not Cancelled"
msgstr "Не скасовано"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of Actions"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of errors"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of messages which requires an action"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Number of unread messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__paid_date
msgid "Paid Date"
msgstr "Дата оплати"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Period"
msgstr "Період"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__planned_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Planned Amount"
msgstr "Запланована сума"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Planned amount"
msgstr "Запланована сума"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__practical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Practical Amount"
msgstr "Фактична сума"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Practical amount"
msgstr "Фактична сума"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Reset to Draft"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__user_id
msgid "Responsible"
msgstr "Відповідальний"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "SMS Delivery error"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_from
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_from
msgid "Start Date"
msgstr "Дата початку"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__state
msgid "Status"
msgstr "Статус"
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid "The budget must have at least one account."
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__theoritical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Theoretical Amount"
msgstr "Теоретична сума"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Theoritical Amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Theoritical amount"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve Budgets"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread
msgid "Unread Messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_unread_counter
msgid "Unread Messages Counter"
msgstr ""
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Use budgets to compare actual with expected revenues and costs"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__validate
msgid "Validated"
msgstr "Перевірено"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website Messages"
msgstr ""
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website communication history"
msgstr ""
#. module: om_account_budget
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"You have to enter at least a budgetary position or analytic account on a "
"budget line."
msgstr ""

View File

@@ -0,0 +1,496 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * om_account_budget
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0-20231105\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-23 21:30+0000\n"
"PO-Revision-Date: 2023-11-24 06:16+0800\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.4.1\n"
#. module: om_account_budget
#. odoo-python
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"End Date\" of the budget line should be included in the Period of the "
"budget"
msgstr "預算項目的「結束日期」應包含在預算期間"
#. module: om_account_budget
#. odoo-python
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"\"Start Date\" of the budget line should be included in the Period of the "
"budget"
msgstr "預算項目的「開始日期」應包含在預算期間"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_kanban
msgid ""
"<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" "
"title=\"Period\"/>"
msgstr ""
"<i class=\"fa fa-clock-o\" role=\"img\" aria-label=\"Period\" "
"title=\"Period\"/>"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__account_ids
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
msgid "Accounts"
msgstr "會計帳戶"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__percentage
msgid "Achievement"
msgstr "達成"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction
msgid "Action Needed"
msgstr "需採取行動"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__practical_amount
msgid "Amount really earned/spent."
msgstr "實際賺取/花費的金額。"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__theoritical_amount
msgid "Amount you are supposed to have earned/spent at this date."
msgstr "您在該日期應賺取/支出的金額。"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__planned_amount
msgid ""
"Amount you plan to earn/spend. Record a positive amount if it is a revenue "
"and a negative amount if it is a cost."
msgstr ""
"您計劃賺取/支出的金額。如果是收入,則記錄正數;如果是成本,則記錄負數。"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_analytic_account
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_account_id
msgid "Analytic Account"
msgstr "分析科目"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__analytic_plan_id
msgid "Analytic Plan"
msgstr "分析計劃"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Approve"
msgstr "批准"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_attachment_count
msgid "Attachment Count"
msgstr "附件數"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_tree
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Budget"
msgstr "預算"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_account_analytic_account_cb_lines
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Budget Items"
msgstr "預算項目"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_crossovered_budget_lines
msgid "Budget Line"
msgstr "預算明細"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_analytic_account__crossovered_budget_line
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__crossovered_budget_line
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_tree
msgid "Budget Lines"
msgstr "預算明細"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__name
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Budget Name"
msgstr "預算名稱"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__crossovered_budget_state
msgid "Budget State"
msgstr "預算國家"
#. module: om_account_budget
#: model:ir.model,name:om_account_budget.model_account_budget_post
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__general_budget_id
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_search
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_budget_post_tree
msgid "Budgetary Position"
msgstr "預算狀況"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.open_budget_post_form
#: model:ir.ui.menu,name:om_account_budget.menu_budget_post_form
msgid "Budgetary Positions"
msgstr "預算項目"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_view
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Budgets"
msgstr "預算"
#. module: om_account_budget
#: model:ir.actions.act_window,name:om_account_budget.act_crossovered_budget_lines_view
#: model:ir.ui.menu,name:om_account_budget.menu_act_crossovered_budget_lines_view
msgid "Budgets Analysis"
msgstr "預算分析"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Cancel Budget"
msgstr "取消預算"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__cancel
msgid "Cancelled"
msgstr "已取消"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Click to create a new budget."
msgstr "點選以建立新預算。"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__company_id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__company_id
msgid "Company"
msgstr "公司"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget_lines__percentage
msgid ""
"Comparison between practical and theoretical amount. This measure tells you "
"if you are below or over budget."
msgstr "實際金額與理論金額的比較。此指標可以告訴您是否低於或超過預算。"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Confirm"
msgstr "確認"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__confirm
msgid "Confirmed"
msgstr "已確認"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_uid
msgid "Created by"
msgstr "建立者"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__create_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__create_date
msgid "Created on"
msgstr "建立於"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__currency_id
msgid "Currency"
msgstr "幣別"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__display_name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__display_name
msgid "Display Name"
msgstr "顯示名稱"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__done
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Done"
msgstr "完成"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__draft
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft"
msgstr "草稿"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "Draft Budgets"
msgstr "預算草案"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_to
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_to
msgid "End Date"
msgstr "結束日期"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Entries..."
msgstr "細項"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_follower_ids
msgid "Followers"
msgstr "關注者"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_partner_ids
msgid "Followers (Partners)"
msgstr "訂閱者(合作夥伴)"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Group By"
msgstr "分組按"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__has_message
msgid "Has Message"
msgstr "有訊息"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__id
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__id
msgid "ID"
msgstr "ID"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction
msgid "If checked, new messages require your attention."
msgstr "勾選代表有新訊息需要您留意."
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "If checked, some messages have a delivery error."
msgstr "勾選代表有訊息發生傳送錯誤."
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__is_above_budget
msgid "Is Above Budget"
msgstr "超出預算"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_is_follower
msgid "Is Follower"
msgstr "是訂閱者"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_uid
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_uid
msgid "Last Updated by"
msgstr "最後更新人"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__write_date
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__write_date
msgid "Last Updated on"
msgstr "最後更新時間"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error
msgid "Message Delivery error"
msgstr "訊息遞送錯誤"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_ids
msgid "Messages"
msgstr "訊息"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_account_budget_post__name
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__name
msgid "Name"
msgstr "名稱"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_search
msgid "Not Cancelled"
msgstr "未取消"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of Actions"
msgstr "動作數"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of errors"
msgstr "錯誤數"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_needaction_counter
msgid "Number of messages requiring action"
msgstr "需要執行操作的訊息數量"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr "有發送錯誤的郵件數"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__paid_date
msgid "Paid Date"
msgstr "付款日期"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Period"
msgstr "會計期間"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__planned_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Planned Amount"
msgstr "計劃金額"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Planned amount"
msgstr "計劃金額"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__practical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Practical Amount"
msgstr "實際金額"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Practical amount"
msgstr "實際數量"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__rating_ids
msgid "Ratings"
msgstr "評分"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Reset to Draft"
msgstr "重設為草稿"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__user_id
msgid "Responsible"
msgstr "負責人"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__message_has_sms_error
msgid "SMS Delivery error"
msgstr "簡訊發送錯誤"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__date_from
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__date_from
msgid "Start Date"
msgstr "開始日期"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__state
msgid "Status"
msgstr "狀態"
#. module: om_account_budget
#. odoo-python
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid "The budget must have at least one account."
msgstr "預算必須至少有一個帳戶。"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget_lines__theoritical_amount
#: model_terms:ir.ui.view,arch_db:om_account_budget.crossovered_budget_view_form
msgid "Theoretical Amount"
msgstr "理論金額"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_account_analytic_account_form_inherit_budget
msgid "Theoritical Amount"
msgstr "理論金額"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_graph
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_line_pivot
msgid "Theoritical amount"
msgstr "理論金額"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve"
msgstr "待批准"
#. module: om_account_budget
#: model_terms:ir.ui.view,arch_db:om_account_budget.view_crossovered_budget_search
msgid "To Approve Budgets"
msgstr "待批准預算"
#. module: om_account_budget
#: model_terms:ir.actions.act_window,help:om_account_budget.act_crossovered_budget_view
msgid "Use budgets to compare actual with expected revenues and costs"
msgstr "使用預算來比較實際與預期的收入和成本"
#. module: om_account_budget
#: model:ir.model.fields.selection,name:om_account_budget.selection__crossovered_budget__state__validate
msgid "Validated"
msgstr "已驗證"
#. module: om_account_budget
#: model:ir.model.fields,field_description:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website Messages"
msgstr "網站訊息"
#. module: om_account_budget
#: model:ir.model.fields,help:om_account_budget.field_crossovered_budget__website_message_ids
msgid "Website communication history"
msgstr "網站溝通記錄"
#. module: om_account_budget
#. odoo-python
#: code:addons/om_account_budget/models/account_budget.py:0
#, python-format
msgid ""
"You have to enter at least a budgetary position or analytic account on a "
"budget line."
msgstr "您必須在預算明細上至少輸入預算狀況或分析帳戶。"

View File

@@ -0,0 +1,2 @@
from . import account_budget
from . import account_analytic_account

View File

@@ -0,0 +1,37 @@
from odoo import fields, models, api
class AccountAnalyticAccount(models.Model):
_inherit = "account.analytic.account"
crossovered_budget_line = fields.One2many(
'crossovered.budget.lines', 'analytic_account_id', 'Budget Lines'
)
class AccountAnalyticLine(models.Model):
_inherit = 'account.analytic.line'
@api.model
def _where_calc(self, domain, active_test=True):
"""Computes the WHERE clause needed to implement an OpenERP domain.
:param list domain: the domain to compute
:param bool active_test: whether the default filtering of records with
``active`` field set to ``False`` should be applied.
:return: the query expressing the given domain as provided in domain
:rtype: Query
"""
# if the object has an active field ('active', 'x_active'), filter out all
# inactive records unless they were explicitly asked for
if self._active_name and active_test and self._context.get('active_test', True):
# the item[0] trick below works for domain items and '&'/'|'/'!'
# operators too
if not any(item[0] == self._active_name for item in domain):
domain = [(self._active_name, '=', 1)] + domain
if domain:
return expression.expression(domain, self).query
else:
return Query(self.env, self._table, self._table_sql)

View File

@@ -0,0 +1,270 @@
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class AccountBudgetPost(models.Model):
_name = "account.budget.post"
_order = "name"
_description = "Budgetary Position"
name = fields.Char('Name', required=True)
account_ids = fields.Many2many(
'account.account', 'account_budget_rel', 'budget_id',
'account_id', 'Accounts'
)
company_id = fields.Many2one('res.company', 'Company', required=True, default=lambda self: self.env.company)
def _check_account_ids(self, vals):
# Raise an error to prevent the account.budget.post to have not specified account_ids.
# This check is done on create because require=True doesn't work on Many2many fields.
if 'account_ids' in vals:
account_ids = self.new({'account_ids': vals['account_ids']}, origin=self).account_ids
else:
account_ids = self.account_ids
if not account_ids:
raise ValidationError(_('The budget must have at least one account.'))
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
self._check_account_ids(vals)
return super(AccountBudgetPost, self).create(vals_list)
def write(self, vals):
self._check_account_ids(vals)
return super(AccountBudgetPost, self).write(vals)
class CrossoveredBudget(models.Model):
_name = "crossovered.budget"
_description = "Budget"
_inherit = ['mail.thread']
name = fields.Char('Budget Name', required=True)
user_id = fields.Many2one('res.users', 'Responsible', default=lambda self: self.env.user)
date_from = fields.Date('Start Date', required=True)
date_to = fields.Date('End Date', required=True)
state = fields.Selection([
('draft', 'Draft'),
('cancel', 'Cancelled'),
('confirm', 'Confirmed'),
('validate', 'Validated'),
('done', 'Done')
], 'Status', default='draft', index=True, required=True, readonly=True, copy=False, tracking=True)
crossovered_budget_line = fields.One2many(
'crossovered.budget.lines', 'crossovered_budget_id',
'Budget Lines', copy=True
)
company_id = fields.Many2one('res.company', 'Company', required=True, default=lambda self: self.env.company)
def action_budget_confirm(self):
self.write({'state': 'confirm'})
def action_budget_draft(self):
self.write({'state': 'draft'})
def action_budget_validate(self):
self.write({'state': 'validate'})
def action_budget_cancel(self):
self.write({'state': 'cancel'})
def action_budget_done(self):
self.write({'state': 'done'})
class CrossoveredBudgetLines(models.Model):
_name = "crossovered.budget.lines"
_description = "Budget Line"
name = fields.Char(compute='_compute_line_name')
crossovered_budget_id = fields.Many2one('crossovered.budget', 'Budget', ondelete='cascade', index=True, required=True)
analytic_account_id = fields.Many2one('account.analytic.account', 'Analytic Account')
analytic_plan_id = fields.Many2one(related='analytic_account_id.plan_id')
general_budget_id = fields.Many2one('account.budget.post', 'Budgetary Position')
date_from = fields.Date('Start Date', required=True)
date_to = fields.Date('End Date', required=True)
paid_date = fields.Date('Paid Date')
currency_id = fields.Many2one('res.currency', related='company_id.currency_id', readonly=True)
planned_amount = fields.Monetary(
'Planned Amount', required=True,
help="Amount you plan to earn/spend. Record a positive amount if it is a revenue and a negative amount if it is a cost.")
practical_amount = fields.Monetary(
compute='_compute_practical_amount', string='Practical Amount', help="Amount really earned/spent.")
theoritical_amount = fields.Monetary(
compute='_compute_theoritical_amount', string='Theoretical Amount',
help="Amount you are supposed to have earned/spent at this date.")
percentage = fields.Float(
compute='_compute_percentage', string='Achievement',
help="Comparison between practical and theoretical amount. This measure tells you if you are below or over budget.")
company_id = fields.Many2one(related='crossovered_budget_id.company_id', comodel_name='res.company',
string='Company', store=True, readonly=True)
is_above_budget = fields.Boolean(compute='_is_above_budget')
crossovered_budget_state = fields.Selection(related='crossovered_budget_id.state', string='Budget State', store=True, readonly=True)
@api.model
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
# overrides the default read_group in order to compute the computed fields manually for the group
fields_list = {'practical_amount', 'theoritical_amount', 'percentage'}
fields = {field.split(':', 1)[0] if field.split(':', 1)[0] in fields_list else field for field in fields}
result = super(CrossoveredBudgetLines, self).read_group(domain, fields, groupby, offset=offset, limit=limit,
orderby=orderby, lazy=lazy)
if any(x in fields for x in fields_list):
for group_line in result:
# initialise fields to compute to 0 if they are requested
if 'practical_amount' in fields:
group_line['practical_amount'] = 0
if 'theoritical_amount' in fields:
group_line['theoritical_amount'] = 0
if 'percentage' in fields:
group_line['percentage'] = 0
group_line['practical_amount'] = 0
group_line['theoritical_amount'] = 0
if group_line.get('__domain'):
all_budget_lines_that_compose_group = self.search(group_line['__domain'])
else:
all_budget_lines_that_compose_group = self.search([])
for budget_line_of_group in all_budget_lines_that_compose_group:
if 'practical_amount' in fields or 'percentage' in fields:
group_line['practical_amount'] += budget_line_of_group.practical_amount
if 'theoritical_amount' in fields or 'percentage' in fields:
group_line['theoritical_amount'] += budget_line_of_group.theoritical_amount
if 'percentage' in fields:
if group_line['theoritical_amount']:
# use a weighted average
group_line['percentage'] = float(
(group_line['practical_amount'] or 0.0) / group_line['theoritical_amount']) * 100
return result
def _is_above_budget(self):
for line in self:
if line.theoritical_amount >= 0:
line.is_above_budget = line.practical_amount > line.theoritical_amount
else:
line.is_above_budget = line.practical_amount < line.theoritical_amount
def _compute_line_name(self):
#just in case someone opens the budget line in form view
for line in self:
computed_name = line.crossovered_budget_id.name
if line.general_budget_id:
computed_name += ' - ' + line.general_budget_id.name
if line.analytic_account_id:
computed_name += ' - ' + line.analytic_account_id.name
line.name = computed_name
def _compute_practical_amount(self):
for line in self:
acc_ids = line.general_budget_id.account_ids.ids
date_to = line.date_to
date_from = line.date_from
if line.analytic_account_id.id:
analytic_line_obj = self.env['account.analytic.line']
domain = [('account_id', '=', line.analytic_account_id.id),
('date', '>=', date_from),
('date', '<=', date_to),
]
if acc_ids:
domain += [('general_account_id', 'in', acc_ids)]
where_query = analytic_line_obj._where_calc(domain)
analytic_line_obj._apply_ir_rules(where_query, 'read')
from_string, from_params = where_query.from_clause
where_string, where_params = where_query.where_clause
from_clause, where_clause, where_clause_params = from_string, where_string, from_params + where_params
select = "SELECT SUM(amount) from " + from_clause + " where " + where_clause
else:
aml_obj = self.env['account.move.line']
domain = [('account_id', 'in',
line.general_budget_id.account_ids.ids),
('date', '>=', date_from),
('date', '<=', date_to)
]
where_query = aml_obj._where_calc(domain)
aml_obj._apply_ir_rules(where_query, 'read')
from_string, from_params = where_query.from_clause
where_string, where_params = where_query.where_clause
from_clause, where_clause, where_clause_params = from_string, where_string, from_params + where_params
select = "SELECT sum(credit)-sum(debit) from " + from_clause + " where " + where_clause
self.env.cr.execute(select, where_clause_params)
line.practical_amount = self.env.cr.fetchone()[0] or 0.0
def _compute_theoritical_amount(self):
# beware: 'today' variable is mocked in the python tests and thus, its implementation matter
today = fields.Date.today()
for line in self:
if line.paid_date:
if today <= line.paid_date:
theo_amt = 0.00
else:
theo_amt = line.planned_amount
else:
line_timedelta = line.date_to - line.date_from
elapsed_timedelta = today - line.date_from
if elapsed_timedelta.days < 0:
# If the budget line has not started yet, theoretical amount should be zero
theo_amt = 0.00
elif line_timedelta.days > 0 and today < line.date_to:
# If today is between the budget line date_from and date_to
theo_amt = (elapsed_timedelta.total_seconds() / line_timedelta.total_seconds()) * line.planned_amount
else:
theo_amt = line.planned_amount
line.theoritical_amount = theo_amt
def _compute_percentage(self):
for line in self:
if line.theoritical_amount != 0.00:
line.percentage = float((line.practical_amount or 0.0) / line.theoritical_amount)
else:
line.percentage = 0.00
@api.constrains('general_budget_id', 'analytic_account_id')
def _must_have_analytical_or_budgetary_or_both(self):
if not self.analytic_account_id and not self.general_budget_id:
raise ValidationError(
_("You have to enter at least a budgetary position or analytic account on a budget line."))
def action_open_budget_entries(self):
if self.analytic_account_id:
# if there is an analytic account, then the analytic items are loaded
action = self.env['ir.actions.act_window']._for_xml_id('analytic.account_analytic_line_action_entries')
action['domain'] = [('account_id', '=', self.analytic_account_id.id),
('date', '>=', self.date_from),
('date', '<=', self.date_to)
]
if self.general_budget_id:
action['domain'] += [('general_account_id', 'in', self.general_budget_id.account_ids.ids)]
else:
# otherwise the journal entries booked on the accounts of the budgetary postition are opened
action = self.env['ir.actions.act_window']._for_xml_id('account.action_account_moves_all_a')
action['domain'] = [('account_id', 'in',
self.general_budget_id.account_ids.ids),
('date', '>=', self.date_from),
('date', '<=', self.date_to)
]
return action
@api.constrains('date_from', 'date_to')
def _line_dates_between_budget_dates(self):
for rec in self:
budget_date_from = rec.crossovered_budget_id.date_from
budget_date_to = rec.crossovered_budget_id.date_to
if rec.date_from:
date_from = rec.date_from
if date_from < budget_date_from or date_from > budget_date_to:
raise ValidationError(_('"Start Date" of the budget line should be included in the Period of the budget'))
if rec.date_to:
date_to = rec.date_to
if date_to < budget_date_from or date_to > budget_date_to:
raise ValidationError(_('"End Date" of the budget line should be included in the Period of the budget'))

View File

@@ -0,0 +1,7 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_crossovered_budget,crossovered.budget,model_crossovered_budget,account.group_account_manager,1,0,0,0
access_account_budget_post,account.budget.post,model_account_budget_post,account.group_account_manager,1,0,0,0
access_account_budget_post_accountant,account.budget.post accountant,model_account_budget_post,account.group_account_user,1,1,1,1
access_crossovered_budget_accountant,crossovered.budget accountant,model_crossovered_budget,account.group_account_user,1,1,1,1
access_crossovered_budget_lines_accountant,crossovered.budget.lines accountant,model_crossovered_budget_lines,account.group_account_user,1,1,1,1
access_budget,crossovered.budget.lines manager,model_crossovered_budget_lines,base.group_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_crossovered_budget crossovered.budget model_crossovered_budget account.group_account_manager 1 0 0 0
3 access_account_budget_post account.budget.post model_account_budget_post account.group_account_manager 1 0 0 0
4 access_account_budget_post_accountant account.budget.post accountant model_account_budget_post account.group_account_user 1 1 1 1
5 access_crossovered_budget_accountant crossovered.budget accountant model_crossovered_budget account.group_account_user 1 1 1 1
6 access_crossovered_budget_lines_accountant crossovered.budget.lines accountant model_crossovered_budget_lines account.group_account_user 1 1 1 1
7 access_budget crossovered.budget.lines manager model_crossovered_budget_lines base.group_user 1 1 1 0

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="budget_post_comp_rule" model="ir.rule">
<field name="name">Budget post multi-company</field>
<field name="model_id" ref="model_account_budget_post"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
</record>
<record id="budget_comp_rule" model="ir.rule">
<field name="name">Budget multi-company</field>
<field name="model_id" ref="model_crossovered_budget"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
</record>
<record id="budget_lines_comp_rule" model="ir.rule">
<field name="name">Budget lines multi-company</field>
<field name="model_id" ref="model_crossovered_budget_lines"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
</record>
</data>
</odoo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,84 @@
<section class="oe_container oe_dark">
<div class="col-md-12">
<h2 class="oe_slogan" style="font-size: 35px;color:#2C0091"><b>Odoo 19 Budget Management</b></h2>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div style="text-align:center;">
<p class="fa fa-hand-o-right" style="color:CRIMSON;font-size: 25px;">
<span style="color:#2dd280;font-size: 15px;">Use budgets to compare actual with expected revenues and costs.</span>
</p><br/>
</div>
<br/>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan" style="color:#332c3c;font-size: 28px;">Budgetary Positions</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img src="budgetary_postions.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan" style="color:#332c3c;font-size: 28px;">Budgets</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img src="budgets.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan" style="color:#332c3c;font-size: 28px;">Budget Analysis</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img src="budget_analysis_pivot.png">
</div>
</div>
</div>
</section>
<hr style="width: 100%;height: 4px;background: #2C0091;margin: 0px 0px;">
<hr style="width: 100%;height: 4px;background: #148963;margin: 0px 0px;">
<section class="oe_container oe_dark">
<div class="oe_row ">
<div class="oe_slogan text-center">
<img src="odoo_mates.png"/>
<div style="color:#269900;">
<h3 style="color:#2C0091;font-size: 25px;">If you need any help or want more features, just contact us:</h3><br>
<h3 style="color:#2C0091;font-size: 20px;">Email: <a href="odoomates@gmail.com">odoomates@gmail.com</a> <br></h3>
</div>
<div class="oe_slogan">
<h2>
<a target="_blank" href="https://www.facebook.com/odoomate/" target="new">
<i class="fa fa-facebook-square" style="font-size:38px;"></i>
</a>
<a target="_blank" href="https://twitter.com/odoomates/" target="new">
<i class="fa fa-twitter" style="font-size:38px;"></i>
</a>
<a href="#" target="_blank">
<i class="fa fa-linkedin" style="font-size:38px;"></i>
</a>
<a target="_blank" href="https://www.youtube.com/channel/UCVKlUZP7HAhdQgs-9iTJklQ">
<i class="fa fa-youtube-play" style="font-size:38px;"></i>
</a>
</h2>
</div>
</div>
</div>
</section>
<hr style="width: 100%;height: 4px;background: #148963;margin: 0px 0px;">
<hr style="width: 100%;height: 4px;background: #2C0091;margin: 0px 0px;">

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_analytic_account_form_inherit_budget" model="ir.ui.view">
<field name="name">account.analytic.account.form.inherit.budget</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
<field name="priority" eval="50"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='main']" position='after'>
<notebook groups="account.group_account_user">
<page string="Budget Items">
<field name="crossovered_budget_line" widget="one2many_list" colspan="4" nolabel="1"
mode="list">
<list string="Budget Items" editable="top">
<field name="crossovered_budget_id"/>
<field name="general_budget_id"/>
<field name="date_from"/>
<field name="date_to"/>
<field name="paid_date"/>
<field name="planned_amount" widget="monetary"/>
<field name="practical_amount" sum="Practical Amount" widget="monetary"/>
<field name="theoritical_amount" sum="Theoritical Amount" widget="monetary"/>
<field name="percentage"/>
</list>
<form string="Budget Items">
<field name="crossovered_budget_id"/>
<field name="general_budget_id"/>
<field name="date_from"/>
<field name="date_to"/>
<field name="paid_date"/>
<field name="planned_amount" widget="monetary"/>
</form>
</field>
</page>
</notebook>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,382 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_budget_post_search" model="ir.ui.view">
<field name="name">account.budget.post.search</field>
<field name="model">account.budget.post</field>
<field name="arch" type="xml">
<search string="Budgetary Position">
<field name="name" filter_domain="[('name','ilike',self)]" string="Budgetary Position"/>
<field name="company_id" groups="base.group_multi_company"/>
</search>
</field>
</record>
<record id="view_budget_post_tree" model="ir.ui.view">
<field name="name">account.budget.post.list</field>
<field name="model">account.budget.post</field>
<field name="arch" type="xml">
<list string="Budgetary Position">
<field name="name"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</list>
</field>
</record>
<record id="open_budget_post_form" model="ir.actions.act_window">
<field name="name">Budgetary Positions</field>
<field name="res_model">account.budget.post</field>
<field name="view_mode">list,kanban,form</field>
<field name="view_id" ref="view_budget_post_tree"/>
<field name="search_view_id" ref="view_budget_post_search"/>
</record>
<menuitem id="menu_budget_post_form"
action="open_budget_post_form"
parent="account.account_account_menu"
sequence="5"/>
<record id="view_budget_post_form" model="ir.ui.view">
<field name="name">account.budget.post.form</field>
<field name="model">account.budget.post</field>
<field name="arch" type="xml">
<form string="Budgetary Position">
<group col="4">
<field name="name"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
</group>
<notebook>
<page string="Accounts">
<field name="account_ids">
<list>
<field name="code"/>
<field name="name"/>
</list>
</field>
</page>
</notebook>
</form>
</field>
</record>
<record id="crossovered_budget_view_form" model="ir.ui.view">
<field name="name">crossovered.budget.view.form</field>
<field name="model">crossovered.budget</field>
<field name="arch" type="xml">
<form string="Budget">
<header>
<button string="Confirm" name="action_budget_confirm" type="object"
invisible="state != 'draft'"
class="oe_highlight"/>
<button string="Approve" name="action_budget_validate" type="object"
invisible="state != 'confirm'"
class="oe_highlight"/>
<button string="Done" name="action_budget_done" type="object"
invisible="state != 'validate'"
class="oe_highlight"/>
<button string="Reset to Draft" name="action_budget_draft"
invisible="state != 'cancel'" type="object"/>
<button string="Cancel Budget" name="action_budget_cancel" invisible="state not in ('confirm', 'validate')" type="object"/>
<field name="state" widget="statusbar" />
</header>
<sheet string="Budget">
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name" readonly="state != 'draft'" placeholder="Budget Name"/>
</h1>
</div>
<group>
<group>
<field name="user_id" readonly="state != 'draft'"/>
</group>
<group>
<label for="date_from" string="Period"/>
<div>
<field name="date_from" class="oe_inline"
readonly="state != 'draft'"/>
-
<field name="date_to" class="oe_inline" readonly="state != 'draft'"
nolabel="1"/>
</div>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
</group>
</group>
<notebook>
<page string="Budget Lines">
<field name="crossovered_budget_line"
context="{'default_date_from': date_from,'default_date_to': date_to}" colspan="4"
nolabel="1" readonly="state != 'draft'">
<list string="Budget Lines" decoration-success="is_above_budget and planned_amount &gt; 0" decoration-danger="is_above_budget and planned_amount &lt; 0" editable="bottom">
<field name="general_budget_id"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
<field name="date_from"/>
<field name="date_to"/>
<field name="paid_date" groups="base.group_no_one"/>
<field name="currency_id" invisible="1"/>
<field name="planned_amount" sum="Planned Amount"/>
<field name="practical_amount" sum="Practical Amount"/>
<field name="theoritical_amount" sum="Theoretical Amount"/>
<field name="percentage" widget="percentage" />
<button type="object" name="action_open_budget_entries" string="Entries..."
icon="fa-arrow-circle-o-right"/>
<field name="is_above_budget" invisible="1"/>
</list>
<form string="Budget Lines">
<group>
<group>
<field name="currency_id" invisible="1"/>
<field name="general_budget_id"/>
<field name="planned_amount"/>
<field name="analytic_account_id"
groups="analytic.group_analytic_accounting"/>
</group>
<group>
<label for="date_from" string="Period"/>
<div>
<field name="date_from" class="oe_inline"/>
-
<field name="date_to" class="oe_inline"/>
</div>
<field name="paid_date" groups="base.group_no_one"/>
<field name="company_id" options="{'no_create': True}"
groups="base.group_multi_company"/>
</group>
</group>
</form>
</field>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<record id="crossovered_budget_view_tree" model="ir.ui.view">
<field name="name">crossovered.budget.view.list</field>
<field name="model">crossovered.budget</field>
<field name="arch" type="xml">
<list decoration-info="state == 'draft'" decoration-muted="state in ('done','cancel')" string="Budget">
<field name="name" colspan="1"/>
<field name="date_from"/>
<field name="date_to"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<field name="user_id"/>
<field name="state"/>
</list>
</field>
</record>
<record id="view_crossovered_budget_kanban" model="ir.ui.view">
<field name="name">crossovered.budget.kanban</field>
<field name="model">crossovered.budget</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="name"/>
<field name="date_from"/>
<field name="date_to"/>
<field name="user_id"/>
<field name="state"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<div class="row mb4">
<div class="col-8">
<strong>
<field name="name"/>
</strong>
</div>
<div class="col-4">
<span class="float-right">
<field name="state" widget="kanban_label_selection"
options="{'classes': {'draft': 'default', 'done': 'success'}}"/>
</span>
</div>
</div>
<div class="row">
<div class="col-10">
<i class="fa fa-clock-o" role="img" aria-label="Period" title="Period"/>
<t t-esc="record.date_from.value"/>-
<t t-esc="record.date_to.value"/>
</div>
<div class="col-2">
<span class="float-right">
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)"
t-att-title="record.user_id.value" t-att-alt="record.user_id.value" width="24" height="24"
class="oe_kanban_avatar float-right"/>
</span>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="view_crossovered_budget_search" model="ir.ui.view">
<field name="name">crossovered.budget.search</field>
<field name="model">crossovered.budget</field>
<field name="arch" type="xml">
<search string="Budget">
<field name="name" filter_domain="[('name','ilike',self)]" string="Budget"/>
<field name="date_from"/>
<field name="date_to"/>
<filter string="Draft" name="draft" domain="[('state','=','draft')]" help="Draft Budgets"/>
<filter string="To Approve" name="toapprove" domain="[('state','=','confirm')]"
help="To Approve Budgets"/>
<field name="state"/>
</search>
</field>
</record>
<record id="act_crossovered_budget_view" model="ir.actions.act_window">
<field name="name">Budgets</field>
<field name="res_model">crossovered.budget</field>
<field name="view_mode">list,kanban,form</field>
<field name="view_id" ref="crossovered_budget_view_tree"/>
<field name="search_view_id" ref="view_crossovered_budget_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Click to create a new budget.
</p>
<p>
Use budgets to compare actual with expected revenues and costs
</p>
</field>
</record>
<menuitem id="menu_act_crossovered_budget_view"
parent="account.account_account_menu"
name="Budgets"
action="act_crossovered_budget_view"
sequence="60"
groups="account.group_account_manager"/>
<record id="view_crossovered_budget_line_search" model="ir.ui.view">
<field name="name">account.budget.line.search</field>
<field name="model">crossovered.budget.lines</field>
<field name="arch" type="xml">
<search string="Budget Lines">
<field name="analytic_account_id"/>
<field name="crossovered_budget_id"/>
<filter name="filter_not_cancelled" string="Not Cancelled"
domain="[('crossovered_budget_state','!=','cancel')]"/>
<group>
<filter name="group_crossevered_budgdet_id" string="Budgets"
domain="[]" context="{'group_by':'crossovered_budget_id'}"/>
</group>
</search>
</field>
</record>
<record id="view_crossovered_budget_line_tree" model="ir.ui.view">
<field name="name">crossovered.budget.line.list</field>
<field name="model">crossovered.budget.lines</field>
<field name="arch" type="xml">
<list string="Budget Lines" create="0">
<field name="currency_id" invisible="1"/>
<field name="crossovered_budget_id" invisible="1"/>
<field name="general_budget_id" />
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" />
<field name="date_from" />
<field name="date_to" />
<field name="paid_date" groups="base.group_no_one" />
<field name="planned_amount"/>
<field name="practical_amount"/>
<field name="theoritical_amount"/>
<field name="percentage" widget="percentage"/>
</list>
</field>
</record>
<record id="view_crossovered_budget_line_form" model="ir.ui.view">
<field name="name">crossovered.budget.line.form</field>
<field name="model">crossovered.budget.lines</field>
<field name="arch" type="xml">
<form string="Budget Lines">
<sheet>
<group col="4">
<field name="currency_id" invisible="1"/>
<field name="crossovered_budget_state" invisible="1"/>
<field name="crossovered_budget_id"
readonly="crossovered_budget_state != 'draft'"/>
<field name="analytic_account_id"
readonly="crossovered_budget_state != 'draft'"/>
<field name="general_budget_id"
readonly="crossovered_budget_state != 'draft'"/>
<field name="date_from"
readonly="crossovered_budget_state != 'draft'"/>
<field name="date_to"
readonly="crossovered_budget_state != 'draft'"/>
<field name="paid_date"
readonly="crossovered_budget_state != 'draft'"/>
<field name="planned_amount"
readonly="crossovered_budget_state != 'draft'"/>
<field name="practical_amount"
readonly="crossovered_budget_state != 'draft'"/>
<field name="theoritical_amount"
readonly="crossovered_budget_state != 'draft'"/>
<field name="percentage" widget="percentage"
readonly="crossovered_budget_state != 'draft'"/>
<field name="company_id" options="{'no_create': True}"
groups="base.group_multi_company"
readonly="crossovered_budget_state != 'draft'"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_crossovered_budget_line_pivot" model="ir.ui.view">
<field name="name">crossovered.budget.line.pivot</field>
<field name="model">crossovered.budget.lines</field>
<field name="arch" type="xml">
<pivot string="Budget Lines">
<field name="crossovered_budget_id" type="row"/>
<field name="planned_amount" type="measure" string="Planned amount"/>
<field name="theoritical_amount" type="measure" string="Theoritical amount"/>
<field name="practical_amount" type="measure" string="Practical amount"/>
<field name="percentage" type="measure" widget="percentage"/>
</pivot>
</field>
</record>
<record id="view_crossovered_budget_line_graph" model="ir.ui.view">
<field name="name">crossovered.budget.line.graph</field>
<field name="model">crossovered.budget.lines</field>
<field name="arch" type="xml">
<graph string="Budget Lines">
<field name="crossovered_budget_id" type="row"/>
<field name="planned_amount" type="measure" string="Planned amount"/>
<field name="theoritical_amount" type="measure" string="Theoritical amount"/>
<field name="practical_amount" type="measure" string="Practical amount"/>
</graph>
</field>
</record>
<record id="act_crossovered_budget_lines_view" model="ir.actions.act_window">
<field name="name">Budgets Analysis</field>
<field name="res_model">crossovered.budget.lines</field>
<field name="view_mode">list,form,pivot,graph</field>
<field name="view_id" eval="False"/>
<field name="context">{'search_default_group_crossevered_budgdet_id': True,
'search_default_filter_not_cancelled':True}</field>
</record>
<menuitem id="menu_act_crossovered_budget_lines_view"
parent="account.account_reports_management_menu"
action="act_crossovered_budget_lines_view"
sequence="20"
groups="account.group_account_user"/>
<record id="act_account_analytic_account_cb_lines" model="ir.actions.act_window">
<field name="name">Budget Items</field>
<field name="res_model">crossovered.budget.lines</field>
<field name="view_mode">list,kanban,form</field>
<field name="context">{'search_default_analytic_account_id': [active_id],
'default_analytic_account_id': active_id}</field>
</record>
</odoo>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.account.budget</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="account.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//setting[@id='account_budget']" position="replace"/>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,45 @@
=============================
Customer Follow Up Management
=============================
This Module will add customer follow up management in Odoo 19 Community Edition
Installation
============
To install this module, you need to:
Download the module and add it to your Odoo addons folder. Afterward, log on to
your Odoo server and go to the Apps menu. Trigger the debug mode and update the
list by clicking on the "Update Apps List" link. Now install the module by
clicking on the install button.
Upgrade
============
To upgrade this module, you need to:
Download the module and add it to your Odoo addons folder. Restart the server
and log on to your Odoo server. Select the Apps menu and upgrade the module by
clicking on the upgrade button.
Configuration
=============
Configure follow up levels
Credits
=======
Contributors
------------
* Odoo Mates <odoomates@gmail.com>
Author & Maintainer
-------------------
This module is maintained by the Odoo Mates

View File

@@ -0,0 +1,3 @@
from . import wizard
from . import models
from . import report

View File

@@ -0,0 +1,27 @@
{
'name': 'Customer Follow Up Management',
'version': '19.0.1.0.2', # __odoosky_original_version__: '1.0.2'
'category': 'Accounting',
'description': """Customer FollowUp Management""",
'summary': """Customer FollowUp Management""",
'author': 'Odoo Mates, Odoo S.A',
'license': 'LGPL-3',
'website': 'https://www.odoomates.tech',
'depends': ['account', 'mail'],
'data': [
'security/security.xml',
'security/ir.model.access.csv',
'data/mail_template_data.xml',
'wizard/followup_print_view.xml',
'wizard/followup_results_view.xml',
'views/followup_view.xml',
'views/account_move.xml',
'views/partners.xml',
'views/report_followup.xml',
'views/reports.xml',
'views/followup_partner_view.xml',
'report/followup_report.xml',
],
'demo': ['demo/demo.xml'],
'images': ['static/description/banner.png'],
}

View File

@@ -0,0 +1,242 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="email_template_om_account_followup_level0" model="mail.template">
<field name="name">First polite payment follow-up reminder email</field>
<field name="email_from">{{ (user.email or '') }}</field>
<field name="subject">{{ user.company_id.name }} Payment Reminder</field>
<field name="lang">{{ object.lang }}</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); ">
<p>Dear <t t-out="object.name"/>,</p>
<p>
Exception made if there was a mistake of ours, it seems that the following amount stays unpaid. Please, take
appropriate measures in order to carry out this payment in the next 8 days.
Would your payment have been carried out after this mail was sent, please ignore this message. Do not hesitate to
contact our accounting department.
</p>
<br/>
Best Regards,
<br/>
<br/>
<t t-out="user.name" />
<br/>
<br/>
<t t-out="object.get_followup_table_html()" />
<br/>
</div>
]]></field>
</record>
<!--Mail template level 1 -->
<record id="email_template_om_account_followup_level1" model="mail.template">
<field name="name">A bit urging second payment follow-up reminder email</field>
<field name="email_from">{{ (user.email or '') }}</field>
<field name="subject">{{ user.company_id.name }} Payment Reminder</field>
<field name="email_to">{{ object.email }}</field>
<field name="lang">{{ object.lang }}</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); ">
<p>Dear <t t-out="object.name"/>,</p>
<p>
We are disappointed to see that despite sending a reminder, that your account is now seriously overdue.
It is essential that immediate payment is made, otherwise we will have to consider placing a stop on your account
which means that we will no longer be able to supply your company with (goods/services).
Please, take appropriate measures in order to carry out this payment in the next 8 days.
If there is a problem with paying invoice that we are not aware of, do not hesitate to contact our accounting
department. so that we can resolve the matter quickly.
Details of due payments is printed below.
</p>
<br/>
Best Regards,
<br/>
<br/>
<t t-out="user.name" />
<br/>
<br/>
<t t-out="object.get_followup_table_html()" />
<br/>
</div>
]]></field>
</record>
<!--Mail template level 2 -->
<record id="email_template_om_account_followup_level2" model="mail.template">
<field name="name">Urging payment follow-up reminder email</field>
<field name="email_from">{{ (user.email or '') }}</field>
<field name="subject">{{ user.company_id.name }} Payment Reminder</field>
<field name="email_to">{{ object.email }}</field>
<field name="lang">{{ object.lang }}</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); ">
<p>Dear <t t-out="object.name"/>,</p>
<p>
Despite several reminders, your account is still not settled.
Unless full payment is made in next 8 days, legal action for the recovery of the debt will be taken without
further notice.
I trust that this action will prove unnecessary and details of due payments is printed below.
In case of any queries concerning this matter, do not hesitate to contact our accounting department.
</p>
<br/>
Best Regards,
<br/>
<br/>
<t t-out="user.name" />
<br/>
<br/>
<t t-out="object.get_followup_table_html()" />
<br/>
</div>
]]></field>
</record>
<!-- Default follow up message -->
<record id="email_template_om_account_followup_default" model="mail.template">
<field name="name">Default payment follow-up reminder e-mail</field>
<field name="email_from">{{ (user.email or '') }}</field>
<field name="subject">{{ user.company_id.name }} Payment Reminder</field>
<field name="email_to">{{ object.email }}</field>
<field name="lang">{{ object.lang }}</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); ">
<p>Dear <t t-out="object.name"/>,</p>
<p>
Exception made if there was a mistake of ours, it seems that the following amount stays unpaid. Please, take
appropriate measures in order to carry out this payment in the next 8 days.
Would your payment have been carried out after this mail was sent, please ignore this message. Do not hesitate to
contact our accounting department.
</p>
<br/>
Best Regards,
<br/>
<br/>
<t t-out="user.name" />
<br/>
<br/>
<t t-out="object.get_followup_table_html()" />
<br/>
</div>
]]></field>
</record>
<record id="demo_followup1" model="followup.followup" forcecreate="False">
<field name="company_id" ref="base.main_company"/>
</record>
<record id="demo_followup_line1" model="followup.line" forcecreate="False">
<field name="name">Send first reminder email</field>
<field name="sequence">0</field>
<field name="delay">15</field>
<field name="followup_id" ref="demo_followup1"/>
<field name="send_email">True</field>
<field name="description">
Dear %(partner_name)s,
Exception made if there was a mistake of ours, it seems that
the following amount stays unpaid. Please, take appropriate
measures in order to carry out this payment in the next 8 days.
Would your payment have been carried out after this mail was
sent, please ignore this message. Do not hesitate to contact
our accounting department.
Best Regards,
</field>
<field name="email_template_id" ref="email_template_om_account_followup_level0"/>
</record>
<record id="demo_followup_line2" model="followup.line" forcecreate="False">
<field name="name">Send reminder letter and email</field>
<field name="sequence">1</field>
<field name="delay">30</field>
<field name="followup_id" ref="demo_followup1"/>
<field name="email_template_id"
ref="email_template_om_account_followup_level1"/>
<field name="send_email">True</field>
<field name="send_letter">True</field>
<field name="description">
Dear %(partner_name)s,
We are disappointed to see that despite sending a reminder,
that your account is now seriously overdue.
It is essential that immediate payment is made, otherwise we
will have to consider placing a stop on your account which
means that we will no longer be able to supply your company
with (goods/services).
Please, take appropriate measures in order to carry out this
payment in the next 8 days.
If there is a problem with paying invoice that we are not aware
of, do not hesitate to contact our accounting department, so
that we can resolve the matter quickly.
Details of due payments is printed below.
Best Regards,
</field>
</record>
<record id="demo_followup_line3" model="followup.line" forcecreate="False">
<field name="name">Call the customer on the phone</field>
<field name="sequence">3</field>
<field name="delay">40</field>
<field name="followup_id" ref="demo_followup1"/>
<field name="email_template_id"
ref="email_template_om_account_followup_level2"/>
<field eval="False" name="send_email"/>
<field name="manual_action">True</field>
<field name="manual_action_note">Call the customer on the phone!</field>
<field name="description">
Dear %(partner_name)s,
Despite several reminders, your account is still not settled.
Unless full payment is made in next 8 days, then legal action
for the recovery of the debt will be taken without further
notice.
I trust that this action will prove unnecessary and details of
due payments is printed below.
In case of any queries concerning this matter, do not hesitate
to contact our accounting department.
Best Regards,
</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="demo_followup_line4" model="followup.line">
<field name="name">Urging reminder email</field>
<field name="sequence">4</field>
<field name="delay">50</field>
<field name="followup_id" ref="demo_followup1"/>
<field name="send_email">True</field>
<field name="email_template_id" ref="email_template_om_account_followup_level2"/>
<field name="description">
Dear %(partner_name)s,
Despite several reminders, your account is still not settled.
Unless full payment is made in next 8 days, then legal action
for the recovery of the debt will be taken without further
notice.
I trust that this action will prove unnecessary and details of
due payments is printed below.
In case of any queries concerning this matter, do not hesitate
to contact our accounting department.
Best Regards,
</field>
</record>
<record id="demo_followup_line5" model="followup.line">
<field name="name">Urging reminder letter</field>
<field name="sequence">5</field>
<field name="delay">60</field>
<field name="followup_id" ref="demo_followup1"/>
<field eval="False" name="send_email"/>
<field name="send_letter">True</field>
<field name="email_template_id" ref="email_template_om_account_followup_level2"/>
<field name="description">
Dear %(partner_name)s,
Despite several reminders, your account is still not settled.
Unless full payment is made in next 8 days, then legal action
for the recovery of the debt will be taken without further
notice.
I trust that this action will prove unnecessary and details of
due payments is printed below.
In case of any queries concerning this matter, do not hesitate
to contact our accounting department.
Best Regards,
</field>
</record>
</data>
</odoo>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from . import account_move
from . import followup
from . import followup_partner
from . import partner
from . import settings

View File

@@ -0,0 +1,13 @@
from odoo import api, fields, models, _
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
followup_line_id = fields.Many2one('followup.line', 'Follow-up Level')
followup_date = fields.Date('Latest Follow-up')
result = fields.Float(compute='_get_result', string="Balance Amount")
def _get_result(self):
for aml in self:
aml.result = aml.debit - aml.credit

View File

@@ -0,0 +1,91 @@
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class FollowupFollowup(models.Model):
_name = 'followup.followup'
_description = 'Account Follow-up'
_rec_name = 'name'
name = fields.Char(string="Name", related='company_id.name', readonly=True)
followup_line = fields.One2many('followup.line', 'followup_id', 'Follow-up', copy=True)
company_id = fields.Many2one('res.company', 'Company', required=True, default=lambda self: self.env.company)
_company_uniq = models.Constraint(
'unique(company_id)',
'Only one follow-up per company is allowed',
)
class FollowupLine(models.Model):
_name = 'followup.line'
_description = 'Follow-up Criteria'
_order = 'delay'
def _compute_sequence(self):
delays = [line.delay for line in self.followup_id.followup_line]
delays.sort()
for line in self.followup_id.followup_line:
sequence = delays.index(line.delay)
line.sequence = sequence+1
@api.model
def default_get(self, default_fields):
values = super(FollowupLine, self).default_get(default_fields)
if self.env.ref('om_account_followup.email_template_om_account_followup_default'):
values['email_template_id'] = self.env.ref('om_account_followup.email_template_om_account_followup_default').id
return values
name = fields.Char('Follow-Up Action', required=True)
sequence = fields.Integer('Sequence', compute='_compute_sequence',
store=False,
help="Gives the sequence order when displaying a list of follow-up lines.")
followup_id = fields.Many2one('followup.followup', 'Follow Ups',
required=True, ondelete="cascade")
delay = fields.Integer('Due Days',
help="The number of days after the due date of the "
"invoice to wait before sending the reminder. Could be negative if you want "
"to send a polite alert beforehand.",
required=True)
description = fields.Text('Printed Message', translate=True, default="""
Dear %(partner_name)s,
Exception made if there was a mistake of ours, it seems that the following
amount stays unpaid. Please, take appropriate measures in order to carry out
this payment in the next 8 days.
Would your payment have been carried out after this mail was sent, please
ignore this message. Do not hesitate to contact our accounting department.
Best Regards,
""", )
send_email = fields.Boolean('Send an Email', default=True,
help="When processing, it will send an email")
send_letter = fields.Boolean('Send a Letter', default=True,
help="When processing, it will print a letter")
manual_action = fields.Boolean('Manual Action', default=False,
help="When processing, it will set the "
"manual action to be taken for that customer. ")
manual_action_note = fields.Text('Action To Do')
manual_action_responsible_id = fields.Many2one('res.users',
string='Assign a Responsible', ondelete='set null')
email_template_id = fields.Many2one('mail.template', 'Email Template',
ondelete='set null')
_days_uniq = models.Constraint(
'unique(followup_id, delay)',
'Days of the follow-up levels must be different',
)
@api.constrains('description')
def _check_description(self):
for line in self:
if line.description:
try:
line.description % {'partner_name': '', 'date': '',
'user_signature': '',
'company_name': ''}
except ValidationError:
raise ValidationError(
_('Your description is invalid, use the right legend '
'or %% if you want to use the percent character.'))

View File

@@ -0,0 +1,50 @@
from odoo import api, fields, models, _
from odoo import tools
class FollowupStatByPartner(models.Model):
_name = "followup.stat.by.partner"
_description = "Follow-up Statistics by Partner"
_rec_name = 'partner_id'
_auto = False
def _get_invoice_partner_id(self):
for rec in self:
rec.invoice_partner_id = rec.partner_id.address_get(
adr_pref=['invoice']).get('invoice', rec.partner_id.id)
partner_id = fields.Many2one('res.partner', 'Partner', readonly=True)
date_move = fields.Date('First move', readonly=True)
date_move_last = fields.Date('Last move', readonly=True)
date_followup = fields.Date('Latest follow-up', readonly=True)
max_followup_id = fields.Many2one('followup.line', 'Max Follow Up Level', readonly=True, ondelete="cascade")
balance = fields.Float('Balance', readonly=True)
company_id = fields.Many2one('res.company', 'Company', readonly=True)
invoice_partner_id = fields.Many2one('res.partner', compute='_get_invoice_partner_id', string='Invoice Address')
@api.model
def init(self):
tools.drop_view_if_exists(self.env.cr, 'followup_stat_by_partner')
self.env.cr.execute("""
create view followup_stat_by_partner as (
SELECT
l.partner_id * 10000::bigint + l.company_id as id,
l.partner_id AS partner_id,
min(l.date) AS date_move,
max(l.date) AS date_move_last,
max(l.followup_date) AS date_followup,
max(l.followup_line_id) AS max_followup_id,
sum(l.debit - l.credit) AS balance,
l.company_id as company_id
FROM
account_move_line l
LEFT JOIN account_account a ON (l.account_id = a.id)
WHERE
a.account_type = 'asset_receivable' AND
l.full_reconcile_id is NULL AND
l.partner_id IS NOT NULL
GROUP BY
l.partner_id, l.company_id
)""")

View File

@@ -0,0 +1,408 @@
from functools import reduce
from lxml import etree
from odoo import api, fields, models, _
from datetime import datetime
from odoo.exceptions import ValidationError
from odoo.tools.misc import formatLang
class ResPartner(models.Model):
_inherit = "res.partner"
def fields_view_get(self, view_id=None, view_type='form', toolbar=False,
submenu=False):
res = super(ResPartner, self).fields_view_get(
view_id=view_id, view_type=view_type, toolbar=toolbar,
submenu=submenu)
if view_type == 'form' and self.env.context.get('Followupfirst'):
doc = etree.XML(res['arch'], parser=None, base_url=None)
first_node = doc.xpath("//page[@name='followup_tab']")
root = first_node[0].getparent()
root.insert(0, first_node[0])
res['arch'] = etree.tostring(doc, encoding="utf-8")
return res
def _get_latest(self):
company = self.env.user.company_id
for partner in self:
amls = partner.unreconciled_aml_ids
latest_date = False
latest_level = False
latest_days = False
latest_level_without_lit = False
latest_days_without_lit = False
for aml in amls:
aml_followup = aml.followup_line_id
if (aml.company_id == company) and aml_followup and \
(not latest_days or latest_days < aml_followup.delay):
latest_days = aml_followup.delay
latest_level = aml_followup.id
if (aml.company_id == company) and aml.followup_date and (
not latest_date or latest_date < aml.followup_date):
latest_date = aml.followup_date
if (aml.company_id == company) and \
(aml_followup and (not latest_days_without_lit or
latest_days_without_lit < aml_followup.delay)):
latest_days_without_lit = aml_followup.delay
latest_level_without_lit = aml_followup.id
partner.latest_followup_date = latest_date
partner.latest_followup_level_id = latest_level
partner.latest_followup_level_id_without_lit = latest_level_without_lit
def do_partner_manual_action_dermanord(self, followup_line):
action_text = followup_line.manual_action_note or ''
action_date = self.payment_next_action_date or \
fields.Date.today()
if self.payment_responsible_id:
responsible_id = self.payment_responsible_id.id
else:
p = followup_line.manual_action_responsible_id
responsible_id = p and p.id or False
self.write({'payment_next_action_date': action_date,
'payment_next_action': action_text,
'payment_responsible_id': responsible_id})
def do_partner_manual_action(self, partner_ids):
for partner in self.browse(partner_ids):
followup_without_lit = partner.latest_followup_level_id_without_lit
if partner.payment_next_action:
action_text = \
(partner.payment_next_action or '') + "\n" + \
(followup_without_lit.manual_action_note or '')
else:
action_text = followup_without_lit.manual_action_note or ''
action_date = partner.payment_next_action_date or \
fields.Date.today()
if partner.payment_responsible_id:
responsible_id = partner.payment_responsible_id.id
else:
p = followup_without_lit.manual_action_responsible_id
responsible_id = p and p.id or False
partner.write({'payment_next_action_date': action_date,
'payment_next_action': action_text,
'payment_responsible_id': responsible_id})
def do_partner_print(self, wizard_partner_ids, data):
if not wizard_partner_ids:
return {}
data['partner_ids'] = wizard_partner_ids
datas = {
'ids': wizard_partner_ids,
'model': 'followup.followup',
'form': data
}
return self.env.ref(
'om_account_followup.action_report_followup').report_action(
self, data=datas)
def do_partner_mail(self):
ctx = self.env.context.copy()
ctx['followup'] = True
template = 'om_account_followup.email_template_om_account_followup_default'
unknown_mails = 0
for partner in self:
partners_to_email = [child for child in partner.child_ids if
child.type == 'invoice' and child.email]
if not partners_to_email and partner.email:
partners_to_email = [partner]
if partners_to_email:
level = partner.latest_followup_level_id_without_lit
for partner_to_email in partners_to_email:
if level and level.send_email and \
level.email_template_id and \
level.email_template_id.id:
level.email_template_id.with_context(ctx).send_mail(
partner_to_email.id)
else:
mail_template_id = self.env.ref(template)
mail_template_id.with_context(ctx).send_mail(
partner_to_email.id)
if partner not in partners_to_email:
partner.message_post(body=_(
'Overdue email sent to %s' % ', '.join(
['%s <%s>' % (partner.name, partner.email) for
partner in partners_to_email])))
else:
unknown_mails = unknown_mails + 1
action_text = _("Email not sent because of email address "
"of partner not filled in")
if partner.payment_next_action_date:
payment_action_date = min(
fields.Date.today(),
partner.payment_next_action_date)
else:
payment_action_date = fields.Date.today()
if partner.payment_next_action:
payment_next_action = \
partner.payment_next_action + " \n " + action_text
else:
payment_next_action = action_text
partner.with_context(ctx).write(
{'payment_next_action_date': payment_action_date,
'payment_next_action': payment_next_action})
return unknown_mails
def get_followup_table_html(self):
self.ensure_one()
partner = self.commercial_partner_id
followup_table = ''
if partner.unreconciled_aml_ids:
company = self.env.user.company_id
current_date = fields.Date.today()
report = self.env['report.om_account_followup.report_followup']
final_res = report._lines_get_with_partner(partner, company.id)
for currency_dict in final_res:
currency = currency_dict.get('line', [
{'currency_id': company.currency_id}])[0]['currency_id']
followup_table += '''
<table border="2" width=100%%>
<tr>
<td>''' + _("Invoice Date") + '''</td>
<td>''' + _("Description") + '''</td>
<td>''' + _("Reference") + '''</td>
<td>''' + _("Due Date") + '''</td>
<td>''' + _("Amount") + " (%s)" % (
currency.symbol) + '''</td>
<td>''' + _("Lit.") + '''</td>
</tr>
'''
total = 0
for aml in currency_dict['line']:
total += aml['balance']
strbegin = "<TD>"
strend = "</TD>"
date = aml['date_maturity'] or aml['date']
date = datetime.strptime(date, "%m/%d/%Y").date()
if date <= current_date and aml['balance'] > 0:
strbegin = "<TD><B>"
strend = "</B></TD>"
followup_table += "<TR>" + strbegin + str(aml['date']) + \
strend + strbegin + aml['name'] + \
strend + strbegin + \
(aml['ref'] or '') + strend + \
strbegin + str(date) + strend + \
strbegin + str(aml['balance']) + \
strend + "</TR>"
total = reduce(lambda x, y: x + y['balance'],
currency_dict['line'], 0.00)
total = formatLang(self.env, total, currency_obj=currency)
followup_table += '''<tr> </tr>
</table>
<center>''' + _(
"Amount due") + ''' : %s </center>''' % (total)
return followup_table
def write(self, vals):
if vals.get("payment_responsible_id", False):
for part in self:
if part.payment_responsible_id != \
self.env['res.users'].browse(vals["payment_responsible_id"]):
# Find partner_id of user put as responsible
responsible_partner_id = self.env["res.users"].browse(
vals['payment_responsible_id']).partner_id.id
part.message_post(
body=_("You became responsible to do the next action "
"for the payment follow-up of") +
" <b><a href='#id=" + str(part.id) +
"&view_type=form&model=res.partner'> " + part.name +
" </a></b>",
type='comment',
context=self.env.context,
partner_ids=[responsible_partner_id])
return super(ResPartner, self).write(vals)
def action_done(self):
return self.write({'payment_next_action_date': False,
'payment_next_action': '',
'payment_responsible_id': False})
def do_button_print(self):
self.ensure_one()
company_id = self.env.user.company_id.id
if not self.env['account.move.line'].search(
[('partner_id', '=', self.id),
('account_id.account_type', '=', 'asset_receivable'),
('full_reconcile_id', '=', False),
('company_id', '=', company_id),
'|', ('date_maturity', '=', False),
('date_maturity', '<=', fields.Date.today())]):
raise ValidationError(
_("The partner does not have any accounting entries to "
"print in the overdue report for the current company."))
self.message_post(body=_('Printed overdue payments report'))
self.message_post(body=_('Printed overdue payments report'))
wizard_partner_ids = [self.id * 10000 + company_id]
followup_ids = self.env['followup.followup'].search(
[('company_id', '=', company_id)])
if not followup_ids:
raise ValidationError(_(
"There is no followup plan defined for the current company."))
data = {
'date': fields.date.today(),
'followup_id': followup_ids[0].id,
}
return self.do_partner_print(wizard_partner_ids, data)
def _get_amounts_and_date(self):
company = self.env.user.company_id
current_date = fields.Date.today()
for partner in self:
worst_due_date = False
amount_due = amount_overdue = 0.0
for aml in partner.unreconciled_aml_ids:
if (aml.company_id == company):
date_maturity = aml.date_maturity or aml.date
if not worst_due_date or date_maturity < worst_due_date:
worst_due_date = date_maturity
amount_due += aml.result
if (date_maturity <= current_date):
amount_overdue += aml.result
partner.payment_amount_due = amount_due
partner.payment_amount_overdue = amount_overdue
partner.payment_earliest_due_date = worst_due_date
def _get_followup_overdue_query(self, args, overdue_only=False):
company_id = self.env.user.company_id.id
having_clauses = []
having_values = []
for field, operator, value in args:
if operator in ['=', '!=', '>', '>=', '<', '<=']:
having_clauses.append(f'SUM(bal2) {operator} %s')
having_values.append(value)
else:
raise ValueError(f"Unsupported operator: {operator}")
having_where_clause = ' AND '.join(having_clauses)
overdue_only_str = 'AND date_maturity <= NOW()' if overdue_only else ''
query = ('''
SELECT pid AS partner_id, SUM(bal2) FROM (
SELECT
CASE WHEN bal IS NOT NULL THEN bal ELSE 0.0 END AS bal2,
p.id as pid
FROM (
SELECT
(debit - credit) AS bal,
partner_id
FROM account_move_line l
LEFT JOIN account_account a ON a.id = l.account_id
WHERE a.account_type = 'asset_receivable'
%s AND full_reconcile_id IS NULL
AND l.company_id = %%s
) AS l
RIGHT JOIN res_partner p ON p.id = partner_id
) AS pl
GROUP BY pid HAVING %s
''') % (overdue_only_str, having_where_clause)
params = [company_id] + having_values
return query, params
def _payment_overdue_search(self, operator, operand):
args = [('payment_amount_overdue', operator, operand)]
query, params = self._get_followup_overdue_query(args, overdue_only=True)
self.env.cr.execute(query, params)
res = self.env.cr.fetchall()
if not res:
return [('id', '=', '0')]
return [('id', 'in', [x[0] for x in res])]
def _payment_earliest_date_search(self, operator, operand):
args = [('payment_earliest_due_date', operator, operand)]
company_id = self.env.user.company_id.id
having_where_clause = ' AND '.join(
map(lambda x: "(MIN(l.date_maturity) %s '%%s')" % (x[1]), args))
having_values = [x[2] for x in args]
having_where_clause = having_where_clause % (having_values[0])
query = """SELECT partner_id FROM account_move_line l
LEFT JOIN account_account a ON a.id = l.account_id
WHERE a.account_type = 'asset_receivable'
AND l.company_id = %s
AND l.full_reconcile_id IS NULL
AND partner_id IS NOT NULL GROUP BY partner_id"""
query = query % company_id
if having_where_clause:
query += ' HAVING %s ' % (having_where_clause)
self.env.cr.execute(query)
res = self.env.cr.fetchall()
if not res:
return [('id', '=', '0')]
return [('id', 'in', [x[0] for x in res])]
def _payment_due_search(self, operator, operand):
args = [('payment_amount_due', operator, operand)]
query, params = self._get_followup_overdue_query(args, overdue_only=False)
self.env.cr.execute(query, params)
res = self.env.cr.fetchall()
if not res:
return [('id', '=', '0')]
return [('id', 'in', [x[0] for x in res])]
def _get_partners(self):
partners = set()
for aml in self:
if aml.partner_id:
partners.add(aml.partner_id.id)
return list(partners)
payment_responsible_id = fields.Many2one(
'res.users', ondelete='set null',
string='Follow-up Responsible', tracking=True, copy=False,
help="Optionally you can assign a user to this field, which will make "
"him responsible for the action.")
payment_note = fields.Text(
'Customer Payment Promise', help="Payment Note", copy=False
)
payment_next_action = fields.Text(
'Next Action', copy=False, tracking=True,
help="This is the next action to be taken. It will automatically be "
"set when the partner gets a follow-up level that requires a manual action. "
)
payment_next_action_date = fields.Date(
'Next Action Date', copy=False,
help="This is when the manual follow-up is needed. The date will be "
"set to the current date when the partner gets a follow-up level "
"that requires a manual action. Can be practical to set manually "
"e.g. to see if he keeps his promises."
)
unreconciled_aml_ids = fields.One2many(
'account.move.line', 'partner_id',
domain=[('full_reconcile_id', '=', False), ('account_id.account_type', '=', 'asset_receivable')]
)
latest_followup_date = fields.Date(
compute='_get_latest', string="Latest Follow-up Date", compute_sudo=True,
help="Latest date that the follow-up level of the partner was changed"
)
latest_followup_level_id = fields.Many2one(
'followup.line', compute='_get_latest', compute_sudo=True,
string="Latest Follow-up Level", help="The maximum follow-up level"
)
latest_followup_sequence = fields.Integer(
'Sequence',
help="Gives the sequence order when displaying a list of follow-up lines.", default=0
)
latest_followup_level_id_without_lit = fields.Many2one(
'followup.line', compute='_get_latest', compute_sudo=True,
string="Latest Follow-up Level without litigation",
help="The maximum follow-up level without taking into "
"account the account move lines with litigation")
payment_amount_due = fields.Float(
compute='_get_amounts_and_date',
string="Amount Due", search='_payment_due_search'
)
payment_amount_overdue = fields.Float(
compute='_get_amounts_and_date',
string="Amount Overdue", search='_payment_overdue_search'
)
payment_earliest_due_date = fields.Date(
compute='_get_amounts_and_date', string="Worst Due Date",
search='_payment_earliest_date_search'
)

View File

@@ -0,0 +1,15 @@
from odoo import api, fields, models, _
class AccountConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
def open_followup_level_form(self):
res_ids = self.env['followup.followup'].search([], limit=1)
return {
'type': 'ir.actions.act_window',
'name': 'Follow-up Levels',
'res_model': 'followup.followup',
'res_id': res_ids and res_ids.id or False,
'view_mode': 'form,list',
}

View File

@@ -0,0 +1,2 @@
from . import followup_print
from . import followup_report

View File

@@ -0,0 +1,110 @@
import time
from collections import defaultdict
from odoo.exceptions import ValidationError
from odoo import api, fields, models, _
from odoo.tools import format_date
class ReportFollowup(models.AbstractModel):
_name = 'report.om_account_followup.report_followup'
_description = 'Report Followup'
@api.model
def _get_report_values(self, docids, data=None):
model = self.env['followup.sending.results']
ids = self.env.context.get('active_ids') or False
docs = model.browse(ids)
return {
'docs': docs,
'doc_ids': docids,
'doc_model': model,
'time': time,
'ids_to_objects': self._ids_to_objects,
'getLines': self._lines_get,
'get_text': self._get_text,
'data': data and data['form'] or {}}
def _ids_to_objects(self, ids):
all_lines = []
for line in self.env['followup.stat.by.partner'].browse(ids):
if line not in all_lines:
all_lines.append(line)
return all_lines
def _lines_get(self, stat_by_partner_line):
return self._lines_get_with_partner(stat_by_partner_line.partner_id,
stat_by_partner_line.company_id.id)
def _lines_get_with_partner(self, partner, company_id):
moveline_obj = self.env['account.move.line']
moveline_ids = moveline_obj.search(
[('partner_id', '=', partner.id),
('account_id.account_type', '=', 'asset_receivable'),
('full_reconcile_id', '=', False),
('company_id', '=', company_id),
'|', ('date_maturity', '=', False),
('date_maturity', '<=', fields.Date.today())])
lines_per_currency = defaultdict(list)
total = 0
for line in moveline_ids:
currency = line.currency_id or line.company_id.currency_id
balance = line.debit - line.credit
if currency != line.company_id.currency_id:
balance = line.amount_currency
line_data = {
'name': line.move_id.name,
'ref': line.ref,
'date': format_date(self.env, line.date),
'date_maturity': format_date(self.env, line.date_maturity),
'balance': balance,
'currency_id': currency,
}
total = total + line_data['balance']
lines_per_currency[currency].append(line_data)
return [{'total': total, 'line': lines, 'currency': currency} for
currency, lines in
lines_per_currency.items()]
def _get_text(self, stat_line, followup_id, context=None):
fp_obj = self.env['followup.followup']
fp_line = fp_obj.browse(followup_id).followup_line
if not fp_line:
raise ValidationError(
_("The followup plan defined for the current company does not "
"have any followup action."))
default_text = ''
li_delay = []
for line in fp_line:
if not default_text and line.description:
default_text = line.description
li_delay.append(line.delay)
li_delay.sort(reverse=True)
partner_line_ids = self.env['account.move.line'].search(
[('partner_id', '=', stat_line.partner_id.id),
('full_reconcile_id', '=', False),
('company_id', '=', stat_line.company_id.id),
('debit', '!=', False),
('account_id.account_type', '=', 'asset_receivable'),
('followup_line_id', '!=', False)])
partner_max_delay = 0
partner_max_text = ''
for i in partner_line_ids:
if i.followup_line_id.delay > partner_max_delay and \
i.followup_line_id.description:
partner_max_delay = i.followup_line_id.delay
partner_max_text = i.followup_line_id.description
text = partner_max_delay and partner_max_text or default_text
if text:
lang_obj = self.env['res.lang']
lang_ids = lang_obj.search(
[('code', '=', stat_line.partner_id.lang)], limit=1)
date_format = lang_ids and lang_ids.date_format or '%Y-%m-%d'
text = text % {
'partner_name': stat_line.partner_id.name,
'date': time.strftime(date_format),
'company_name': stat_line.company_id.name,
'user_signature': self.env.user.signature or '',
}
return text

View File

@@ -0,0 +1,47 @@
from odoo import api, fields, models
from odoo import tools
class AccountFollowupStat(models.Model):
_name = "followup.stat"
_description = "Follow-up Statistics"
_rec_name = 'partner_id'
_order = 'date_move'
_auto = False
partner_id = fields.Many2one('res.partner', 'Partner', readonly=True)
date_move = fields.Date('First move', readonly=True)
date_move_last = fields.Date('Last move', readonly=True)
date_followup = fields.Date('Latest followup', readonly=True)
followup_id = fields.Many2one('followup.line', 'Follow Ups', readonly=True, ondelete="cascade")
balance = fields.Float('Balance', readonly=True)
debit = fields.Float('Debit', readonly=True)
credit = fields.Float('Credit', readonly=True)
company_id = fields.Many2one('res.company', 'Company', readonly=True)
@api.model
def init(self):
tools.drop_view_if_exists(self.env.cr, 'followup_stat')
self.env.cr.execute("""
create or replace view followup_stat as (
SELECT
l.id as id,
l.partner_id AS partner_id,
min(l.date) AS date_move,
max(l.date) AS date_move_last,
max(l.followup_date) AS date_followup,
max(l.followup_line_id) AS followup_id,
sum(l.debit) AS debit,
sum(l.credit) AS credit,
sum(l.debit - l.credit) AS balance,
l.company_id AS company_id
FROM
account_move_line l
LEFT JOIN account_account a ON (l.account_id = a.id)
WHERE
a.account_type = 'asset_receivable' AND
l.full_reconcile_id is NULL AND
l.partner_id IS NOT NULL
GROUP BY
l.id, l.partner_id, l.company_id
)""")

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="view_om_account_followup_stat_graph" model="ir.ui.view">
<field name="name">followup.stat.graph</field>
<field name="model">followup.stat</field>
<field name="arch" type="xml">
<graph string="Follow-up lines">
<field name="followup_id" type="row"/>
<field name="date_followup" type="col"/>
<field name="balance" type="measure"/>
</graph>
</field>
</record>
<record id="view_om_account_followup_stat_search" model="ir.ui.view">
<field name="name">followup.stat.search</field>
<field name="model">followup.stat</field>
<field name="arch" type="xml">
<search string="Follow-ups Sent">
<field name="date_move"/>
<field name="date_move_last"/>
<separator/>
<filter string="Not Litigation" name="not_litigation"
help="Including journal entries marked as a litigation"/>
<field name="partner_id"/>
<field name="balance"/>
<group>
<filter string="Partner" name="partner"
context="{'group_by':'partner_id'}"/>
<filter string="Follow-up Level" name="followup_level"
context="{'group_by':'followup_id'}"/>
<filter string="Company" name="company"
groups="base.group_multi_company"
context="{'group_by':'company_id'}"/>
<separator/>
<filter string="Latest Follow-up Month" name="lastest_month"
context="{'group_by':'date_followup:month'}"/>
</group>
</search>
</field>
</record>
<record id="action_followup_stat" model="ir.actions.act_window">
<field name="name">Follow-ups Analysis</field>
<field name="res_model">followup.stat</field>
<field name="view_mode">graph</field>
<field name="context">{'search_default_followup_level':1}</field>
<field name="search_view_id" ref="view_om_account_followup_stat_search"/>
</record>
<menuitem action="action_followup_stat"
id="menu_action_followup_stat_follow"
parent="om_account_followup.menu_finance_followup"
groups="account.group_account_invoice"
name="Follow-ups Analysis"
sequence="20"/>
</data>
</odoo>

View File

@@ -0,0 +1,11 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_followup_followup_line,followup.followup.line,model_followup_line,account.group_account_invoice,1,0,0,0
access_followup_followup_line_manager,followup.followup.line.manager,model_followup_line,account.group_account_manager,1,1,1,1
access_followup_followup_accountant,followup.followup.user,model_followup_followup,account.group_account_invoice,1,0,0,0
access_followup_followup_manager,followup.followup.manager,model_followup_followup,account.group_account_manager,1,1,1,1
access_followup_stat_invoice,followup.stat.invoice,model_followup_stat,account.group_account_invoice,1,1,0,0
access_followup_stat_by_partner_manager,followup.stat.by.partner,model_followup_stat_by_partner,account.group_account_user,1,1,0,0
access_followup_stat_user,followup.stat.user,model_followup_stat,account.group_account_user,1,1,0,0
access_followup_stat_manager,followup.stat.manager,model_followup_stat,account.group_account_manager,1,1,1,1
access_followup_print,access_followup_print,model_followup_print,base.group_user,1,1,1,1
access_followup_sending_results,access_followup_sending_results,model_followup_sending_results,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_followup_followup_line followup.followup.line model_followup_line account.group_account_invoice 1 0 0 0
3 access_followup_followup_line_manager followup.followup.line.manager model_followup_line account.group_account_manager 1 1 1 1
4 access_followup_followup_accountant followup.followup.user model_followup_followup account.group_account_invoice 1 0 0 0
5 access_followup_followup_manager followup.followup.manager model_followup_followup account.group_account_manager 1 1 1 1
6 access_followup_stat_invoice followup.stat.invoice model_followup_stat account.group_account_invoice 1 1 0 0
7 access_followup_stat_by_partner_manager followup.stat.by.partner model_followup_stat_by_partner account.group_account_user 1 1 0 0
8 access_followup_stat_user followup.stat.user model_followup_stat account.group_account_user 1 1 0 0
9 access_followup_stat_manager followup.stat.manager model_followup_stat account.group_account_manager 1 1 1 1
10 access_followup_print access_followup_print model_followup_print base.group_user 1 1 1 1
11 access_followup_sending_results access_followup_sending_results model_followup_sending_results base.group_user 1 1 1 1

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="om_account_followup_comp_rule" model="ir.rule">
<field name="name">Account Follow-up multi company rule</field>
<field name="model_id" ref="model_followup_followup"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),
('company_id','child_of',[user.company_id.id])]</field>
</record>
<record id="om_account_followup_stat_by_partner_comp_rule" model="ir.rule">
<field name="name">Account Follow-up Statistics by Partner Rule</field>
<field ref="model_followup_stat_by_partner" name="model_id"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),
('company_id','child_of',[user.company_id.id])]</field>
</record>
</data>
</odoo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,81 @@
<section class="oe_container oe_dark">
<div class="col-md-12">
<h2 class="oe_slogan" style="font-size: 35px;color:#2C0091"><b>Customer Follow Up Management</b></h2>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan" style="color:olive;">Follow-Up Levels</h2>
<div class="oe_demo oe_picture oe_screenshot">
<img src="follow_up_level.png">
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan" style="color:olive;">Send Follow-Ups</h2>
<div class="oe_demo oe_picture oe_screenshot">
<img src="followup.png">
</div>
</div>
</section>
<br/>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan" style="color:olive;">Manual Follow-Ups</h2>
<div class="oe_demo oe_picture oe_screenshot">
<img src="manual_followup.png">
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan" style="color:olive;">Follow-ups Analysis</h2>
<div class="oe_demo oe_picture oe_screenshot">
<img src="follow_up_analysis.png">
</div>
</div>
</section>
<br/>
<br/>
<br/>
<hr style="width: 100%;height: 4px;background: #2C0091;margin: 0px 0px;">
<hr style="width: 100%;height: 4px;background: #148963;margin: 0px 0px;">
<section class="oe_container oe_dark">
<div class="oe_row ">
<div class="oe_slogan text-center">
<img src="odoo_mates.png"/>
<div style="color:#269900;">
<h3 style="color:#2C0091;font-size: 25px;">If you need any support or want more features, just contact us:</h3><br>
<h3 style="color:#2C0091;font-size: 20px;">Email: <a href="odoomates@gmail.com">odoomates@gmail.com</a> <br></h3>
</div>
<div class="oe_slogan">
<h2>
<a target="_blank" href="https://www.facebook.com/odoomate/" target="new">
<i class="fa fa-facebook-square" style="font-size:38px;"></i>
</a>
<a target="_blank" href="https://twitter.com/odoomates/" target="new">
<i class="fa fa-twitter" style="font-size:38px;"></i>
</a>
<a href="#" target="_blank">
<i class="fa fa-linkedin" style="font-size:38px;"></i>
</a>
<a target="_blank" href="https://www.youtube.com/channel/UCVKlUZP7HAhdQgs-9iTJklQ">
<i class="fa fa-youtube-play" style="font-size:38px;"></i>
</a>
</h2>
</div>
</div>
</div>
</section>
<hr style="width: 100%;height: 4px;background: #148963;margin: 0px 0px;">
<hr style="width: 100%;height: 4px;background: #2C0091;margin: 0px 0px;">

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="view_move_line_reconcile_tree" model="ir.ui.view">
<field name="name">account.move.line.list</field>
<field name="model">account.move.line</field>
<field name="arch" type="xml">
<list string="Journal Items to Reconcile" create="false">
<field name="date"/>
<field name="move_id"/>
<field name="ref"/>
<field name="name"/>
<field name="partner_id"/>
<field name="account_id"/>
<field name="journal_id" invisible="1"/>
<field name="full_reconcile_id"/>
<field name="debit" sum="Total debit"/>
<field name="credit" sum="Total credit"/>
</list>
</field>
</record>
<record id="account_manual_reconcile_action" model="ir.actions.act_window">
<field name="context">{'search_default_unreconciled': 1,'view_mode':True}</field>
<field name="name">Journal Items to Reconcile</field>
<field name="res_model">account.move.line</field>
<field name="view_id" ref="view_move_line_reconcile_tree"/>
<field name="view_mode">list</field>
<field name="help" type="html">
<p>No journal items found.</p>
</field>
</record>
<record id="account_move_line_partner_tree" model="ir.ui.view">
<field name="name">account.move.line.partner.list</field>
<field name="model">account.move.line</field>
<field eval="32" name="priority"/>
<field name="arch" type="xml">
<list editable="bottom" string="Partner Entries">
<field name="date"/>
<field name="move_id"/>
<field name="ref"/>
<field name="name"/>
<field name="partner_id"/>
<field name="company_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
<field name="account_id" options="{'no_open': True, 'no_create': True}"
domain="[('company_ids', 'in', company_id)]" groups="account.group_account_readonly"/>
<field name="followup_line_id"/>
<field name="followup_date"/>
<field name="debit" sum="Total debit"/>
<field name="credit" sum="Total credit"/>
<field name="date_maturity"/>
</list>
</field>
</record>
<record id="view_move_line_form" model="ir.ui.view">
<field name="name">account.move.line.form.followup</field>
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_move_line_form"/>
<field name="arch" type="xml">
<field name="date_maturity" position="after">
<field name="followup_line_id"/>
<field name="followup_date"/>
</field>
</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="om_account_followup_stat_by_partner_search" model="ir.ui.view">
<field name="name">followup.stat.by.partner.search</field>
<field name="model">followup.stat.by.partner</field>
<field name="arch" type="xml">
<search string="Partner to Remind">
<field name="date_followup"/>
<filter string="Balance > 0"
domain="[('balance','&gt;',0)]" icon="terp-dolar"
name="balance_positive"/>
<field name="partner_id"/>
<field name="max_followup_id"/>
<field name="company_id"
groups="base.group_multi_company"/>
</search>
</field>
</record>
<record id="om_account_followup_stat_by_partner_tree" model="ir.ui.view">
<field name="name">followup.stat.by.partner.list</field>
<field name="model">followup.stat.by.partner</field>
<field name="arch" type="xml">
<list string="Partner to Remind">
<field name="partner_id"/>
<field name="balance"/>
<field name="max_followup_id"/>
<field name="date_followup"/>
<field name="date_move_last"/>
<field name="company_id" groups="base.group_multi_company"/>
</list>
</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="view_om_account_followup_followup_line_tree" model="ir.ui.view">
<field name="name">followup.line.list</field>
<field name="model">followup.line</field>
<field name="arch" type="xml">
<list string="Follow-up Steps">
<field name="name"/>
<field name="delay"/>
<field name="send_email"/>
<field name="send_letter"/>
<field name="manual_action"/>
</list>
</field>
</record>
<record id="view_om_account_followup_followup_line_form" model="ir.ui.view">
<field name="name">followup.line.form</field>
<field name="model">followup.line</field>
<field name="arch" type="xml">
<form string="Follow-up Steps">
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name"/>
</h1>
<div class="oe_inline">
After
<field name="delay" class="oe_inline"/>
days overdue, do the following actions:
</div>
<div>
<field name="manual_action" class="oe_inline"/>
<label for="manual_action"/>
</div>
<div>
<field name="send_email" class="oe_inline"/>
<label for="send_email"/>
</div>
<div>
<field name="send_letter" class="oe_inline"/>
<label for="send_letter"/>
</div>
<group string="Manual Action" invisible="not manual_action">
<field name="manual_action_responsible_id"/>
<field name="manual_action_note"/>
</group>
<group string="Send an Email" invisible="not send_email">
<field name="email_template_id"/>
</group>
<group string="Send a Letter or Email"
invisible="not send_email and not send_letter">
<p colspan="2" class="oe_grey">
Write here the introduction in the letter,
according to the level of the follow-up. You can
use the following keywords in the text. Don't
forget to translate in all languages you installed
using to top right icon.
<table>
<tr>
<td t-translation="off">%%(partner_name)s
</td>
<td>: Partner Name</td>
</tr>
<tr>
<td t-translation="off">%%(date)s</td>
<td>: Current Date</td>
</tr>
<tr>
<td t-translation="off">
%%(user_signature)s
</td>
<td>: User Name</td>
</tr>
<tr>
<td t-translation="off">%%(company_name)s
</td>
<td>: User's Company Name</td>
</tr>
</table>
</p>
<field name="description" nolabel="1" colspan="2"/>
</group>
</form>
</field>
</record>
<record id="view_om_account_followup_followup_form" model="ir.ui.view">
<field name="name">followup.followup.form</field>
<field name="model">followup.followup</field>
<field name="arch" type="xml">
<form string="Follow-up">
<h1>
<field name="name"/>
</h1>
<label for="company_id" groups="base.group_multi_company"/>
<field name="company_id" widget="selection"
class="oe_inline"
groups="base.group_multi_company"/>
<p class="oe_grey">
To remind customers of paying their invoices, you can
define different actions depending on how severely
overdue the customer is. These actions are bundled
into follow-up levels that are triggered when the due
date of an invoice has passed a certain
number of days. If there are other overdue invoices for
the
same customer, the actions of the most
overdue invoice will be executed.
</p>
<field name="followup_line"/>
</form>
</field>
</record>
<record id="view_om_account_followup_followup_tree" model="ir.ui.view">
<field name="name">followup.followup.list</field>
<field name="model">followup.followup</field>
<field name="arch" type="xml">
<list string="Follow-up">
<field name="company_id"/>
</list>
</field>
</record>
<record id="view_om_account_followup_filter" model="ir.ui.view">
<field name="name">account.followup.select</field>
<field name="model">followup.followup</field>
<field name="arch" type="xml">
<search string="Search Follow-up">
<field name="company_id" groups="base.group_multi_company"/>
</search>
</field>
</record>
<record id="action_om_account_followup_definition_form" model="ir.actions.act_window">
<field name="name">Follow-up Levels</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">followup.followup</field>
<field name="search_view_id" ref="view_om_account_followup_filter"/>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to define follow-up levels and their related actions.
</p>
<p>
For each step, specify the actions to be taken and delay in
days. It is
possible to use print and e-mail templates to send specific
messages to
the customer.
</p>
</field>
</record>
<record id="view_move_line_reconcile_tree" model="ir.ui.view">
<field name="name">account.move.line.list</field>
<field name="model">account.move.line</field>
<field name="arch" type="xml">
<list string="Journal Items to Reconcile" create="false">
<field name="date"/>
<field name="move_id"/>
<field name="ref"/>
<field name="name"/>
<field name="partner_id"/>
<field name="account_id"/>
<field name="journal_id" invisible="1"/>
<field name="full_reconcile_id"/>
<field name="debit" sum="Total debit"/>
<field name="credit" sum="Total credit"/>
</list>
</field>
</record>
<record id="account_manual_reconcile_action" model="ir.actions.act_window">
<field name="context">{'search_default_unreconciled': 1,'view_mode':True}</field>
<field name="name">Journal Items to Reconcile</field>
<field name="res_model">account.move.line</field>
<field name="view_id" ref="view_move_line_reconcile_tree"/>
<field name="view_mode">list</field>
<field name="help" type="html">
<p>
No journal items found.
</p>
</field>
</record>
<menuitem id="om_account_followup_main_menu"
parent="account.menu_finance_configuration"
name="Follow-up"/>
<menuitem id="om_account_followup_menu"
name="Follow-up Levels"
action="action_om_account_followup_definition_form"
parent="om_account_followup_main_menu" />
<menuitem id="om_account_followup_main_menu"
parent="account.menu_finance_configuration"
name="Follow-up"/>
<menuitem id="om_account_followup_menu"
name="Follow-up Levels"
action="action_om_account_followup_definition_form"
parent="om_account_followup_main_menu"/>
</data>
</odoo>

Some files were not shown because too many files have changed in this diff Show More